예제 #1
0
//++ ------------------------------------------------------------------------------------
// Details:	Retrieve the specified thread's frame information.
// Type:	Method.
// Args:	vCmdData		- (R) A command's information.
//			vThreadIdx		- (R) Thread index.
//			vwrThreadFrames	- (W) Frame data.
// Return:	MIstatus::success - Functional succeeded.
//			MIstatus::failure - Functional failed.
// Throws:	None.
//--
bool CMICmnLLDBDebugSessionInfo::GetThreadFrames( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMICmnMIValueTuple & vwrThreadFrames ) 
{
	lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID( vThreadIdx );
	const uint32_t nFrames = thread.GetNumFrames();
	if( nFrames == 0 )
	{
		vwrThreadFrames = CMICmnMIValueTuple();
		return MIstatus::success;
	}

	CMICmnMIValueTuple miValueTupleAll;
	for( MIuint nLevel = 0; nLevel < nFrames; nLevel++ )
	{
		lldb::SBFrame frame = thread.GetFrameAtIndex( nLevel );
		lldb::addr_t pc = 0;
		CMIUtilString fnName;
		CMIUtilString fileName;
		CMIUtilString path; 
		MIuint nLine = 0;
		if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
			return MIstatus::failure;

		// Function args
		CMICmnMIValueList miValueList( true );
		const MIuint vMaskVarTypes = 0x1000;
		if( !MIResponseFormVariableInfo( frame, vMaskVarTypes, miValueList ) )
			return MIstatus::failure;

		const MIchar * pUnknown = "??";
		if( fnName != pUnknown )
		{
			std::replace( fnName.begin(), fnName.end(), ')', ' ' );
			std::replace( fnName.begin(), fnName.end(), '(', ' ' );
			std::replace( fnName.begin(), fnName.end(), '\'', ' ' );
		}

		const CMIUtilString strLevel( CMIUtilString::Format( "%d", nLevel ) );
		const CMICmnMIValueConst miValueConst( strLevel );
		const CMICmnMIValueResult miValueResult( "level", miValueConst );
		miValueTupleAll.Add( miValueResult );
		
		CMICmnMIValueTuple miValueTuple( miValueResult );
		if( !MIResponseFormFrameInfo( pc, fnName, miValueList.GetString(), fileName, path, nLine, miValueTuple ) )
			return MIstatus::failure;
	}

	vwrThreadFrames = miValueTupleAll;

	return MIstatus::success;
}
예제 #2
0
//++ ------------------------------------------------------------------------------------
// Details: Helper function for CMIDriver::InterpretCommandThisDriver.
//          Convert a CLI command to MI command (just wrap any CLI command
//          into "<tokens>-interpreter-exec command \"<CLI command>\"").
// Type:    Method.
// Args:    vTextLine   - (R) Text data representing a possible command.
// Return:  CMIUtilString   - The original MI command or converted CLI command.
//          MIstatus::failure - Functional failed.
// Throws:  None.
//--
CMIUtilString
CMIDriver::WrapCLICommandIntoMICommand(const CMIUtilString &vTextLine) const
{
    // Tokens contain following digits
    static const CMIUtilString digits("0123456789");

    // Consider an algorithm on the following example:
    // 001-file-exec-and-symbols "/path/to/file"
    //
    // 1. Skip a command token
    // For example:
    // 001-file-exec-and-symbols "/path/to/file"
    // 001target create "/path/to/file"
    //    ^ -- command starts here (in both cases)
    // Also possible case when command not found:
    // 001
    //    ^ -- i.e. only tokens are present (or empty string at all)
    const size_t nCommandOffset = vTextLine.find_first_not_of(digits);

    // 2. Check if command is empty
    // For example:
    // 001-file-exec-and-symbols "/path/to/file"
    // 001target create "/path/to/file"
    //    ^ -- command not empty (in both cases)
    // or:
    // 001
    //    ^ -- command wasn't found
    const bool bIsEmptyCommand = (nCommandOffset == CMIUtilString::npos);

    // 3. Check and exit if it isn't a CLI command
    // For example:
    // 001-file-exec-and-symbols "/path/to/file"
    // 001
    //    ^ -- it isn't CLI command (in both cases)
    // or:
    // 001target create "/path/to/file"
    //    ^ -- it's CLI command
    const bool bIsCliCommand = !bIsEmptyCommand && (vTextLine.at(nCommandOffset) != '-');
    if (!bIsCliCommand)
        return vTextLine;

   // 4. Wrap CLI command to make it MI-compatible
   //
   // 001target create "/path/to/file"
   // ^^^ -- token
   const std::string vToken(vTextLine.begin(), vTextLine.begin() + nCommandOffset);
   // 001target create "/path/to/file"
   //    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- CLI command
   const CMIUtilString vCliCommand(std::string(vTextLine, nCommandOffset).c_str());

   // 5. Escape special characters and embed the command in a string
   // Result: it looks like -- target create \"/path/to/file\".
   const std::string vShieldedCliCommand(vCliCommand.AddSlashes());

   // 6. Turn the CLI command into an MI command, as in:
   // 001-interpreter-exec command "target create \"/path/to/file\""
   // ^^^ -- token
   //    ^^^^^^^^^^^^^^^^^^^^^^^^^^^                               ^ -- wrapper
   //                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- shielded CLI command
   return CMIUtilString::Format("%s-interpreter-exec command \"%s\"",
                                vToken.c_str(), vShieldedCliCommand.c_str());
}