//++ ------------------------------------------------------------------------------------ // 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; }
//++ ------------------------------------------------------------------------------------ // 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()); }