1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
//===-- MICmdCmdTarget.cpp --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//++
// File: MICmdCmdTarget.cpp
//
// Overview: CMICmdCmdTargetSelect implementation.
//
// Environment: Compilers: Visual C++ 12.
// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
// Libraries: See MIReadmetxt.
//
// Copyright: None.
//--
// Third Party Headers:
#include <lldb/API/SBStream.h>
#include <lldb/API/SBCommandInterpreter.h>
#include <lldb/API/SBCommandReturnObject.h>
// In-house headers:
#include "MICmnConfig.h"
#include "MICmdCmdTarget.h"
#include "MICmnMIResultRecord.h"
#include "MICmnMIValueConst.h"
#include "MICmnMIOutOfBandRecord.h"
#include "MICmnLLDBDebugger.h"
#include "MICmnLLDBDebugSessionInfo.h"
#include "MICmdArgContext.h"
#include "MICmdArgValFile.h"
#include "MICmdArgValNumber.h"
#include "MICmdArgValString.h"
#include "MICmdArgValThreadGrp.h"
#include "MICmdArgValOptionLong.h"
#include "MICmdArgValOptionShort.h"
#include "MICmdArgValListOfN.h"
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdTargetSelect constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdTargetSelect::CMICmdCmdTargetSelect( void )
: m_constStrArgNamedType( "type" )
, m_constStrArgNamedParameters( "parameters" )
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "target-select";
// Required by the CMICmdFactory when registering *this command
m_pSelfCreatorFn = &CMICmdCmdTargetSelect::CreateSelf;
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdTargetSelect destructor.
// Type: Overrideable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect( void )
{
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The parses the command line options
// arguments to extract values for each of those arguments.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdTargetSelect::ParseArgs( void )
{
bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedType, true, true )) );
bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedParameters, true, true )) );
CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) );
return MIstatus::failure;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command does work in this function.
// The command is likely to communicate with the LLDB SBDebugger in here.
// Synopsis: -target-select type parameters ...
// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdTargetSelect::Execute( void )
{
CMICMDBASE_GETOPTION( pArgType, String, m_constStrArgNamedType );
CMICMDBASE_GETOPTION( pArgParameters, String, m_constStrArgNamedParameters );
CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
// Check we have a valid target
// Note: target created via 'file-exec-and-symbols' command
if( !rSessionInfo.m_lldbTarget.IsValid() )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_TARGET_CURRENT ), m_cmdData.strMiCmd.c_str() ) );
return MIstatus::failure;
}
// Verify that we are executing remotely
const CMIUtilString & rRemoteType( pArgType->GetValue() );
if( rRemoteType != "remote" )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_TARGET_TYPE ), m_cmdData.strMiCmd.c_str(), rRemoteType.c_str() ) );
return MIstatus::failure;
}
// Create a URL pointing to the remote gdb stub
const CMIUtilString strUrl = CMIUtilString::Format( "connect://%s", pArgParameters->GetValue().c_str() );
// Ask LLDB to collect to the target port
const MIchar * pPlugin( "gdb-remote" );
lldb::SBError error;
lldb::SBProcess process = rSessionInfo.m_lldbTarget.ConnectRemote( rSessionInfo.m_rLlldbListener, strUrl.c_str(), pPlugin, error );
// Verify that we have managed to connect successfully
lldb::SBStream errMsg;
if( !process.IsValid() )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_TARGET_PLUGIN ), m_cmdData.strMiCmd.c_str(), errMsg.GetData() ) );
return MIstatus::failure;
}
if( error.Fail() )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_CONNECT_TO_TARGET ), m_cmdData.strMiCmd.c_str(), errMsg.GetData() ) );
return MIstatus::failure;
}
// Save the process in the session info
// Note: Order is important here since this process handle may be used by CMICmnLLDBDebugHandleEvents
// which can fire when interpreting via HandleCommand() below.
rSessionInfo.m_lldbProcess = process;
// Set the environment path if we were given one
CMIUtilString strWkDir;
if( rSessionInfo.SharedDataRetrieve< CMIUtilString >( rSessionInfo.m_constStrSharedDataKeyWkDir, strWkDir ) )
{
lldb::SBDebugger & rDbgr = rSessionInfo.m_rLldbDebugger;
if( !rDbgr.SetCurrentPlatformSDKRoot( strWkDir.c_str() ) )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_FNFAILED ), m_cmdData.strMiCmd.c_str(), "target-select" ) );
return MIstatus::failure;
}
}
// Set the shared object path if we were given one
CMIUtilString strSolibPath;
if( rSessionInfo.SharedDataRetrieve< CMIUtilString >( rSessionInfo.m_constStrSharedDataSolibPath, strSolibPath ) )
{
lldb::SBDebugger & rDbgr = rSessionInfo.m_rLldbDebugger;
lldb::SBCommandInterpreter cmdIterpreter = rDbgr.GetCommandInterpreter();
CMIUtilString strCmdString = CMIUtilString::Format( "target modules search-paths add . %s", strSolibPath.c_str() );
lldb::SBCommandReturnObject retObj;
cmdIterpreter.HandleCommand( strCmdString.c_str(), retObj, false );
if( !retObj.Succeeded() )
{
SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_FNFAILED ), m_cmdData.strMiCmd.c_str(), "target-select" ) );
return MIstatus::failure;
}
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmdCmdTargetSelect::Acknowledge( void )
{
const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Connected );
m_miResultRecord = miRecordResult;
CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID();
// Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger
// Give the client '=thread-group-started,id="i1"'
m_bHasResultRecordExtra = true;
const CMICmnMIValueConst miValueConst2( "i1" );
const CMICmnMIValueResult miValueResult2( "id", miValueConst2 );
const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) );
const CMICmnMIValueConst miValueConst( strPid );
const CMICmnMIValueResult miValueResult( "pid", miValueConst );
CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2 );
miOutOfBand.Add( miValueResult );
m_miResultRecordExtra = miOutOfBand.GetString();
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Required by the CMICmdFactory when registering *this command. The factory
// calls this function to create an instance of *this command.
// Type: Static method.
// Args: None.
// Return: CMICmdBase * - Pointer to a new command.
// Throws: None.
//--
CMICmdBase * CMICmdCmdTargetSelect::CreateSelf( void )
{
return new CMICmdCmdTargetSelect();
}
|