llvm-project/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEven...

1833 lines
76 KiB
C++
Raw Normal View History

//===-- MICmnLLDBDebuggerHandleEvents.cpp -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Third party headers:
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBUnixSignals.h"
#ifdef _WIN32
#include <io.h> // For the ::_access()
#else
#include <unistd.h> // For the ::access()
#endif // _WIN32
// In-house headers:
#include "MICmnLLDBDebuggerHandleEvents.h"
#include "MICmnResources.h"
#include "MICmnLog.h"
Fix handling of CommandInterpreter's events in lldb-mi Summary: Previously lldb-mi contains a stub for that but it didn't work and all CommanInterpreter's events were ignored. This commit adds a handling of CommandInterpreter's events in lldb-mi. Steps: # Fix CMICmnLLDBDebugger::InitSBListener # Add SBCommandInterpreter::EventIsCommandInterpreterEvent # Exit on lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived All tests pass on OS X. In further we can remove "quit" hack in lldb-mi. Test Plan: # Create start_script file: ``` target create ~/p/hello b main r quit ``` # Run lldb-mi --interpreter # Execute start_script file by following command: ``` -interpreter-exec console "command source start_script" ``` Log: ``` $ bin/lldb-mi --interpreter (gdb) -interpreter-exec console "command source start_script" Executing commands in '/Users/IliaK/p/llvm/build_ninja/start_script'. (lldb) target create ~/p/hello Current executable set to '~/p/hello' (x86_64). (lldb) b main Breakpoint 1: where = hello`main + 29 at hello.cpp:12, address = 0x0000000100000e2d (lldb) r Process 1582 launched: '/Users/IliaK/p/hello' (x86_64) (lldb) quit ^done (gdb) =thread-created,id="1",group-id="i1" =thread-selected,id="1" (gdb) =shlibs-added,shlib-info=[num="1",name="hello",dyld-addr="-",reason="dyld",path="/Users/IliaK/p/hello",loaded_addr="-",dsym-objpath="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello"] ... =shlibs-added,shlib-info=[num="132",name="libDiagnosticMessagesClient.dylib",dyld-addr="0x7fff91705000",reason="dyld",path="/usr/lib/libDiagnosticMessagesClient.dylib",loaded_addr="0x7fff91705000"] (gdb) *stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x100000e2d",func="main",args=[{name="argc",value="1"},{name="argv",value="0x00007fff5fbffc88"}],file="hello.cpp",fullname="/Users/IliaK/p/hello.cpp",line="12"},thread-id="1",stopped-threads="all" (gdb)<press Enter> MI: Program exited OK ``` Reviewers: abidh, clayborg Reviewed By: abidh Subscribers: jingham, lldb-commits, clayborg, abidh Differential Revision: http://reviews.llvm.org/D8382 llvm-svn: 232891
2015-03-21 18:53:37 +08:00
#include "MICmnLLDBDebugger.h"
#include "MICmnLLDBDebugSessionInfo.h"
#include "MICmnMIResultRecord.h"
#include "MICmnMIValueConst.h"
#include "MICmnMIValueList.h"
#include "MICmnMIOutOfBandRecord.h"
#include "MICmnStreamStdout.h"
#include "MICmnStreamStderr.h"
#include "MIUtilDebug.h"
#include "MIDriver.h"
#include "Platform.h" // for PATH_MAX
//++ ------------------------------------------------------------------------------------
// Details: CMICmnLLDBDebuggerHandleEvents constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents()
{
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmnLLDBDebuggerHandleEvents destructor.
// Type: Overridable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents()
{
Shutdown();
}
//++ ------------------------------------------------------------------------------------
2015-07-07 22:04:40 +08:00
// Details: Initialize resources for *this broadcaster object.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::Initialize()
{
m_clientUsageRefCnt++;
if (m_bInitialized)
return MIstatus::success;
m_bInitialized = MIstatus::success;
m_bSignalsInitialized = false;
m_SIGINT = 0;
m_SIGSTOP = 0;
m_SIGSEGV = 0;
m_SIGTRAP = 0;
return m_bInitialized;
}
//++ ------------------------------------------------------------------------------------
2015-07-07 22:04:40 +08:00
// Details: Release resources for *this broadcaster object.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
if (!m_bInitialized)
return MIstatus::success;
m_bInitialized = false;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
2015-07-07 22:04:40 +08:00
// Details: Interpret the event object to ascertain the action to take or information to
// to form and put in a MI Out-of-band record object which is given to stdout.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// vrbHandledEvent - (W) True - event handled, false = not handled.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent)
{
bool bOk = MIstatus::success;
vrbHandledEvent = false;
if (lldb::SBProcess::EventIsProcessEvent(vEvent))
{
vrbHandledEvent = true;
bOk = HandleEventSBProcess(vEvent);
}
else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent))
{
vrbHandledEvent = true;
bOk = HandleEventSBBreakPoint(vEvent);
}
else if (lldb::SBThread::EventIsThreadEvent(vEvent))
{
vrbHandledEvent = true;
bOk = HandleEventSBThread(vEvent);
}
else if (lldb::SBTarget::EventIsTargetEvent(vEvent))
{
vrbHandledEvent = true;
bOk = HandleEventSBTarget(vEvent);
}
Fix handling of CommandInterpreter's events in lldb-mi Summary: Previously lldb-mi contains a stub for that but it didn't work and all CommanInterpreter's events were ignored. This commit adds a handling of CommandInterpreter's events in lldb-mi. Steps: # Fix CMICmnLLDBDebugger::InitSBListener # Add SBCommandInterpreter::EventIsCommandInterpreterEvent # Exit on lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived All tests pass on OS X. In further we can remove "quit" hack in lldb-mi. Test Plan: # Create start_script file: ``` target create ~/p/hello b main r quit ``` # Run lldb-mi --interpreter # Execute start_script file by following command: ``` -interpreter-exec console "command source start_script" ``` Log: ``` $ bin/lldb-mi --interpreter (gdb) -interpreter-exec console "command source start_script" Executing commands in '/Users/IliaK/p/llvm/build_ninja/start_script'. (lldb) target create ~/p/hello Current executable set to '~/p/hello' (x86_64). (lldb) b main Breakpoint 1: where = hello`main + 29 at hello.cpp:12, address = 0x0000000100000e2d (lldb) r Process 1582 launched: '/Users/IliaK/p/hello' (x86_64) (lldb) quit ^done (gdb) =thread-created,id="1",group-id="i1" =thread-selected,id="1" (gdb) =shlibs-added,shlib-info=[num="1",name="hello",dyld-addr="-",reason="dyld",path="/Users/IliaK/p/hello",loaded_addr="-",dsym-objpath="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello"] ... =shlibs-added,shlib-info=[num="132",name="libDiagnosticMessagesClient.dylib",dyld-addr="0x7fff91705000",reason="dyld",path="/usr/lib/libDiagnosticMessagesClient.dylib",loaded_addr="0x7fff91705000"] (gdb) *stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x100000e2d",func="main",args=[{name="argc",value="1"},{name="argv",value="0x00007fff5fbffc88"}],file="hello.cpp",fullname="/Users/IliaK/p/hello.cpp",line="12"},thread-id="1",stopped-threads="all" (gdb)<press Enter> MI: Program exited OK ``` Reviewers: abidh, clayborg Reviewed By: abidh Subscribers: jingham, lldb-commits, clayborg, abidh Differential Revision: http://reviews.llvm.org/D8382 llvm-svn: 232891
2015-03-21 18:53:37 +08:00
else if (lldb::SBCommandInterpreter::EventIsCommandInterpreterEvent(vEvent))
{
vrbHandledEvent = true;
bOk = HandleEventSBCommandInterpreter(vEvent);
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Handle a LLDB SBProcess event.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent)
{
bool bOk = MIstatus::success;
const char *pEventType = "";
const MIuint nEventType = vEvent.GetType();
switch (nEventType)
{
case lldb::SBProcess::eBroadcastBitInterrupt:
pEventType = "eBroadcastBitInterrupt";
break;
case lldb::SBProcess::eBroadcastBitProfileData:
pEventType = "eBroadcastBitProfileData";
break;
case lldb::SBProcess::eBroadcastBitStateChanged:
pEventType = "eBroadcastBitStateChanged";
bOk = HandleProcessEventBroadcastBitStateChanged(vEvent);
break;
case lldb::SBProcess::eBroadcastBitSTDERR:
pEventType = "eBroadcastBitSTDERR";
bOk = GetProcessStderr();
break;
case lldb::SBProcess::eBroadcastBitSTDOUT:
pEventType = "eBroadcastBitSTDOUT";
bOk = GetProcessStdout();
break;
default:
{
const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess", (MIuint)nEventType));
SetErrorDescription(msg);
return MIstatus::failure;
}
}
m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event occurred: %s", pEventType));
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Handle a LLDB SBBreakpoint event.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint(const lldb::SBEvent &vEvent)
{
bool bOk = MIstatus::success;
const char *pEventType = "";
const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(vEvent);
switch (eEvent)
{
case lldb::eBreakpointEventTypeThreadChanged:
pEventType = "eBreakpointEventTypeThreadChanged";
break;
case lldb::eBreakpointEventTypeLocationsRemoved:
pEventType = "eBreakpointEventTypeLocationsRemoved";
break;
case lldb::eBreakpointEventTypeInvalidType:
pEventType = "eBreakpointEventTypeInvalidType";
break;
case lldb::eBreakpointEventTypeLocationsAdded:
pEventType = "eBreakpointEventTypeLocationsAdded";
bOk = HandleEventSBBreakpointLocationsAdded(vEvent);
break;
case lldb::eBreakpointEventTypeAdded:
pEventType = "eBreakpointEventTypeAdded";
bOk = HandleEventSBBreakpointAdded(vEvent);
break;
case lldb::eBreakpointEventTypeRemoved:
pEventType = "eBreakpointEventTypeRemoved";
bOk = HandleEventSBBreakpointCmn(vEvent);
break;
case lldb::eBreakpointEventTypeLocationsResolved:
pEventType = "eBreakpointEventTypeLocationsResolved";
Generate an event when a pending breakpoint binds Summary: This checkin sends an MI event when a module is loaded that causes a pending breakpoint to bind to it's real address in the target. This allows breakpoints to be set before the process is launched, and the target address of the BP to be discovered when the module loads, prior to the breakpoint being hit. Patch from chuckr@microsoft.com Test Plan: I ran the check-lldb target with and without this patch and saw no change. I am unsure of how to write an MI specific test for this because the new event is buried in module load events. Here is an example (the new event is in bold): ``` (gdb) -file-exec-and-symbols a.out ^done (gdb) =shlibs-added,shlib-info=[num="1",name="a.out",dyld-addr="-",reason="dyld",path="/Users/chuckr/llama/llvm/tools/lldb/test/tools/lldb-mi/a.out",loaded_addr="-",dsym-objpath="/Users/chuckr/llama/llvm/tools/lldb/test/tools/lldb-mi/a.out.dSYM/Contents/Resources/DWARF/a.out"] -break-insert -f main.cpp:15 ^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0xffffffffffffffff",func="main",file="main.cpp",fullname="/Users/chuckr/llama/llvm/tools/lldb/test/tools/lldb-mi/main.cpp",line="15",pending=["main.cpp:15"],times="0",original-location="main.cpp:15"} (gdb) =breakpoint-modified,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0xffffffffffffffff",func="main",file="main.cpp",fullname="/Users/chuckr/llama/llvm/tools/lldb/test/tools/lldb-mi/main.cpp",line="15",pending=["main.cpp:15"],times="0",original-location="main.cpp:15"} -exec-run ^running =thread-group-started,id="i1",pid="75620" (gdb) =thread-created,id="1",group-id="i1" =thread-selected,id="1" (gdb) =shlibs-added,shlib-info=[num="2",name="dyld",dyld-addr="0x7fff5fc00000",reason="dyld",path="/usr/lib/dyld",loaded_addr="0x7fff5fc00000"] (gdb) =shlibs-added,shlib-info=[num="3",name="dyld",dyld-addr="0x7fff5fc00000",reason="dyld",path="/usr/lib/dyld",loaded_addr="0x7fff5fc00000"] (gdb) *running,thread-id="all" (gdb) (gdb) =shlibs-added,shlib-info=[num="4",name="libc++.1.dylib",dyld-addr="0x7fff85dd0000",reason="dyld",path="/usr/lib/libc++.1.dylib",loaded_addr="0x7fff85dd0000"] (gdb) =shlibs-added,shlib-info=[num="5",name="libSystem.B.dylib",dyld-addr="0x7fff851ab000",reason="dyld",path="/usr/lib/libSystem.B.dylib",loaded_addr="0x7fff851ab000"] (gdb) =shlibs-added,shlib-info=[num="6",name="libc++abi.dylib",dyld-addr="0x7fff81be8000",reason="dyld",path="/usr/lib/libc++abi.dylib",loaded_addr="0x7fff81be8000"] (gdb) =shlibs-added,shlib-info=[num="7",name="libcache.dylib",dyld-addr="0x7fff8b975000",reason="dyld",path="/usr/lib/system/libcache.dylib",loaded_addr="0x7fff8b975000"] (gdb) =shlibs-added,shlib-info=[num="8",name="libcommonCrypto.dylib",dyld-addr="0x7fff85d14000",reason="dyld",path="/usr/lib/system/libcommonCrypto.dylib",loaded_addr="0x7fff85d14000"] (gdb) =shlibs-added,shlib-info=[num="9",name="libcompiler_rt.dylib",dyld-addr="0x7fff86154000",reason="dyld",path="/usr/lib/system/libcompiler_rt.dylib",loaded_addr="0x7fff86154000"] (gdb) =shlibs-added,shlib-info=[num="10",name="libcopyfile.dylib",dyld-addr="0x7fff81ac7000",reason="dyld",path="/usr/lib/system/libcopyfile.dylib",loaded_addr="0x7fff81ac7000"] (gdb) =shlibs-added,shlib-info=[num="11",name="libcorecrypto.dylib",dyld-addr="0x7fff87d5d000",reason="dyld",path="/usr/lib/system/libcorecrypto.dylib",loaded_addr="0x7fff87d5d000"] (gdb) =shlibs-added,shlib-info=[num="12",name="libdispatch.dylib",dyld-addr="0x7fff8ea8c000",reason="dyld",path="/usr/lib/system/libdispatch.dylib",loaded_addr="0x7fff8ea8c000"] (gdb) =shlibs-added,shlib-info=[num="13",name="libdyld.dylib",dyld-addr="0x7fff89087000",reason="dyld",path="/usr/lib/system/libdyld.dylib",loaded_addr="0x7fff89087000"] (gdb) =shlibs-added,shlib-info=[num="14",name="libkeymgr.dylib",dyld-addr="0x7fff8e818000",reason="dyld",path="/usr/lib/system/libkeymgr.dylib",loaded_addr="0x7fff8e818000"] (gdb) =shlibs-added,shlib-info=[num="15",name="liblaunch.dylib",dyld-addr="0x7fff84936000",reason="dyld",path="/usr/lib/system/liblaunch.dylib",loaded_addr="0x7fff84936000"] (gdb) =shlibs-added,shlib-info=[num="16",name="libmacho.dylib",dyld-addr="0x7fff8534e000",reason="dyld",path="/usr/lib/system/libmacho.dylib",loaded_addr="0x7fff8534e000"] (gdb) =shlibs-added,shlib-info=[num="17",name="libquarantine.dylib",dyld-addr="0x7fff90f97000",reason="dyld",path="/usr/lib/system/libquarantine.dylib",loaded_addr="0x7fff90f97000"] (gdb) =shlibs-added,shlib-info=[num="18",name="libremovefile.dylib",dyld-addr="0x7fff8ccb5000",reason="dyld",path="/usr/lib/system/libremovefile.dylib",loaded_addr="0x7fff8ccb5000"] (gdb) =shlibs-added,shlib-info=[num="19",name="libsystem_asl.dylib",dyld-addr="0x7fff8df67000",reason="dyld",path="/usr/lib/system/libsystem_asl.dylib",loaded_addr="0x7fff8df67000"] (gdb) =shlibs-added,shlib-info=[num="20",name="libsystem_blocks.dylib",dyld-addr="0x7fff8621c000",reason="dyld",path="/usr/lib/system/libsystem_blocks.dylib",loaded_addr="0x7fff8621c000"] (gdb) =shlibs-added,shlib-info=[num="21",name="libsystem_c.dylib",dyld-addr="0x7fff83c0f000",reason="dyld",path="/usr/lib/system/libsystem_c.dylib",loaded_addr="0x7fff83c0f000"] (gdb) =shlibs-added,shlib-info=[num="22",name="libsystem_configuration.dylib",dyld-addr="0x7fff8fd71000",reason="dyld",path="/usr/lib/system/libsystem_configuration.dylib",loaded_addr="0x7fff8fd71000"] (gdb) =shlibs-added,shlib-info=[num="23",name="libsystem_coreservices.dylib",dyld-addr="0x7fff8a028000",reason="dyld",path="/usr/lib/system/libsystem_coreservices.dylib",loaded_addr="0x7fff8a028000"] (gdb) =shlibs-added,shlib-info=[num="24",name="libsystem_coretls.dylib",dyld-addr="0x7fff90996000",reason="dyld",path="/usr/lib/system/libsystem_coretls.dylib",loaded_addr="0x7fff90996000"] (gdb) =shlibs-added,shlib-info=[num="25",name="libsystem_dnssd.dylib",dyld-addr="0x7fff8b71f000",reason="dyld",path="/usr/lib/system/libsystem_dnssd.dylib",loaded_addr="0x7fff8b71f000"] (gdb) =shlibs-added,shlib-info=[num="26",name="libsystem_info.dylib",dyld-addr="0x7fff8b9f2000",reason="dyld",path="/usr/lib/system/libsystem_info.dylib",loaded_addr="0x7fff8b9f2000"] (gdb) =shlibs-added,shlib-info=[num="27",name="libsystem_kernel.dylib",dyld-addr="0x7fff81ad0000",reason="dyld",path="/usr/lib/system/libsystem_kernel.dylib",loaded_addr="0x7fff81ad0000"] (gdb) =shlibs-added,shlib-info=[num="28",name="libsystem_m.dylib",dyld-addr="0x7fff84953000",reason="dyld",path="/usr/lib/system/libsystem_m.dylib",loaded_addr="0x7fff84953000"] (gdb) =shlibs-added,shlib-info=[num="29",name="libsystem_malloc.dylib",dyld-addr="0x7fff887bd000",reason="dyld",path="/usr/lib/system/libsystem_malloc.dylib",loaded_addr="0x7fff887bd000"] (gdb) =shlibs-added,shlib-info=[num="30",name="libsystem_network.dylib",dyld-addr="0x7fff88304000",reason="dyld",path="/usr/lib/system/libsystem_network.dylib",loaded_addr="0x7fff88304000"] (gdb) =shlibs-added,shlib-info=[num="31",name="libsystem_networkextension.dylib",dyld-addr="0x7fff82085000",reason="dyld",path="/usr/lib/system/libsystem_networkextension.dylib",loaded_addr="0x7fff82085000"] (gdb) =shlibs-added,shlib-info=[num="32",name="libsystem_notify.dylib",dyld-addr="0x7fff8eb69000",reason="dyld",path="/usr/lib/system/libsystem_notify.dylib",loaded_addr="0x7fff8eb69000"] (gdb) =shlibs-added,shlib-info=[num="33",name="libsystem_platform.dylib",dyld-addr="0x7fff89ac7000",reason="dyld",path="/usr/lib/system/libsystem_platform.dylib",loaded_addr="0x7fff89ac7000"] (gdb) =shlibs-added,shlib-info=[num="34",name="libsystem_pthread.dylib",dyld-addr="0x7fff83ff8000",reason="dyld",path="/usr/lib/system/libsystem_pthread.dylib",loaded_addr="0x7fff83ff8000"] (gdb) =shlibs-added,shlib-info=[num="35",name="libsystem_sandbox.dylib",dyld-addr="0x7fff89084000",reason="dyld",path="/usr/lib/system/libsystem_sandbox.dylib",loaded_addr="0x7fff89084000"] (gdb) =shlibs-added,shlib-info=[num="36",name="libsystem_secinit.dylib",dyld-addr="0x7fff8e816000",reason="dyld",path="/usr/lib/system/libsystem_secinit.dylib",loaded_addr="0x7fff8e816000"] (gdb) =shlibs-added,shlib-info=[num="37",name="libsystem_stats.dylib",dyld-addr="0x7fff89eaf000",reason="dyld",path="/usr/lib/system/libsystem_stats.dylib",loaded_addr="0x7fff89eaf000"] (gdb) =shlibs-added,shlib-info=[num="38",name="libsystem_trace.dylib",dyld-addr="0x7fff8ead4000",reason="dyld",path="/usr/lib/system/libsystem_trace.dylib",loaded_addr="0x7fff8ead4000"] (gdb) =shlibs-added,shlib-info=[num="39",name="libunc.dylib",dyld-addr="0x7fff8ab27000",reason="dyld",path="/usr/lib/system/libunc.dylib",loaded_addr="0x7fff8ab27000"] (gdb) =shlibs-added,shlib-info=[num="40",name="libunwind.dylib",dyld-addr="0x7fff85cf3000",reason="dyld",path="/usr/lib/system/libunwind.dylib",loaded_addr="0x7fff85cf3000"] (gdb) =shlibs-added,shlib-info=[num="41",name="libxpc.dylib",dyld-addr="0x7fff88896000",reason="dyld",path="/usr/lib/system/libxpc.dylib",loaded_addr="0x7fff88896000"] (gdb) =shlibs-added,shlib-info=[num="42",name="libobjc.A.dylib",dyld-addr="0x7fff84f13000",reason="dyld",path="/usr/lib/libobjc.A.dylib",loaded_addr="0x7fff84f13000"] (gdb) =shlibs-added,shlib-info=[num="43",name="libauto.dylib",dyld-addr="0x7fff85d89000",reason="dyld",path="/usr/lib/libauto.dylib",loaded_addr="0x7fff85d89000"] (gdb) =shlibs-added,shlib-info=[num="44",name="libDiagnosticMessagesClient.dylib",dyld-addr="0x7fff822e1000",reason="dyld",path="/usr/lib/libDiagnosticMessagesClient.dylib",loaded_addr="0x7fff822e1000"] ``` =breakpoint-modified,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x0000000100000f4d",func="main",file="main.cpp",fullname="/Users/chuckr/llama/llvm/tools/lldb/test/tools/lldb-mi/main.cpp",line="15",pending=["main.cpp:15"],times="0",original-location="main.cpp:15"} ``` (gdb) =shlibs-added,shlib-info=[num="45",name="a.out",dyld-addr="0x100000000",reason="dyld",path="/Users/chuckr/llama/llvm/tools/lldb/test/tools/lldb-mi/a.out",loaded_addr="0x100000000",dsym-objpath="/Users/chuckr/llama/llvm/tools/lldb/test/tools/lldb-mi/a.out.dSYM/Contents/Resources/DWARF/a.out"] =shlibs-added,shlib-info=[num="46",name="libc++.1.dylib",dyld-addr="0x7fff85dd0000",reason="dyld",path="/usr/lib/libc++.1.dylib",loaded_addr="0x7fff85dd0000"] =shlibs-added,shlib-info=[num="47",name="libSystem.B.dylib",dyld-addr="0x7fff851ab000",reason="dyld",path="/usr/lib/libSystem.B.dylib",loaded_addr="0x7fff851ab000"] =shlibs-added,shlib-info=[num="48",name="libc++abi.dylib",dyld-addr="0x7fff81be8000",reason="dyld",path="/usr/lib/libc++abi.dylib",loaded_addr="0x7fff81be8000"] =shlibs-added,shlib-info=[num="49",name="libcache.dylib",dyld-addr="0x7fff8b975000",reason="dyld",path="/usr/lib/system/libcache.dylib",loaded_addr="0x7fff8b975000"] =shlibs-added,shlib-info=[num="50",name="libcommonCrypto.dylib",dyld-addr="0x7fff85d14000",reason="dyld",path="/usr/lib/system/libcommonCrypto.dylib",loaded_addr="0x7fff85d14000"] =shlibs-added,shlib-info=[num="51",name="libcompiler_rt.dylib",dyld-addr="0x7fff86154000",reason="dyld",path="/usr/lib/system/libcompiler_rt.dylib",loaded_addr="0x7fff86154000"] =shlibs-added,shlib-info=[num="52",name="libcopyfile.dylib",dyld-addr="0x7fff81ac7000",reason="dyld",path="/usr/lib/system/libcopyfile.dylib",loaded_addr="0x7fff81ac7000"] =shlibs-added,shlib-info=[num="53",name="libcorecrypto.dylib",dyld-addr="0x7fff87d5d000",reason="dyld",path="/usr/lib/system/libcorecrypto.dylib",loaded_addr="0x7fff87d5d000"] =shlibs-added,shlib-info=[num="54",name="libdispatch.dylib",dyld-addr="0x7fff8ea8c000",reason="dyld",path="/usr/lib/system/libdispatch.dylib",loaded_addr="0x7fff8ea8c000"] =shlibs-added,shlib-info=[num="55",name="libdyld.dylib",dyld-addr="0x7fff89087000",reason="dyld",path="/usr/lib/system/libdyld.dylib",loaded_addr="0x7fff89087000"] =shlibs-added,shlib-info=[num="56",name="libkeymgr.dylib",dyld-addr="0x7fff8e818000",reason="dyld",path="/usr/lib/system/libkeymgr.dylib",loaded_addr="0x7fff8e818000"] =shlibs-added,shlib-info=[num="57",name="liblaunch.dylib",dyld-addr="0x7fff84936000",reason="dyld",path="/usr/lib/system/liblaunch.dylib",loaded_addr="0x7fff84936000"] =shlibs-added,shlib-info=[num="58",name="libmacho.dylib",dyld-addr="0x7fff8534e000",reason="dyld",path="/usr/lib/system/libmacho.dylib",loaded_addr="0x7fff8534e000"] =shlibs-added,shlib-info=[num="59",name="libquarantine.dylib",dyld-addr="0x7fff90f97000",reason="dyld",path="/usr/lib/system/libquarantine.dylib",loaded_addr="0x7fff90f97000"] =shlibs-added,shlib-info=[num="60",name="libremovefile.dylib",dyld-addr="0x7fff8ccb5000",reason="dyld",path="/usr/lib/system/libremovefile.dylib",loaded_addr="0x7fff8ccb5000"] =shlibs-added,shlib-info=[num="61",name="libsystem_asl.dylib",dyld-addr="0x7fff8df67000",reason="dyld",path="/usr/lib/system/libsystem_asl.dylib",loaded_addr="0x7fff8df67000"] =shlibs-added,shlib-info=[num="62",name="libsystem_blocks.dylib",dyld-addr="0x7fff8621c000",reason="dyld",path="/usr/lib/system/libsystem_blocks.dylib",loaded_addr="0x7fff8621c000"] =shlibs-added,shlib-info=[num="63",name="libsystem_c.dylib",dyld-addr="0x7fff83c0f000",reason="dyld",path="/usr/lib/system/libsystem_c.dylib",loaded_addr="0x7fff83c0f000"] =shlibs-added,shlib-info=[num="64",name="libsystem_configuration.dylib",dyld-addr="0x7fff8fd71000",reason="dyld",path="/usr/lib/system/libsystem_configuration.dylib",loaded_addr="0x7fff8fd71000"] =shlibs-added,shlib-info=[num="65",name="libsystem_coreservices.dylib",dyld-addr="0x7fff8a028000",reason="dyld",path="/usr/lib/system/libsystem_coreservices.dylib",loaded_addr="0x7fff8a028000"] =shlibs-added,shlib-info=[num="66",name="libsystem_coretls.dylib",dyld-addr="0x7fff90996000",reason="dyld",path="/usr/lib/system/libsystem_coretls.dylib",loaded_addr="0x7fff90996000"] =shlibs-added,shlib-info=[num="67",name="libsystem_dnssd.dylib",dyld-addr="0x7fff8b71f000",reason="dyld",path="/usr/lib/system/libsystem_dnssd.dylib",loaded_addr="0x7fff8b71f000"] =shlibs-added,shlib-info=[num="68",name="libsystem_info.dylib",dyld-addr="0x7fff8b9f2000",reason="dyld",path="/usr/lib/system/libsystem_info.dylib",loaded_addr="0x7fff8b9f2000"] =shlibs-added,shlib-info=[num="69",name="libsystem_kernel.dylib",dyld-addr="0x7fff81ad0000",reason="dyld",path="/usr/lib/system/libsystem_kernel.dylib",loaded_addr="0x7fff81ad0000"] =shlibs-added,shlib-info=[num="70",name="libsystem_m.dylib",dyld-addr="0x7fff84953000",reason="dyld",path="/usr/lib/system/libsystem_m.dylib",loaded_addr="0x7fff84953000"] =shlibs-added,shlib-info=[num="71",name="libsystem_malloc.dylib",dyld-addr="0x7fff887bd000",reason="dyld",path="/usr/lib/system/libsystem_malloc.dylib",loaded_addr="0x7fff887bd000"] =shlibs-added,shlib-info=[num="72",name="libsystem_network.dylib",dyld-addr="0x7fff88304000",reason="dyld",path="/usr/lib/system/libsystem_network.dylib",loaded_addr="0x7fff88304000"] =shlibs-added,shlib-info=[num="73",name="libsystem_networkextension.dylib",dyld-addr="0x7fff82085000",reason="dyld",path="/usr/lib/system/libsystem_networkextension.dylib",loaded_addr="0x7fff82085000"] =shlibs-added,shlib-info=[num="74",name="libsystem_notify.dylib",dyld-addr="0x7fff8eb69000",reason="dyld",path="/usr/lib/system/libsystem_notify.dylib",loaded_addr="0x7fff8eb69000"] =shlibs-added,shlib-info=[num="75",name="libsystem_platform.dylib",dyld-addr="0x7fff89ac7000",reason="dyld",path="/usr/lib/system/libsystem_platform.dylib",loaded_addr="0x7fff89ac7000"] =shlibs-added,shlib-info=[num="76",name="libsystem_pthread.dylib",dyld-addr="0x7fff83ff8000",reason="dyld",path="/usr/lib/system/libsystem_pthread.dylib",loaded_addr="0x7fff83ff8000"] =shlibs-added,shlib-info=[num="77",name="libsystem_sandbox.dylib",dyld-addr="0x7fff89084000",reason="dyld",path="/usr/lib/system/libsystem_sandbox.dylib",loaded_addr="0x7fff89084000"] =shlibs-added,shlib-info=[num="78",name="libsystem_secinit.dylib",dyld-addr="0x7fff8e816000",reason="dyld",path="/usr/lib/system/libsystem_secinit.dylib",loaded_addr="0x7fff8e816000"] =shlibs-added,shlib-info=[num="79",name="libsystem_stats.dylib",dyld-addr="0x7fff89eaf000",reason="dyld",path="/usr/lib/system/libsystem_stats.dylib",loaded_addr="0x7fff89eaf000"] =shlibs-added,shlib-info=[num="80",name="libsystem_trace.dylib",dyld-addr="0x7fff8ead4000",reason="dyld",path="/usr/lib/system/libsystem_trace.dylib",loaded_addr="0x7fff8ead4000"] =shlibs-added,shlib-info=[num="81",name="libunc.dylib",dyld-addr="0x7fff8ab27000",reason="dyld",path="/usr/lib/system/libunc.dylib",loaded_addr="0x7fff8ab27000"] =shlibs-added,shlib-info=[num="82",name="libunwind.dylib",dyld-addr="0x7fff85cf3000",reason="dyld",path="/usr/lib/system/libunwind.dylib",loaded_addr="0x7fff85cf3000"] =shlibs-added,shlib-info=[num="83",name="libxpc.dylib",dyld-addr="0x7fff88896000",reason="dyld",path="/usr/lib/system/libxpc.dylib",loaded_addr="0x7fff88896000"] =shlibs-added,shlib-info=[num="84",name="libobjc.A.dylib",dyld-addr="0x7fff84f13000",reason="dyld",path="/usr/lib/libobjc.A.dylib",loaded_addr="0x7fff84f13000"] =shlibs-added,shlib-info=[num="85",name="libauto.dylib",dyld-addr="0x7fff85d89000",reason="dyld",path="/usr/lib/libauto.dylib",loaded_addr="0x7fff85d89000"] =shlibs-added,shlib-info=[num="86",name="libDiagnosticMessagesClient.dylib",dyld-addr="0x7fff822e1000",reason="dyld",path="/usr/lib/libDiagnosticMessagesClient.dylib",loaded_addr="0x7fff822e1000"] (gdb) *stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x0000000100000f4d",func="main",args=[{name="argc",value="1"},{name="argv",value="0x00007fff5fbffed8"}],file="main.cpp",fullname="/Users/chuckr/llama/llvm/tools/lldb/test/tools/lldb-mi/main.cpp",line="15"},thread-id="1",stopped-threads="all" (gdb) ``` Reviewers: abidh, clayborg, ChuckR, jingham Subscribers: ki.stfu, paulmaybee, lldb-commits Differential Revision: http://reviews.llvm.org/D8847 llvm-svn: 234483
2015-04-09 20:55:13 +08:00
bOk = HandleEventSBBreakpointCmn(vEvent);
break;
case lldb::eBreakpointEventTypeEnabled:
pEventType = "eBreakpointEventTypeEnabled";
bOk = HandleEventSBBreakpointCmn(vEvent);
break;
case lldb::eBreakpointEventTypeDisabled:
pEventType = "eBreakpointEventTypeDisabled";
bOk = HandleEventSBBreakpointCmn(vEvent);
break;
case lldb::eBreakpointEventTypeCommandChanged:
pEventType = "eBreakpointEventTypeCommandChanged";
bOk = HandleEventSBBreakpointCmn(vEvent);
break;
case lldb::eBreakpointEventTypeConditionChanged:
pEventType = "eBreakpointEventTypeConditionChanged";
bOk = HandleEventSBBreakpointCmn(vEvent);
break;
case lldb::eBreakpointEventTypeIgnoreChanged:
pEventType = "eBreakpointEventTypeIgnoreChanged";
bOk = HandleEventSBBreakpointCmn(vEvent);
break;
}
m_pLog->WriteLog(CMIUtilString::Format("##### An SB Breakpoint event occurred: %s", pEventType));
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Handle a LLDB SBBreakpoint event.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent)
{
const MIuint nLoc = lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent(vEvent);
if (nLoc == 0)
return MIstatus::success;
lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
const CMIUtilString plural((nLoc == 1) ? "" : "s");
const CMIUtilString msg(CMIUtilString::Format("%d location%s added to breakpoint %d", nLoc, plural.c_str(), brkPt.GetID()));
return TextToStdout(msg);
}
//++ ------------------------------------------------------------------------------------
// Details: Handle a LLDB SBBreakpoint event.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent)
{
lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
if (!brkPt.IsValid())
return MIstatus::success;
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo))
{
SetErrorDescription(
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointCmn()", brkPt.GetID()));
return MIstatus::failure;
}
// CODETAG_LLDB_BREAKPOINT_CREATION
// This is in a worker thread
// Add more breakpoint information or overwrite existing information
CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
if (!rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec))
{
SetErrorDescription(
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND), "HandleEventSBBreakpointCmn()", brkPt.GetID()));
return MIstatus::failure;
}
sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
sBrkPtInfo.m_strOptThrdGrp = "";
sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
// MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\",
// func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
CMICmnMIValueTuple miValueTuple;
if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
{
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointCmn()"));
return MIstatus::failure;
}
const CMICmnMIValueResult miValueResultC("bkpt", miValueTuple);
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC);
bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Handle a LLDB SBBreakpoint added event.
// Add more breakpoint information or overwrite existing information.
// Normally a break point session info objects exists by now when an MI command
// was issued to insert a break so the retrieval would normally always succeed
// however should a user type "b main" into a console then LLDB will create a
// breakpoint directly, hence no MI command, hence no previous record of the
// breakpoint so RecordBrkPtInfoGet() will fail. We still get the event though
// so need to create a breakpoint info object here and send appropriate MI
// response.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent)
{
lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
if (!brkPt.IsValid())
return MIstatus::success;
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo))
{
SetErrorDescription(
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointAdded()", brkPt.GetID()));
return MIstatus::failure;
}
// CODETAG_LLDB_BREAKPOINT_CREATION
// This is in a worker thread
CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
const bool bBrkPtExistAlready = rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec);
if (bBrkPtExistAlready)
{
// Update breakpoint information object
sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
sBrkPtInfo.m_strOptThrdGrp.clear();
sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
}
else
{
// Create a breakpoint information object
sBrkPtInfo.m_bDisp = brkPt.IsOneShot();
sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
sBrkPtInfo.m_strOptThrdGrp.clear();
sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format("%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine);
sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount();
sBrkPtInfo.m_bPending = false;
const char *pStrCondition = brkPt.GetCondition();
sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false;
sBrkPtInfo.m_strCondition = (pStrCondition != nullptr) ? pStrCondition : "??";
sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false;
sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID();
}
CMICmnMIValueTuple miValueTuple;
if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
{
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointAdded()"));
return MIstatus::failure;
}
bool bOk = MIstatus::success;
if (bBrkPtExistAlready)
{
// MI print
// "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
else
{
// CODETAG_LLDB_BRKPT_ID_MAX
if (brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax)
{
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), "HandleEventSBBreakpointAdded()",
rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id));
return MIstatus::failure;
}
if (!rSessionInfo.RecordBrkPtInfo(brkPt.GetID(), sBrkPtInfo))
{
SetErrorDescription(
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id));
return MIstatus::failure;
}
// MI print
// "=breakpoint-created,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Handle a LLDB SBThread event.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread(const lldb::SBEvent &vEvent)
{
if (!ChkForStateChanges())
return MIstatus::failure;
bool bOk = MIstatus::success;
const char *pEventType = "";
const MIuint nEventType = vEvent.GetType();
switch (nEventType)
{
case lldb::SBThread::eBroadcastBitStackChanged:
pEventType = "eBroadcastBitStackChanged";
bOk = HandleEventSBThreadBitStackChanged(vEvent);
break;
case lldb::SBThread::eBroadcastBitThreadSuspended:
pEventType = "eBroadcastBitThreadSuspended";
bOk = HandleEventSBThreadSuspended(vEvent);
break;
case lldb::SBThread::eBroadcastBitThreadResumed:
pEventType = "eBroadcastBitThreadResumed";
break;
case lldb::SBThread::eBroadcastBitSelectedFrameChanged:
pEventType = "eBroadcastBitSelectedFrameChanged";
break;
case lldb::SBThread::eBroadcastBitThreadSelected:
pEventType = "eBroadcastBitThreadSelected";
break;
default:
{
const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBThread", (MIuint)nEventType));
SetErrorDescription(msg);
return MIstatus::failure;
}
}
m_pLog->WriteLog(CMIUtilString::Format("##### An SBThread event occurred: %s", pEventType));
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Handle a LLDB SBThread event.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent)
{
lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
if (!thread.IsValid())
return MIstatus::success;
const lldb::StopReason eStopReason = thread.GetStopReason();
if (eStopReason != lldb::eStopReasonSignal)
return MIstatus::success;
// MI print "@thread=%d,signal=%lld"
const MIuint64 nId = thread.GetStopReasonDataAtIndex(0);
const CMIUtilString strThread(CMIUtilString::Format("%d", thread.GetThreadID()));
const CMICmnMIValueConst miValueConst(strThread);
const CMICmnMIValueResult miValueResult("thread", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult);
const CMIUtilString strSignal(CMIUtilString::Format("%lld", nId));
const CMICmnMIValueConst miValueConst2(strSignal);
const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
return MiOutOfBandRecordToStdout(miOutOfBandRecord);
}
//++ ------------------------------------------------------------------------------------
// Details: Handle a LLDB SBThread event.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent)
{
lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
if (!thread.IsValid())
return MIstatus::success;
lldb::SBStream streamOut;
const bool bOk = thread.GetStatus(streamOut);
return bOk && TextToStdout(streamOut.GetData());
}
//++ ------------------------------------------------------------------------------------
// Details: Handle a LLDB SBTarget event.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEventSBTarget(const lldb::SBEvent &vEvent)
{
if (!ChkForStateChanges())
return MIstatus::failure;
bool bOk = MIstatus::success;
const char *pEventType = "";
const MIuint nEventType = vEvent.GetType();
switch (nEventType)
{
case lldb::SBTarget::eBroadcastBitBreakpointChanged:
pEventType = "eBroadcastBitBreakpointChanged";
break;
case lldb::SBTarget::eBroadcastBitModulesLoaded:
pEventType = "eBroadcastBitModulesLoaded";
bOk = HandleTargetEventBroadcastBitModulesLoaded(vEvent);
break;
case lldb::SBTarget::eBroadcastBitModulesUnloaded:
pEventType = "eBroadcastBitModulesUnloaded";
bOk = HandleTargetEventBroadcastBitModulesUnloaded(vEvent);
break;
case lldb::SBTarget::eBroadcastBitWatchpointChanged:
pEventType = "eBroadcastBitWatchpointChanged";
break;
case lldb::SBTarget::eBroadcastBitSymbolsLoaded:
pEventType = "eBroadcastBitSymbolsLoaded";
break;
default:
{
const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBTarget", (MIuint)nEventType));
SetErrorDescription(msg);
return MIstatus::failure;
}
}
m_pLog->WriteLog(CMIUtilString::Format("##### An SBTarget event occurred: %s", pEventType));
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Print to stdout "=library-loaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" PRIx64"\""
// Type: Method.
// Args: None.
// Return: MIstatus::success - Function succeeded.
// MIstatus::failure - Function failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleTargetEventBroadcastBitModulesLoaded(const lldb::SBEvent &vEvent)
{
bool bOk = MIstatus::failure;
const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent);
for (MIuint nIndex = 0; nIndex < nSize; ++nIndex)
{
const lldb::SBModule sbModule = lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded);
const bool bWithExtraFields = true;
bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
if (!bOk)
break;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Print to stdout "=library-unloaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" PRIx64"\""
// Type: Method.
// Args: None.
// Return: MIstatus::success - Function succeeded.
// MIstatus::failure - Function failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleTargetEventBroadcastBitModulesUnloaded(const lldb::SBEvent &vEvent)
{
bool bOk = MIstatus::failure;
const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent);
for (MIuint nIndex = 0; nIndex < nSize; ++nIndex)
{
const lldb::SBModule sbModule = lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded);
const bool bWithExtraFields = false;
bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
if (!bOk)
break;
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Build module information for =library-loaded/=library-unloaded: "id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" PRIx64"\""
// Type: Method.
// Args: vwrMiValueList - (W) MI value list object.
// Return: MIstatus::success - Function succeeded.
// MIstatus::failure - Function failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::MiHelpGetModuleInfo(const lldb::SBModule &vModule, const bool vbWithExtraFields,
CMICmnMIOutOfBandRecord &vwrMiOutOfBandRecord)
{
bool bOk = MIstatus::success;
// First, build standard fields:
// Build "id" field
std::unique_ptr<char[]> apPath(new char[PATH_MAX]);
vModule.GetFileSpec().GetPath(apPath.get(), PATH_MAX);
const CMIUtilString strTargetPath(apPath.get());
const CMICmnMIValueConst miValueConst(strTargetPath.AddSlashes());
const CMICmnMIValueResult miValueResult("id", miValueConst);
vwrMiOutOfBandRecord.Add(miValueResult);
// Build "target-name" field
const CMICmnMIValueConst miValueConst2(strTargetPath.AddSlashes());
const CMICmnMIValueResult miValueResult2("target-name", miValueConst2);
vwrMiOutOfBandRecord.Add(miValueResult2);
// Build "host-name" field
vModule.GetPlatformFileSpec().GetPath(apPath.get(), PATH_MAX);
const CMIUtilString strHostPath(apPath.get());
const CMICmnMIValueConst miValueConst3(strHostPath.AddSlashes());
const CMICmnMIValueResult miValueResult3("host-name", miValueConst3);
vwrMiOutOfBandRecord.Add(miValueResult3);
// Then build extra fields if needed:
if (vbWithExtraFields)
{
// Build "symbols-loaded" field
vModule.GetSymbolFileSpec().GetPath(apPath.get(), PATH_MAX);
const CMIUtilString strSymbolsPath(apPath.get());
const bool bSymbolsLoaded = !CMIUtilString::Compare(strHostPath, strSymbolsPath);
const CMICmnMIValueConst miValueConst4(CMIUtilString::Format("%d", bSymbolsLoaded));
const CMICmnMIValueResult miValueResult4("symbols-loaded", miValueConst4);
vwrMiOutOfBandRecord.Add(miValueResult4);
// Build "symbols-path" field
if (bSymbolsLoaded)
{
const CMICmnMIValueConst miValueConst5(strSymbolsPath.AddSlashes());
const CMICmnMIValueResult miValueResult5("symbols-path", miValueConst5);
vwrMiOutOfBandRecord.Add(miValueResult5);
}
// Build "loaded_addr" field
lldb::SBAddress sbAddress(vModule.GetObjectFileHeaderAddress());
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
const lldb::addr_t nLoadAddress(sbAddress.GetLoadAddress(rSessionInfo.GetTarget()));
const CMIUtilString strLoadedAddr(nLoadAddress != LLDB_INVALID_ADDRESS ?
CMIUtilString::Format("0x%016" PRIx64, nLoadAddress) : "-");
const CMICmnMIValueConst miValueConst6(strLoadedAddr);
const CMICmnMIValueResult miValueResult6("loaded_addr", miValueConst6);
vwrMiOutOfBandRecord.Add(miValueResult6);
// Build "size" field
lldb::SBSection sbSection = sbAddress.GetSection();
const CMIUtilString strSize(CMIUtilString::Format("%" PRIu64, sbSection.GetByteSize()));
const CMICmnMIValueConst miValueConst7(strSize);
const CMICmnMIValueResult miValueResult7("size", miValueConst7);
vwrMiOutOfBandRecord.Add(miValueResult7);
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Handle a LLDB SBCommandInterpreter event.
// Type: Method.
// Args: vEvent - (R) An LLDB command interpreter event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent)
{
// This function is not used
// *** This function is under development
const char *pEventType = "";
const MIuint nEventType = vEvent.GetType();
switch (nEventType)
{
case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit:
pEventType = "eBroadcastBitThreadShouldExit";
// ToDo: IOR: Reminder to maybe handle this here
// const MIuint nEventType = event.GetType();
// if (nEventType & lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit)
//{
// m_pClientDriver->SetExitApplicationFlag();
// vrbYesExit = true;
// return MIstatus::success;
//} break;
case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt:
pEventType = "eBroadcastBitResetPrompt";
break;
case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
Fix handling of CommandInterpreter's events in lldb-mi Summary: Previously lldb-mi contains a stub for that but it didn't work and all CommanInterpreter's events were ignored. This commit adds a handling of CommandInterpreter's events in lldb-mi. Steps: # Fix CMICmnLLDBDebugger::InitSBListener # Add SBCommandInterpreter::EventIsCommandInterpreterEvent # Exit on lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived All tests pass on OS X. In further we can remove "quit" hack in lldb-mi. Test Plan: # Create start_script file: ``` target create ~/p/hello b main r quit ``` # Run lldb-mi --interpreter # Execute start_script file by following command: ``` -interpreter-exec console "command source start_script" ``` Log: ``` $ bin/lldb-mi --interpreter (gdb) -interpreter-exec console "command source start_script" Executing commands in '/Users/IliaK/p/llvm/build_ninja/start_script'. (lldb) target create ~/p/hello Current executable set to '~/p/hello' (x86_64). (lldb) b main Breakpoint 1: where = hello`main + 29 at hello.cpp:12, address = 0x0000000100000e2d (lldb) r Process 1582 launched: '/Users/IliaK/p/hello' (x86_64) (lldb) quit ^done (gdb) =thread-created,id="1",group-id="i1" =thread-selected,id="1" (gdb) =shlibs-added,shlib-info=[num="1",name="hello",dyld-addr="-",reason="dyld",path="/Users/IliaK/p/hello",loaded_addr="-",dsym-objpath="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello"] ... =shlibs-added,shlib-info=[num="132",name="libDiagnosticMessagesClient.dylib",dyld-addr="0x7fff91705000",reason="dyld",path="/usr/lib/libDiagnosticMessagesClient.dylib",loaded_addr="0x7fff91705000"] (gdb) *stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x100000e2d",func="main",args=[{name="argc",value="1"},{name="argv",value="0x00007fff5fbffc88"}],file="hello.cpp",fullname="/Users/IliaK/p/hello.cpp",line="12"},thread-id="1",stopped-threads="all" (gdb)<press Enter> MI: Program exited OK ``` Reviewers: abidh, clayborg Reviewed By: abidh Subscribers: jingham, lldb-commits, clayborg, abidh Differential Revision: http://reviews.llvm.org/D8382 llvm-svn: 232891
2015-03-21 18:53:37 +08:00
{
pEventType = "eBroadcastBitQuitCommandReceived";
Fix handling of CommandInterpreter's events in lldb-mi Summary: Previously lldb-mi contains a stub for that but it didn't work and all CommanInterpreter's events were ignored. This commit adds a handling of CommandInterpreter's events in lldb-mi. Steps: # Fix CMICmnLLDBDebugger::InitSBListener # Add SBCommandInterpreter::EventIsCommandInterpreterEvent # Exit on lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived All tests pass on OS X. In further we can remove "quit" hack in lldb-mi. Test Plan: # Create start_script file: ``` target create ~/p/hello b main r quit ``` # Run lldb-mi --interpreter # Execute start_script file by following command: ``` -interpreter-exec console "command source start_script" ``` Log: ``` $ bin/lldb-mi --interpreter (gdb) -interpreter-exec console "command source start_script" Executing commands in '/Users/IliaK/p/llvm/build_ninja/start_script'. (lldb) target create ~/p/hello Current executable set to '~/p/hello' (x86_64). (lldb) b main Breakpoint 1: where = hello`main + 29 at hello.cpp:12, address = 0x0000000100000e2d (lldb) r Process 1582 launched: '/Users/IliaK/p/hello' (x86_64) (lldb) quit ^done (gdb) =thread-created,id="1",group-id="i1" =thread-selected,id="1" (gdb) =shlibs-added,shlib-info=[num="1",name="hello",dyld-addr="-",reason="dyld",path="/Users/IliaK/p/hello",loaded_addr="-",dsym-objpath="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello"] ... =shlibs-added,shlib-info=[num="132",name="libDiagnosticMessagesClient.dylib",dyld-addr="0x7fff91705000",reason="dyld",path="/usr/lib/libDiagnosticMessagesClient.dylib",loaded_addr="0x7fff91705000"] (gdb) *stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x100000e2d",func="main",args=[{name="argc",value="1"},{name="argv",value="0x00007fff5fbffc88"}],file="hello.cpp",fullname="/Users/IliaK/p/hello.cpp",line="12"},thread-id="1",stopped-threads="all" (gdb)<press Enter> MI: Program exited OK ``` Reviewers: abidh, clayborg Reviewed By: abidh Subscribers: jingham, lldb-commits, clayborg, abidh Differential Revision: http://reviews.llvm.org/D8382 llvm-svn: 232891
2015-03-21 18:53:37 +08:00
const bool bForceExit = true;
CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(bForceExit);
break;
Fix handling of CommandInterpreter's events in lldb-mi Summary: Previously lldb-mi contains a stub for that but it didn't work and all CommanInterpreter's events were ignored. This commit adds a handling of CommandInterpreter's events in lldb-mi. Steps: # Fix CMICmnLLDBDebugger::InitSBListener # Add SBCommandInterpreter::EventIsCommandInterpreterEvent # Exit on lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived All tests pass on OS X. In further we can remove "quit" hack in lldb-mi. Test Plan: # Create start_script file: ``` target create ~/p/hello b main r quit ``` # Run lldb-mi --interpreter # Execute start_script file by following command: ``` -interpreter-exec console "command source start_script" ``` Log: ``` $ bin/lldb-mi --interpreter (gdb) -interpreter-exec console "command source start_script" Executing commands in '/Users/IliaK/p/llvm/build_ninja/start_script'. (lldb) target create ~/p/hello Current executable set to '~/p/hello' (x86_64). (lldb) b main Breakpoint 1: where = hello`main + 29 at hello.cpp:12, address = 0x0000000100000e2d (lldb) r Process 1582 launched: '/Users/IliaK/p/hello' (x86_64) (lldb) quit ^done (gdb) =thread-created,id="1",group-id="i1" =thread-selected,id="1" (gdb) =shlibs-added,shlib-info=[num="1",name="hello",dyld-addr="-",reason="dyld",path="/Users/IliaK/p/hello",loaded_addr="-",dsym-objpath="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello"] ... =shlibs-added,shlib-info=[num="132",name="libDiagnosticMessagesClient.dylib",dyld-addr="0x7fff91705000",reason="dyld",path="/usr/lib/libDiagnosticMessagesClient.dylib",loaded_addr="0x7fff91705000"] (gdb) *stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x100000e2d",func="main",args=[{name="argc",value="1"},{name="argv",value="0x00007fff5fbffc88"}],file="hello.cpp",fullname="/Users/IliaK/p/hello.cpp",line="12"},thread-id="1",stopped-threads="all" (gdb)<press Enter> MI: Program exited OK ``` Reviewers: abidh, clayborg Reviewed By: abidh Subscribers: jingham, lldb-commits, clayborg, abidh Differential Revision: http://reviews.llvm.org/D8382 llvm-svn: 232891
2015-03-21 18:53:37 +08:00
}
case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData:
pEventType = "eBroadcastBitAsynchronousOutputData";
break;
case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData:
pEventType = "eBroadcastBitAsynchronousErrorData";
break;
default:
{
const CMIUtilString msg(
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBCommandInterpreter", (MIuint)nEventType));
SetErrorDescription(msg);
return MIstatus::failure;
}
}
m_pLog->WriteLog(CMIUtilString::Format("##### An SBCommandInterpreter event occurred: %s", pEventType));
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Handle SBProcess event eBroadcastBitStateChanged.
// Type: Method.
// Args: vEvent - (R) An LLDB event object.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent)
{
// Make sure the program hasn't been auto-restarted:
if (lldb::SBProcess::GetRestartedFromEvent(vEvent))
return MIstatus::success;
bool bOk = ChkForStateChanges();
bOk = bOk && GetProcessStdout();
bOk = bOk && GetProcessStderr();
if (!bOk)
return MIstatus::failure;
// Something changed in the process; get the event and report the process's current
// status and location
const lldb::StateType eEventState = lldb::SBProcess::GetStateFromEvent(vEvent);
if (eEventState == lldb::eStateInvalid)
return MIstatus::success;
lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(vEvent);
if (!process.IsValid())
{
const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID), "SBProcess",
"HandleProcessEventBroadcastBitStateChanged()"));
SetErrorDescription(msg);
return MIstatus::failure;
}
bool bShouldBrk = true;
const char *pEventType = "";
switch (eEventState)
{
case lldb::eStateUnloaded:
pEventType = "eStateUnloaded";
break;
case lldb::eStateConnected:
pEventType = "eStateConnected";
break;
case lldb::eStateAttaching:
pEventType = "eStateAttaching";
break;
case lldb::eStateLaunching:
pEventType = "eStateLaunching";
break;
case lldb::eStateStopped:
pEventType = "eStateStopped";
bOk = HandleProcessEventStateStopped(vEvent, bShouldBrk);
if (bShouldBrk)
break;
case lldb::eStateCrashed:
case lldb::eStateSuspended:
pEventType = "eStateSuspended";
bOk = HandleProcessEventStateSuspended(vEvent);
break;
case lldb::eStateRunning:
pEventType = "eStateRunning";
bOk = HandleProcessEventStateRunning();
break;
case lldb::eStateStepping:
pEventType = "eStateStepping";
break;
case lldb::eStateDetached:
pEventType = "eStateDetached";
break;
case lldb::eStateExited:
// Don't exit from lldb-mi here. We should be able to re-run target.
pEventType = "eStateExited";
bOk = HandleProcessEventStateExited();
break;
default:
{
const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess BroadcastBitStateChanged",
(MIuint)eEventState));
SetErrorDescription(msg);
return MIstatus::failure;
}
}
// ToDo: Remove when finished coding application
m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType));
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Asynchronous event handler for LLDB Process state suspended.
// Type: Method.
// Args: vEvent - (R) An LLDB event object.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent)
{
bool bOk = MIstatus::success;
lldb::SBDebugger &rDebugger = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger();
lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBTarget target = sbProcess.GetTarget();
if (rDebugger.GetSelectedTarget() == target)
{
if (!UpdateSelectedThread())
return MIstatus::failure;
lldb::SBCommandReturnObject result;
const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand("process status", result, false);
MIunused(status);
bOk = TextToStderr(result.GetError());
bOk = bOk && TextToStdout(result.GetOutput());
}
else
{
lldb::SBStream streamOut;
const MIuint nTargetIndex = rDebugger.GetIndexOfTarget(target);
if (nTargetIndex != UINT_MAX)
streamOut.Printf("Target %d: (", nTargetIndex);
else
streamOut.Printf("Target <unknown index>: (");
target.GetDescription(streamOut, lldb::eDescriptionLevelBrief);
streamOut.Printf(") stopped.\n");
bOk = TextToStdout(streamOut.GetData());
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Print to stdout MI formatted text to indicate process stopped.
// Type: Method.
// Args: vwrbShouldBrk - (W) True = Yes break, false = do not.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(const lldb::SBEvent &vrEvent, bool &vwrbShouldBrk)
{
if (!UpdateSelectedThread())
return MIstatus::failure;
const char *pEventType = "";
bool bOk = MIstatus::success;
lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
const lldb::StopReason eStoppedReason = sbProcess.GetSelectedThread().GetStopReason();
switch (eStoppedReason)
{
case lldb::eStopReasonInvalid:
pEventType = "eStopReasonInvalid";
vwrbShouldBrk = false;
break;
case lldb::eStopReasonNone:
pEventType = "eStopReasonNone";
break;
case lldb::eStopReasonTrace:
pEventType = "eStopReasonTrace";
bOk = HandleProcessEventStopReasonTrace();
break;
case lldb::eStopReasonBreakpoint:
pEventType = "eStopReasonBreakpoint";
bOk = HandleProcessEventStopReasonBreakpoint();
break;
case lldb::eStopReasonWatchpoint:
pEventType = "eStopReasonWatchpoint";
break;
case lldb::eStopReasonSignal:
pEventType = "eStopReasonSignal";
bOk = HandleProcessEventStopSignal(vrEvent);
break;
case lldb::eStopReasonException:
pEventType = "eStopReasonException";
bOk = HandleProcessEventStopException();
break;
case lldb::eStopReasonExec:
pEventType = "eStopReasonExec";
break;
case lldb::eStopReasonPlanComplete:
pEventType = "eStopReasonPlanComplete";
bOk = HandleProcessEventStopReasonTrace();
break;
case lldb::eStopReasonThreadExiting:
pEventType = "eStopReasonThreadExiting";
break;
case lldb::eStopReasonInstrumentation:
pEventType = "eStopReasonInstrumentation";
break;
}
// ToDo: Remove when finished coding application
m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event stop state occurred: %s", pEventType));
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Asynchronous event handler for LLDB Process stop signal.
// Type: Method.
// Args: vrEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(const lldb::SBEvent &vrEvent)
{
bool bOk = MIstatus::success;
InitializeSignals ();
lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
const MIuint64 nStopReason = sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
const bool bInterrupted = lldb::SBProcess::GetInterruptedFromEvent(vrEvent);
if (nStopReason == m_SIGINT || (nStopReason == m_SIGSTOP && bInterrupted))
{
// MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGINT\",signal-meaning=\"Interrupt\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\""
const CMICmnMIValueConst miValueConst("signal-received");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConst2("SIGINT");
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3("Interrupt");
const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
CMICmnMIValueTuple miValueTuple;
bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(CMIUtilString::Format("%" PRIu32, sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
miOutOfBandRecord.Add(miValueResult5);
const CMICmnMIValueConst miValueConst6("all");
const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
miOutOfBandRecord.Add(miValueResult6);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
else if (nStopReason == m_SIGSTOP)
{
// MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSTOP\",signal-meaning=\"Stop\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\""
const CMICmnMIValueConst miValueConst("signal-received");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConst2("SIGSTOP");
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3("Stop");
const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
CMICmnMIValueTuple miValueTuple;
bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(CMIUtilString::Format("%" PRIu32, sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
miOutOfBandRecord.Add(miValueResult5);
const CMICmnMIValueConst miValueConst6("all");
const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
miOutOfBandRecord.Add(miValueResult6);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
else if (nStopReason == m_SIGSEGV)
{
// MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation fault\",thread-id=\"%d\",frame={%s}"
const CMICmnMIValueConst miValueConst("signal-received");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConst2("SIGSEGV");
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3("Segmentation fault");
const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
CMICmnMIValueTuple miValueTuple;
bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
miOutOfBandRecord.Add(miValueResult5);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
// Note no "(gdb)" output here
}
else if (nStopReason == m_SIGTRAP)
{
lldb::SBThread thread = sbProcess.GetSelectedThread();
const MIuint nFrames = thread.GetNumFrames();
if (nFrames > 0)
{
lldb::SBFrame frame = thread.GetFrameAtIndex(0);
const char *pFnName = frame.GetFunctionName();
if (pFnName != nullptr)
{
const CMIUtilString fnName = CMIUtilString(pFnName);
static const CMIUtilString threadCloneFn = CMIUtilString("__pthread_clone");
if (CMIUtilString::Compare(threadCloneFn, fnName))
{
if (sbProcess.IsValid())
sbProcess.Continue();
}
}
}
}
else
{
// MI print "*stopped,reason=\"signal-received\",signal-name=\"%s\",thread-id=\"%d\",stopped-threads=\"all\""
// MI print "*stopped,reason=\"signal-received\",signal=\"%d\",thread-id=\"%d\",stopped-threads=\"all\""
const CMICmnMIValueConst miValueConst("signal-received");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
lldb::SBUnixSignals sbUnixSignals = sbProcess.GetUnixSignals();
const char *pSignal = sbUnixSignals.GetSignalAsCString(nStopReason);
if (pSignal)
{
const CMICmnMIValueConst miValueConst2(pSignal);
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
}
else
{
const CMIUtilString strSignal(CMIUtilString::Format("%" PRIu64, nStopReason));
const CMICmnMIValueConst miValueConst2(strSignal);
const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
}
const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst3(strThreadId);
const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4("all");
const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4);
miOutOfBandRecord.Add(miValueResult4);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Asynchronous event handler for LLDB Process stop exception.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopException()
{
const lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBThread sbThread = sbProcess.GetSelectedThread();
const size_t nStopDescriptionLen = sbThread.GetStopDescription(nullptr, 0);
std::unique_ptr<char[]> apStopDescription(new char[nStopDescriptionLen]);
sbThread.GetStopDescription(apStopDescription.get(), nStopDescriptionLen);
// MI print "*stopped,reason=\"exception-received\",exception=\"%s\",thread-id=\"%d\",stopped-threads=\"all\""
const CMICmnMIValueConst miValueConst("exception-received");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMIUtilString strReason(apStopDescription.get());
const CMICmnMIValueConst miValueConst2(strReason);
const CMICmnMIValueResult miValueResult2("exception", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbThread.GetIndexID()));
const CMICmnMIValueConst miValueConst3(strThreadId);
const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4("all");
const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4);
miOutOfBandRecord.Add(miValueResult4);
bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Form partial MI response in a MI value tuple object.
// Type: Method.
// Args: vwrMiValueTuple - (W) MI value tuple object.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple)
{
CMIUtilString strThreadFrame;
lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBThread thread = sbProcess.GetSelectedThread();
const MIuint nFrame = thread.GetNumFrames();
if (nFrame == 0)
{
// MI print "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\""
const CMICmnMIValueConst miValueConst("??");
const CMICmnMIValueResult miValueResult("addr", miValueConst);
CMICmnMIValueTuple miValueTuple(miValueResult);
const CMICmnMIValueResult miValueResult2("func", miValueConst);
miValueTuple.Add(miValueResult2);
const CMICmnMIValueResult miValueResult4("file", miValueConst);
miValueTuple.Add(miValueResult4);
const CMICmnMIValueResult miValueResult5("fullname", miValueConst);
miValueTuple.Add(miValueResult5);
const CMICmnMIValueResult miValueResult6("line", miValueConst);
miValueTuple.Add(miValueResult6);
vwrMiValueTuple = miValueTuple;
return MIstatus::success;
}
CMICmnMIValueTuple miValueTuple;
Refactor CMICmnLLDBDebuggerHandleEvents/CMICmnLLDBDebugSessionInfo/CMICmnLLDBDebugSessionInfoVarObj (MI) Summary: This patch includes the following changes: # Refactor GetVariableInfo/GetValueStringFormatted/GetValue to use the same code (MI) Also it expands the variable value format for strings (aka char*): was: ``` ^done,name="v4",numchild="1",value="0x0000000100000f56",type="const char *",thread-id="1",has_more="0" ``` now: ``` ^done,name="v4",numchild="1",value="0x0000000100000f56 \"ab\"",type="const char *",thread-id="1",has_more="0" ``` # Expand the variable value format for arrays (according to GDB) For example: was: ``` ^done,name="v3",numchild="2",value="{...}",type="char [2]",thread-id="1",has_more="0" ``` now: ``` ^done,name="v3",numchild="2",value="[2]",type="char [2]",thread-id="1",has_more="0" ``` # Rename MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry_default to test_lldbmi_gdb_show_process_stopatentry (MI) # Fix a comment in MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry (MI) # Refactor CMICmnLLDBUtilSBValue ## Add CMICmnLLDBUtilSBValue::IsPointerType/IsArrayType ## Refactor CMICmnLLDBUtilSBValue::GetValue ## Fix CMICmnLLDBUtilSBValue::IsChildCharType to ignore a number of childs ## Rename CMICmnLLDBUtilSBValue::IsChildCharType to IsFirstChildCharType ## Fix CMICmnLLDBUtilSBValue::GetValueCString to accept char[] # Minor changes in CMICmnLLDBUtilSBValue::GetValue # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo family functions (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2 ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept args # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Add vArgInfo arg to CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo ## Move CMICmnLLDBDebugSessionInfo::GetFrameInfo/MIResponseFormFrameInfo to private namespace # Refactor CMICmnLLDBDebugSessionInfo::GetThreadFrames family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::GetThreadFrames2 ## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept vnMaxDepth # Fix vnMaxDepth arg name in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Merge CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo functions into one # Don't modify fnName in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3 ## Improve -CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept vnMaxDepth # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2 ## Add CMICmnLLDBDebugSessionInfo::ThreadInfoFormat_e enum to specify thread format ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept veThreadInfoFormat ## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo (not needed because veThreadInfoFormat was added) # Move CMICmnLLDBDebugSessionInfo::GetThreadFrames to private namespace (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (MI) ## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e enum to specify frame format ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept veFrameInfoFormat ## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (not needed because veFrameInfoFormat was added) # Remove duplicated level field in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) # Refactor CMICmnLLDBUtilSBValue::GetValue (MI) ## Add CMICmnLLDBUtilSBValue::GetSimpleValue ## Use CMICmnLLDBUtilSBValue::GetSimpleValue in GetVlaue # Fix CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) ## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e::eFrameInfoFormat_AllArgumentsInSimpleForm which is used to get stack-args in simple form (i.e. show {...} for composite types). It can be done by calling MIResponseFormVariableInfo with vnMaxDepth=0. ## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept veFrameInfoFormat ## Remove vnMaxDepth from CMICmnLLDBDebugSessionInfo::GetThreadFrames (we should use veFrameInfoFormat instead) # Refactor CMICmnLLDBUtilSBValue::GetValue to expand composite types (MI) ## Add CMICmnLLDBUtilSBValue::GetCompositeValue to expand composite types ## Add CMICmnLLDBUtilSBValue::m_pComposite to avoid multiple {...} in the code ## Improve CMICmnLLDBUtilSBValue::GetValue to accept vbExpandAggregates option (default=false) ## Clean up CMICmnLLDBDebugSessionInfo::GetVariableInfo to use CMICmnLLDBUtilSBValue::GetValue ## Remove the wrapping into {} in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo ## Fix MiStackTestCase.test_lldbmi_stack_list_locals test to expect result without superfluous space ' ' around the '{' or '}' brackets: was: ``` {name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = { var_d = 30 }} ``` now: ``` {name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = {var_d = 30}} ``` ## Fix vwrValue arg name in CMICmnLLDBUtilSBValue::GetSimpleValue (was vrValue) # Refactor CMICmnLLDBDebugSessionInfo::GetVariableInfo (MI) ## Remove vnMaxDepth/vbIsChildValue/vnDepth args in CMICmnLLDBDebugSessionInfo::GetVariableInfo ## Improve CMICmnLLDBDebugSessionInfo::GetVariableInfo to accept vwrStrValue ## Remove vwrMiValueList arg in CMICmnLLDBDebugSessionInfo::GetVariableInfo (we should use vwrStrValue instead) ## Fix CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo to Escape values was: ``` {name="p",value="0x0000000000000000 """} ``` now: ``` {name="p",value="0x0000000000000000 \"\""} ``` # Refactor CMICmnLLDBUtilSBValue ## Improve CMICmnLLDBUtilSBValue::GetValue to handle PrintExpandAggregates ## Improve CMICmnLLDBUtilSBValue::GetSimpleValue to handle vbHandleArrayType (use it to specify that array should be represented as simple type, i.e. value="[2]") # Add spacing between fields in CMICmnLLDBUtilSBValue::GetCompositeValue (MI) For example: was: ``` ^done,name="var3",numchild="3",value="{i = 3,inner = {l = 3},complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0" ``` now: ``` ^done,name="var3",numchild="3",value="{i = 3, inner = {l = 3}, complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0" ``` # Fix spacing in MiStackTestCase.test_lldbmi_stack_list_locals test (MI) Test Plan: ./dotest.py -v --executable $BUILDDIR/bin/lldb tools/lldb-mi/ Reviewers: abidh Subscribers: lldb-commits, abidh Differential Revision: http://reviews.llvm.org/D8913 llvm-svn: 234476
2015-04-09 19:17:54 +08:00
if (!CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments, miValueTuple))
{
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "MiHelpGetCurrentThreadFrame()"));
return MIstatus::failure;
}
vwrMiValueTuple = miValueTuple;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Asynchronous event handler for LLDB Process stop reason breakpoint.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint()
{
// CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging())
{
const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE),
"HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str()));
return MIstatus::failure;
}
lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
const MIuint64 brkPtId = sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().GetTarget().GetBreakpointAtIndex((MIuint)brkPtId);
return MiStoppedAtBreakPoint(brkPtId, brkPt);
}
//++ ------------------------------------------------------------------------------------
// Details: Form the MI Out-of-band response for stopped reason on hitting a break point.
// Type: Method.
// Args: vBrkPtId - (R) The LLDB break point's ID
// vBrkPt - (R) THe LLDB break point object.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt)
{
bool bOk = MIstatus::success;
lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBThread thread = sbProcess.GetSelectedThread();
const MIuint nFrame = thread.GetNumFrames();
if (nFrame == 0)
{
// MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\""
const CMICmnMIValueConst miValueConst("breakpoint-hit");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConst2("del");
const CMICmnMIValueResult miValueResult2("disp", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
const CMICmnMIValueConst miValueConst3(strBkp);
CMICmnMIValueResult miValueResult3("bkptno", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4("{}");
const CMICmnMIValueResult miValueResult4("frame", miValueConst4);
miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(CMIUtilString::Format("%d", vBrkPt.GetThreadIndex()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
miOutOfBandRecord.Add(miValueResult5);
const CMICmnMIValueConst miValueConst6("all");
const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
miOutOfBandRecord.Add(miValueResult6);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
}
Refactor CMICmnLLDBDebuggerHandleEvents/CMICmnLLDBDebugSessionInfo/CMICmnLLDBDebugSessionInfoVarObj (MI) Summary: This patch includes the following changes: # Refactor GetVariableInfo/GetValueStringFormatted/GetValue to use the same code (MI) Also it expands the variable value format for strings (aka char*): was: ``` ^done,name="v4",numchild="1",value="0x0000000100000f56",type="const char *",thread-id="1",has_more="0" ``` now: ``` ^done,name="v4",numchild="1",value="0x0000000100000f56 \"ab\"",type="const char *",thread-id="1",has_more="0" ``` # Expand the variable value format for arrays (according to GDB) For example: was: ``` ^done,name="v3",numchild="2",value="{...}",type="char [2]",thread-id="1",has_more="0" ``` now: ``` ^done,name="v3",numchild="2",value="[2]",type="char [2]",thread-id="1",has_more="0" ``` # Rename MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry_default to test_lldbmi_gdb_show_process_stopatentry (MI) # Fix a comment in MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry (MI) # Refactor CMICmnLLDBUtilSBValue ## Add CMICmnLLDBUtilSBValue::IsPointerType/IsArrayType ## Refactor CMICmnLLDBUtilSBValue::GetValue ## Fix CMICmnLLDBUtilSBValue::IsChildCharType to ignore a number of childs ## Rename CMICmnLLDBUtilSBValue::IsChildCharType to IsFirstChildCharType ## Fix CMICmnLLDBUtilSBValue::GetValueCString to accept char[] # Minor changes in CMICmnLLDBUtilSBValue::GetValue # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo family functions (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2 ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept args # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Add vArgInfo arg to CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo ## Move CMICmnLLDBDebugSessionInfo::GetFrameInfo/MIResponseFormFrameInfo to private namespace # Refactor CMICmnLLDBDebugSessionInfo::GetThreadFrames family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::GetThreadFrames2 ## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept vnMaxDepth # Fix vnMaxDepth arg name in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Merge CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo functions into one # Don't modify fnName in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3 ## Improve -CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept vnMaxDepth # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2 ## Add CMICmnLLDBDebugSessionInfo::ThreadInfoFormat_e enum to specify thread format ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept veThreadInfoFormat ## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo (not needed because veThreadInfoFormat was added) # Move CMICmnLLDBDebugSessionInfo::GetThreadFrames to private namespace (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (MI) ## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e enum to specify frame format ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept veFrameInfoFormat ## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (not needed because veFrameInfoFormat was added) # Remove duplicated level field in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) # Refactor CMICmnLLDBUtilSBValue::GetValue (MI) ## Add CMICmnLLDBUtilSBValue::GetSimpleValue ## Use CMICmnLLDBUtilSBValue::GetSimpleValue in GetVlaue # Fix CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) ## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e::eFrameInfoFormat_AllArgumentsInSimpleForm which is used to get stack-args in simple form (i.e. show {...} for composite types). It can be done by calling MIResponseFormVariableInfo with vnMaxDepth=0. ## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept veFrameInfoFormat ## Remove vnMaxDepth from CMICmnLLDBDebugSessionInfo::GetThreadFrames (we should use veFrameInfoFormat instead) # Refactor CMICmnLLDBUtilSBValue::GetValue to expand composite types (MI) ## Add CMICmnLLDBUtilSBValue::GetCompositeValue to expand composite types ## Add CMICmnLLDBUtilSBValue::m_pComposite to avoid multiple {...} in the code ## Improve CMICmnLLDBUtilSBValue::GetValue to accept vbExpandAggregates option (default=false) ## Clean up CMICmnLLDBDebugSessionInfo::GetVariableInfo to use CMICmnLLDBUtilSBValue::GetValue ## Remove the wrapping into {} in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo ## Fix MiStackTestCase.test_lldbmi_stack_list_locals test to expect result without superfluous space ' ' around the '{' or '}' brackets: was: ``` {name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = { var_d = 30 }} ``` now: ``` {name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = {var_d = 30}} ``` ## Fix vwrValue arg name in CMICmnLLDBUtilSBValue::GetSimpleValue (was vrValue) # Refactor CMICmnLLDBDebugSessionInfo::GetVariableInfo (MI) ## Remove vnMaxDepth/vbIsChildValue/vnDepth args in CMICmnLLDBDebugSessionInfo::GetVariableInfo ## Improve CMICmnLLDBDebugSessionInfo::GetVariableInfo to accept vwrStrValue ## Remove vwrMiValueList arg in CMICmnLLDBDebugSessionInfo::GetVariableInfo (we should use vwrStrValue instead) ## Fix CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo to Escape values was: ``` {name="p",value="0x0000000000000000 """} ``` now: ``` {name="p",value="0x0000000000000000 \"\""} ``` # Refactor CMICmnLLDBUtilSBValue ## Improve CMICmnLLDBUtilSBValue::GetValue to handle PrintExpandAggregates ## Improve CMICmnLLDBUtilSBValue::GetSimpleValue to handle vbHandleArrayType (use it to specify that array should be represented as simple type, i.e. value="[2]") # Add spacing between fields in CMICmnLLDBUtilSBValue::GetCompositeValue (MI) For example: was: ``` ^done,name="var3",numchild="3",value="{i = 3,inner = {l = 3},complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0" ``` now: ``` ^done,name="var3",numchild="3",value="{i = 3, inner = {l = 3}, complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0" ``` # Fix spacing in MiStackTestCase.test_lldbmi_stack_list_locals test (MI) Test Plan: ./dotest.py -v --executable $BUILDDIR/bin/lldb tools/lldb-mi/ Reviewers: abidh Subscribers: lldb-commits, abidh Differential Revision: http://reviews.llvm.org/D8913 llvm-svn: 234476
2015-04-09 19:17:54 +08:00
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
// MI print
// "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
const CMICmnMIValueConst miValueConst("breakpoint-hit");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConstA("del");
const CMICmnMIValueResult miValueResultA("disp", miValueConstA);
miOutOfBandRecord.Add(miValueResultA);
const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
const CMICmnMIValueConst miValueConstB(strBkp);
CMICmnMIValueResult miValueResultB("bkptno", miValueConstB);
miOutOfBandRecord.Add(miValueResultB);
// frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
if (bOk)
{
CMICmnMIValueTuple miValueTuple;
Refactor CMICmnLLDBDebuggerHandleEvents/CMICmnLLDBDebugSessionInfo/CMICmnLLDBDebugSessionInfoVarObj (MI) Summary: This patch includes the following changes: # Refactor GetVariableInfo/GetValueStringFormatted/GetValue to use the same code (MI) Also it expands the variable value format for strings (aka char*): was: ``` ^done,name="v4",numchild="1",value="0x0000000100000f56",type="const char *",thread-id="1",has_more="0" ``` now: ``` ^done,name="v4",numchild="1",value="0x0000000100000f56 \"ab\"",type="const char *",thread-id="1",has_more="0" ``` # Expand the variable value format for arrays (according to GDB) For example: was: ``` ^done,name="v3",numchild="2",value="{...}",type="char [2]",thread-id="1",has_more="0" ``` now: ``` ^done,name="v3",numchild="2",value="[2]",type="char [2]",thread-id="1",has_more="0" ``` # Rename MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry_default to test_lldbmi_gdb_show_process_stopatentry (MI) # Fix a comment in MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry (MI) # Refactor CMICmnLLDBUtilSBValue ## Add CMICmnLLDBUtilSBValue::IsPointerType/IsArrayType ## Refactor CMICmnLLDBUtilSBValue::GetValue ## Fix CMICmnLLDBUtilSBValue::IsChildCharType to ignore a number of childs ## Rename CMICmnLLDBUtilSBValue::IsChildCharType to IsFirstChildCharType ## Fix CMICmnLLDBUtilSBValue::GetValueCString to accept char[] # Minor changes in CMICmnLLDBUtilSBValue::GetValue # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo family functions (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2 ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept args # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Add vArgInfo arg to CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo ## Move CMICmnLLDBDebugSessionInfo::GetFrameInfo/MIResponseFormFrameInfo to private namespace # Refactor CMICmnLLDBDebugSessionInfo::GetThreadFrames family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::GetThreadFrames2 ## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept vnMaxDepth # Fix vnMaxDepth arg name in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Merge CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo functions into one # Don't modify fnName in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3 ## Improve -CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept vnMaxDepth # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2 ## Add CMICmnLLDBDebugSessionInfo::ThreadInfoFormat_e enum to specify thread format ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept veThreadInfoFormat ## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo (not needed because veThreadInfoFormat was added) # Move CMICmnLLDBDebugSessionInfo::GetThreadFrames to private namespace (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (MI) ## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e enum to specify frame format ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept veFrameInfoFormat ## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (not needed because veFrameInfoFormat was added) # Remove duplicated level field in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) # Refactor CMICmnLLDBUtilSBValue::GetValue (MI) ## Add CMICmnLLDBUtilSBValue::GetSimpleValue ## Use CMICmnLLDBUtilSBValue::GetSimpleValue in GetVlaue # Fix CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) ## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e::eFrameInfoFormat_AllArgumentsInSimpleForm which is used to get stack-args in simple form (i.e. show {...} for composite types). It can be done by calling MIResponseFormVariableInfo with vnMaxDepth=0. ## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept veFrameInfoFormat ## Remove vnMaxDepth from CMICmnLLDBDebugSessionInfo::GetThreadFrames (we should use veFrameInfoFormat instead) # Refactor CMICmnLLDBUtilSBValue::GetValue to expand composite types (MI) ## Add CMICmnLLDBUtilSBValue::GetCompositeValue to expand composite types ## Add CMICmnLLDBUtilSBValue::m_pComposite to avoid multiple {...} in the code ## Improve CMICmnLLDBUtilSBValue::GetValue to accept vbExpandAggregates option (default=false) ## Clean up CMICmnLLDBDebugSessionInfo::GetVariableInfo to use CMICmnLLDBUtilSBValue::GetValue ## Remove the wrapping into {} in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo ## Fix MiStackTestCase.test_lldbmi_stack_list_locals test to expect result without superfluous space ' ' around the '{' or '}' brackets: was: ``` {name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = { var_d = 30 }} ``` now: ``` {name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = {var_d = 30}} ``` ## Fix vwrValue arg name in CMICmnLLDBUtilSBValue::GetSimpleValue (was vrValue) # Refactor CMICmnLLDBDebugSessionInfo::GetVariableInfo (MI) ## Remove vnMaxDepth/vbIsChildValue/vnDepth args in CMICmnLLDBDebugSessionInfo::GetVariableInfo ## Improve CMICmnLLDBDebugSessionInfo::GetVariableInfo to accept vwrStrValue ## Remove vwrMiValueList arg in CMICmnLLDBDebugSessionInfo::GetVariableInfo (we should use vwrStrValue instead) ## Fix CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo to Escape values was: ``` {name="p",value="0x0000000000000000 """} ``` now: ``` {name="p",value="0x0000000000000000 \"\""} ``` # Refactor CMICmnLLDBUtilSBValue ## Improve CMICmnLLDBUtilSBValue::GetValue to handle PrintExpandAggregates ## Improve CMICmnLLDBUtilSBValue::GetSimpleValue to handle vbHandleArrayType (use it to specify that array should be represented as simple type, i.e. value="[2]") # Add spacing between fields in CMICmnLLDBUtilSBValue::GetCompositeValue (MI) For example: was: ``` ^done,name="var3",numchild="3",value="{i = 3,inner = {l = 3},complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0" ``` now: ``` ^done,name="var3",numchild="3",value="{i = 3, inner = {l = 3}, complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0" ``` # Fix spacing in MiStackTestCase.test_lldbmi_stack_list_locals test (MI) Test Plan: ./dotest.py -v --executable $BUILDDIR/bin/lldb tools/lldb-mi/ Reviewers: abidh Subscribers: lldb-commits, abidh Differential Revision: http://reviews.llvm.org/D8913 llvm-svn: 234476
2015-04-09 19:17:54 +08:00
bOk = bOk && rSessionInfo.MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, miValueTuple);
const CMICmnMIValueResult miValueResult8("frame", miValueTuple);
miOutOfBandRecord.Add(miValueResult8);
}
// Add to MI thread-id=\"%d\",stopped-threads=\"all\"
if (bOk)
{
const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
const CMICmnMIValueConst miValueConst8(strThreadId);
const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
miOutOfBandRecord.Add(miValueResult8);
}
if (bOk)
{
const CMICmnMIValueConst miValueConst9("all");
const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
miOutOfBandRecord.Add(miValueResult9);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Asynchronous event handler for LLDB Process stop reason trace.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace()
{
bool bOk = true;
lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBThread thread = sbProcess.GetSelectedThread();
const MIuint nFrame = thread.GetNumFrames();
if (nFrame == 0)
{
// MI print "*stopped,reason=\"trace\",stopped-threads=\"all\""
const CMICmnMIValueConst miValueConst("trace");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConst2("all");
const CMICmnMIValueResult miValueResult2("stopped-threads", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
}
Refactor CMICmnLLDBDebuggerHandleEvents/CMICmnLLDBDebugSessionInfo/CMICmnLLDBDebugSessionInfoVarObj (MI) Summary: This patch includes the following changes: # Refactor GetVariableInfo/GetValueStringFormatted/GetValue to use the same code (MI) Also it expands the variable value format for strings (aka char*): was: ``` ^done,name="v4",numchild="1",value="0x0000000100000f56",type="const char *",thread-id="1",has_more="0" ``` now: ``` ^done,name="v4",numchild="1",value="0x0000000100000f56 \"ab\"",type="const char *",thread-id="1",has_more="0" ``` # Expand the variable value format for arrays (according to GDB) For example: was: ``` ^done,name="v3",numchild="2",value="{...}",type="char [2]",thread-id="1",has_more="0" ``` now: ``` ^done,name="v3",numchild="2",value="[2]",type="char [2]",thread-id="1",has_more="0" ``` # Rename MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry_default to test_lldbmi_gdb_show_process_stopatentry (MI) # Fix a comment in MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry (MI) # Refactor CMICmnLLDBUtilSBValue ## Add CMICmnLLDBUtilSBValue::IsPointerType/IsArrayType ## Refactor CMICmnLLDBUtilSBValue::GetValue ## Fix CMICmnLLDBUtilSBValue::IsChildCharType to ignore a number of childs ## Rename CMICmnLLDBUtilSBValue::IsChildCharType to IsFirstChildCharType ## Fix CMICmnLLDBUtilSBValue::GetValueCString to accept char[] # Minor changes in CMICmnLLDBUtilSBValue::GetValue # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo family functions (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2 ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept args # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Add vArgInfo arg to CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo ## Move CMICmnLLDBDebugSessionInfo::GetFrameInfo/MIResponseFormFrameInfo to private namespace # Refactor CMICmnLLDBDebugSessionInfo::GetThreadFrames family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::GetThreadFrames2 ## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept vnMaxDepth # Fix vnMaxDepth arg name in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Merge CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo functions into one # Don't modify fnName in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3 ## Improve -CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept vnMaxDepth # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2 ## Add CMICmnLLDBDebugSessionInfo::ThreadInfoFormat_e enum to specify thread format ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept veThreadInfoFormat ## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo (not needed because veThreadInfoFormat was added) # Move CMICmnLLDBDebugSessionInfo::GetThreadFrames to private namespace (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (MI) ## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e enum to specify frame format ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept veFrameInfoFormat ## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (not needed because veFrameInfoFormat was added) # Remove duplicated level field in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) # Refactor CMICmnLLDBUtilSBValue::GetValue (MI) ## Add CMICmnLLDBUtilSBValue::GetSimpleValue ## Use CMICmnLLDBUtilSBValue::GetSimpleValue in GetVlaue # Fix CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) ## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e::eFrameInfoFormat_AllArgumentsInSimpleForm which is used to get stack-args in simple form (i.e. show {...} for composite types). It can be done by calling MIResponseFormVariableInfo with vnMaxDepth=0. ## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept veFrameInfoFormat ## Remove vnMaxDepth from CMICmnLLDBDebugSessionInfo::GetThreadFrames (we should use veFrameInfoFormat instead) # Refactor CMICmnLLDBUtilSBValue::GetValue to expand composite types (MI) ## Add CMICmnLLDBUtilSBValue::GetCompositeValue to expand composite types ## Add CMICmnLLDBUtilSBValue::m_pComposite to avoid multiple {...} in the code ## Improve CMICmnLLDBUtilSBValue::GetValue to accept vbExpandAggregates option (default=false) ## Clean up CMICmnLLDBDebugSessionInfo::GetVariableInfo to use CMICmnLLDBUtilSBValue::GetValue ## Remove the wrapping into {} in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo ## Fix MiStackTestCase.test_lldbmi_stack_list_locals test to expect result without superfluous space ' ' around the '{' or '}' brackets: was: ``` {name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = { var_d = 30 }} ``` now: ``` {name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = {var_d = 30}} ``` ## Fix vwrValue arg name in CMICmnLLDBUtilSBValue::GetSimpleValue (was vrValue) # Refactor CMICmnLLDBDebugSessionInfo::GetVariableInfo (MI) ## Remove vnMaxDepth/vbIsChildValue/vnDepth args in CMICmnLLDBDebugSessionInfo::GetVariableInfo ## Improve CMICmnLLDBDebugSessionInfo::GetVariableInfo to accept vwrStrValue ## Remove vwrMiValueList arg in CMICmnLLDBDebugSessionInfo::GetVariableInfo (we should use vwrStrValue instead) ## Fix CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo to Escape values was: ``` {name="p",value="0x0000000000000000 """} ``` now: ``` {name="p",value="0x0000000000000000 \"\""} ``` # Refactor CMICmnLLDBUtilSBValue ## Improve CMICmnLLDBUtilSBValue::GetValue to handle PrintExpandAggregates ## Improve CMICmnLLDBUtilSBValue::GetSimpleValue to handle vbHandleArrayType (use it to specify that array should be represented as simple type, i.e. value="[2]") # Add spacing between fields in CMICmnLLDBUtilSBValue::GetCompositeValue (MI) For example: was: ``` ^done,name="var3",numchild="3",value="{i = 3,inner = {l = 3},complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0" ``` now: ``` ^done,name="var3",numchild="3",value="{i = 3, inner = {l = 3}, complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0" ``` # Fix spacing in MiStackTestCase.test_lldbmi_stack_list_locals test (MI) Test Plan: ./dotest.py -v --executable $BUILDDIR/bin/lldb tools/lldb-mi/ Reviewers: abidh Subscribers: lldb-commits, abidh Differential Revision: http://reviews.llvm.org/D8913 llvm-svn: 234476
2015-04-09 19:17:54 +08:00
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
// MI print
// "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
// Function args
CMICmnMIValueTuple miValueTuple;
Refactor CMICmnLLDBDebuggerHandleEvents/CMICmnLLDBDebugSessionInfo/CMICmnLLDBDebugSessionInfoVarObj (MI) Summary: This patch includes the following changes: # Refactor GetVariableInfo/GetValueStringFormatted/GetValue to use the same code (MI) Also it expands the variable value format for strings (aka char*): was: ``` ^done,name="v4",numchild="1",value="0x0000000100000f56",type="const char *",thread-id="1",has_more="0" ``` now: ``` ^done,name="v4",numchild="1",value="0x0000000100000f56 \"ab\"",type="const char *",thread-id="1",has_more="0" ``` # Expand the variable value format for arrays (according to GDB) For example: was: ``` ^done,name="v3",numchild="2",value="{...}",type="char [2]",thread-id="1",has_more="0" ``` now: ``` ^done,name="v3",numchild="2",value="[2]",type="char [2]",thread-id="1",has_more="0" ``` # Rename MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry_default to test_lldbmi_gdb_show_process_stopatentry (MI) # Fix a comment in MiGdbSetShowTestCase.test_lldbmi_gdb_show_process_stopatentry (MI) # Refactor CMICmnLLDBUtilSBValue ## Add CMICmnLLDBUtilSBValue::IsPointerType/IsArrayType ## Refactor CMICmnLLDBUtilSBValue::GetValue ## Fix CMICmnLLDBUtilSBValue::IsChildCharType to ignore a number of childs ## Rename CMICmnLLDBUtilSBValue::IsChildCharType to IsFirstChildCharType ## Fix CMICmnLLDBUtilSBValue::GetValueCString to accept char[] # Minor changes in CMICmnLLDBUtilSBValue::GetValue # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo family functions (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2 ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept args # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Add vArgInfo arg to CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo ## Move CMICmnLLDBDebugSessionInfo::GetFrameInfo/MIResponseFormFrameInfo to private namespace # Refactor CMICmnLLDBDebugSessionInfo::GetThreadFrames family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::GetThreadFrames2 ## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept vnMaxDepth # Fix vnMaxDepth arg name in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo family functions (MI) ## Merge CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo functions into one # Don't modify fnName in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3 ## Improve -CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept vnMaxDepth # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo family functions (MI) ## Remove CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2 ## Add CMICmnLLDBDebugSessionInfo::ThreadInfoFormat_e enum to specify thread format ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo to accept veThreadInfoFormat ## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo (not needed because veThreadInfoFormat was added) # Move CMICmnLLDBDebugSessionInfo::GetThreadFrames to private namespace (MI) # Refactor CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (MI) ## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e enum to specify frame format ## Improve CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo to accept veFrameInfoFormat ## Remove vnMaxDepth arg in CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo (not needed because veFrameInfoFormat was added) # Remove duplicated level field in CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) # Refactor CMICmnLLDBUtilSBValue::GetValue (MI) ## Add CMICmnLLDBUtilSBValue::GetSimpleValue ## Use CMICmnLLDBUtilSBValue::GetSimpleValue in GetVlaue # Fix CMICmnLLDBDebugSessionInfo::GetThreadFrames (MI) ## Add CMICmnLLDBDebugSessionInfo::FrameInfoFormat_e::eFrameInfoFormat_AllArgumentsInSimpleForm which is used to get stack-args in simple form (i.e. show {...} for composite types). It can be done by calling MIResponseFormVariableInfo with vnMaxDepth=0. ## Improve CMICmnLLDBDebugSessionInfo::GetThreadFrames to accept veFrameInfoFormat ## Remove vnMaxDepth from CMICmnLLDBDebugSessionInfo::GetThreadFrames (we should use veFrameInfoFormat instead) # Refactor CMICmnLLDBUtilSBValue::GetValue to expand composite types (MI) ## Add CMICmnLLDBUtilSBValue::GetCompositeValue to expand composite types ## Add CMICmnLLDBUtilSBValue::m_pComposite to avoid multiple {...} in the code ## Improve CMICmnLLDBUtilSBValue::GetValue to accept vbExpandAggregates option (default=false) ## Clean up CMICmnLLDBDebugSessionInfo::GetVariableInfo to use CMICmnLLDBUtilSBValue::GetValue ## Remove the wrapping into {} in CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo ## Fix MiStackTestCase.test_lldbmi_stack_list_locals test to expect result without superfluous space ' ' around the '{' or '}' brackets: was: ``` {name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = { var_d = 30 }} ``` now: ``` {name=\"var_c\",value=\"{var_a = 10,var_b = 97 'a',inner_ = {var_d = 30}} ``` ## Fix vwrValue arg name in CMICmnLLDBUtilSBValue::GetSimpleValue (was vrValue) # Refactor CMICmnLLDBDebugSessionInfo::GetVariableInfo (MI) ## Remove vnMaxDepth/vbIsChildValue/vnDepth args in CMICmnLLDBDebugSessionInfo::GetVariableInfo ## Improve CMICmnLLDBDebugSessionInfo::GetVariableInfo to accept vwrStrValue ## Remove vwrMiValueList arg in CMICmnLLDBDebugSessionInfo::GetVariableInfo (we should use vwrStrValue instead) ## Fix CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo to Escape values was: ``` {name="p",value="0x0000000000000000 """} ``` now: ``` {name="p",value="0x0000000000000000 \"\""} ``` # Refactor CMICmnLLDBUtilSBValue ## Improve CMICmnLLDBUtilSBValue::GetValue to handle PrintExpandAggregates ## Improve CMICmnLLDBUtilSBValue::GetSimpleValue to handle vbHandleArrayType (use it to specify that array should be represented as simple type, i.e. value="[2]") # Add spacing between fields in CMICmnLLDBUtilSBValue::GetCompositeValue (MI) For example: was: ``` ^done,name="var3",numchild="3",value="{i = 3,inner = {l = 3},complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0" ``` now: ``` ^done,name="var3",numchild="3",value="{i = 3, inner = {l = 3}, complex_ptr = 0x00007fff5fbff848}",type="complex_type",thread-id="1",has_more="0" ``` # Fix spacing in MiStackTestCase.test_lldbmi_stack_list_locals test (MI) Test Plan: ./dotest.py -v --executable $BUILDDIR/bin/lldb tools/lldb-mi/ Reviewers: abidh Subscribers: lldb-commits, abidh Differential Revision: http://reviews.llvm.org/D8913 llvm-svn: 234476
2015-04-09 19:17:54 +08:00
if (!rSessionInfo.MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, miValueTuple))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst("end-stepping-range");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
miOutOfBandRecord.Add(miValueResult2);
// Add to MI thread-id=\"%d\",stopped-threads=\"all\"
const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
const CMICmnMIValueConst miValueConst8(strThreadId);
const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
miOutOfBandRecord.Add(miValueResult8);
const CMICmnMIValueConst miValueConst9("all");
const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
miOutOfBandRecord.Add(miValueResult9);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Asynchronous function update selected thread.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread()
{
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess();
if (!process.IsValid())
return MIstatus::success;
lldb::SBThread currentThread = process.GetSelectedThread();
lldb::SBThread thread;
const lldb::StopReason eCurrentThreadStoppedReason = currentThread.GetStopReason();
if (!currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) ||
(eCurrentThreadStoppedReason == lldb::eStopReasonNone))
{
// Prefer a thread that has just completed its plan over another thread as current thread
lldb::SBThread planThread;
lldb::SBThread otherThread;
const size_t nThread = process.GetNumThreads();
for (MIuint i = 0; i < nThread; i++)
{
// GetThreadAtIndex() uses a base 0 index
// GetThreadByIndexID() uses a base 1 index
thread = process.GetThreadAtIndex(i);
const lldb::StopReason eThreadStopReason = thread.GetStopReason();
switch (eThreadStopReason)
{
case lldb::eStopReasonTrace:
case lldb::eStopReasonBreakpoint:
case lldb::eStopReasonWatchpoint:
case lldb::eStopReasonSignal:
case lldb::eStopReasonException:
if (!otherThread.IsValid())
otherThread = thread;
break;
case lldb::eStopReasonPlanComplete:
if (!planThread.IsValid())
planThread = thread;
break;
case lldb::eStopReasonInvalid:
case lldb::eStopReasonNone:
default:
break;
}
}
if (planThread.IsValid())
process.SetSelectedThread(planThread);
else if (otherThread.IsValid())
process.SetSelectedThread(otherThread);
else
{
if (currentThread.IsValid())
thread = currentThread;
else
thread = process.GetThreadAtIndex(0);
if (thread.IsValid())
process.SetSelectedThread(thread);
}
} // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason ==
// lldb::eStopReasonNone) )
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)".
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning()
{
CMICmnMIValueConst miValueConst("all");
CMICmnMIValueResult miValueResult("thread-id", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult);
bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"",
// "=thread-group-exited,id=\"i1\",exit-code=\"0\""),
// "*stopped,reason=\"exited-normally\"",
// "(gdb)"
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited()
{
const CMIUtilString strId(CMIUtilString::Format("%ld", 1));
CMICmnMIValueConst miValueConst(strId);
CMICmnMIValueResult miValueResult("id", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
CMICmnMIValueConst miValueConst2("i1");
CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
if (bOk)
{
CMICmnMIValueConst miValueConst3("i1");
CMICmnMIValueResult miValueResult3("id", miValueConst3);
CMICmnMIOutOfBandRecord miOutOfBandRecord2(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3);
CMICmnMIValueConst miValueConst2("0");
CMICmnMIValueResult miValueResult2("exit-code", miValueConst2);
miOutOfBandRecord2.Add(miValueResult2);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord2);
}
if (bOk)
{
CMICmnMIValueConst miValueConst4("exited-normally");
CMICmnMIValueResult miValueResult4("reason", miValueConst4);
CMICmnMIOutOfBandRecord miOutOfBandRecord3(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord3);
}
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Drain all stdout so we don't see any output come after we print our prompts.
// The process has stuff waiting for stdout; get it and write it out to the
// appropriate place.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::GetProcessStdout()
{
CMIUtilString text;
std::unique_ptr<char[]> apStdoutBuffer(new char[1024]);
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess();
while (1)
{
const size_t nBytes = process.GetSTDOUT(apStdoutBuffer.get(), 1024);
text.append(apStdoutBuffer.get(), nBytes);
while (1)
{
const size_t nNewLine = text.find('\n');
if (nNewLine == std::string::npos)
break;
const CMIUtilString line(text.substr(0, nNewLine + 1).c_str());
text.erase(0, nNewLine + 1);
const bool bEscapeQuotes(true);
CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
if (!bOk)
return MIstatus::failure;
}
if (nBytes == 0)
{
if (!text.empty())
{
const bool bEscapeQuotes(true);
CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes));
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
return MiOutOfBandRecordToStdout(miOutOfBandRecord);
}
break;
}
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Drain all stderr so we don't see any output come after we print our prompts.
// The process has stuff waiting for stderr; get it and write it out to the
// appropriate place.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::GetProcessStderr()
{
CMIUtilString text;
std::unique_ptr<char[]> apStderrBuffer(new char[1024]);
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess();
while (1)
{
const size_t nBytes = process.GetSTDERR(apStderrBuffer.get(), 1024);
text.append(apStderrBuffer.get(), nBytes);
while (1)
{
const size_t nNewLine = text.find('\n');
if (nNewLine == std::string::npos)
break;
const CMIUtilString line(text.substr(0, nNewLine + 1).c_str());
const bool bEscapeQuotes(true);
CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
if (!bOk)
return MIstatus::failure;
}
if (nBytes == 0)
{
if (!text.empty())
{
const bool bEscapeQuotes(true);
CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes));
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
return MiOutOfBandRecordToStdout(miOutOfBandRecord);
}
break;
}
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Asynchronous event function check for state changes.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges()
{
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
if (!sbProcess.IsValid())
return MIstatus::success;
// Check for created threads
const MIuint nThread = sbProcess.GetNumThreads();
for (MIuint i = 0; i < nThread; i++)
{
// GetThreadAtIndex() uses a base 0 index
// GetThreadByIndexID() uses a base 1 index
lldb::SBThread thread = sbProcess.GetThreadAtIndex(i);
if (!thread.IsValid())
continue;
const MIuint threadIndexID = thread.GetIndexID();
const bool bFound = std::find(rSessionInfo.m_vecActiveThreadId.cbegin(), rSessionInfo.m_vecActiveThreadId.cend(), threadIndexID) != rSessionInfo.m_vecActiveThreadId.end();
if (!bFound)
{
rSessionInfo.m_vecActiveThreadId.push_back(threadIndexID);
// Form MI "=thread-created,id=\"%d\",group-id=\"i1\""
const CMIUtilString strValue(CMIUtilString::Format("%d", threadIndexID));
const CMICmnMIValueConst miValueConst(strValue);
const CMICmnMIValueResult miValueResult("id", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult);
const CMICmnMIValueConst miValueConst2("i1");
const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
miOutOfBand.Add(miValueResult2);
bool bOk = MiOutOfBandRecordToStdout(miOutOfBand);
if (!bOk)
return MIstatus::failure;
}
}
lldb::SBThread currentThread = sbProcess.GetSelectedThread();
if (currentThread.IsValid())
{
const MIuint currentThreadIndexID = currentThread.GetIndexID();
if (rSessionInfo.m_currentSelectedThread != currentThreadIndexID)
{
rSessionInfo.m_currentSelectedThread = currentThreadIndexID;
// Form MI "=thread-selected,id=\"%d\""
const CMIUtilString strValue(CMIUtilString::Format("%d", currentThreadIndexID));
const CMICmnMIValueConst miValueConst(strValue);
const CMICmnMIValueResult miValueResult("id", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult);
if (!MiOutOfBandRecordToStdout(miOutOfBand))
return MIstatus::failure;
}
}
// Check for invalid (removed) threads
CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::iterator it = rSessionInfo.m_vecActiveThreadId.begin();
while (it != rSessionInfo.m_vecActiveThreadId.end())
{
const MIuint threadIndexID = *it;
lldb::SBThread thread = sbProcess.GetThreadByIndexID(threadIndexID);
if (!thread.IsValid())
{
// Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\""
const CMIUtilString strValue(CMIUtilString::Format("%ld", threadIndexID));
const CMICmnMIValueConst miValueConst(strValue);
const CMICmnMIValueResult miValueResult("id", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
const CMICmnMIValueConst miValueConst2("i1");
const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
miOutOfBand.Add(miValueResult2);
bool bOk = MiOutOfBandRecordToStdout(miOutOfBand);
if (!bOk)
return MIstatus::failure;
// Remove current thread from cache and get next
it = rSessionInfo.m_vecActiveThreadId.erase(it);
}
else
// Next
++it;
}
return CMICmnStreamStdout::WritePrompt();
}
//++ ------------------------------------------------------------------------------------
// Details: Take a fully formed MI result record and send to the stdout stream.
// Also output to the MI Log file.
// Type: Method.
// Args: vrMiResultRecord - (R) MI result record object.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord)
{
return TextToStdout(vrMiResultRecord.GetString());
}
//++ ------------------------------------------------------------------------------------
// Details: Take a fully formed MI Out-of-band record and send to the stdout stream.
// Also output to the MI Log file.
// Type: Method.
// Args: vrMiOutOfBandRecord - (R) MI Out-of-band record object.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiOutOfBandRecord)
{
return TextToStdout(vrMiOutOfBandRecord.GetString());
}
//++ ------------------------------------------------------------------------------------
// Details: Take a text data and send to the stdout stream. Also output to the MI Log
// file.
// Type: Method.
// Args: vrTxt - (R) Text.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::TextToStdout(const CMIUtilString &vrTxt)
{
return CMICmnStreamStdout::TextToStdout(vrTxt);
}
//++ ------------------------------------------------------------------------------------
// Details: Take a text data and send to the stderr stream. Also output to the MI Log
// file.
// Type: Method.
// Args: vrTxt - (R) Text.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::TextToStderr(const CMIUtilString &vrTxt)
{
return CMICmnStreamStderr::TextToStderr(vrTxt);
}
//++ ------------------------------------------------------------------------------------
// Details: Initialize the member variables with the signal values in this process
// file.
// Type: Method.
// Args: None
// Return: Noen
// Throws: None.
//--
void
CMICmnLLDBDebuggerHandleEvents::InitializeSignals()
{
if (!m_bSignalsInitialized)
{
lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
if (sbProcess.IsValid())
{
lldb::SBUnixSignals unix_signals = sbProcess.GetUnixSignals();
m_SIGINT = unix_signals.GetSignalNumberFromName("SIGINT");
m_SIGSTOP = unix_signals.GetSignalNumberFromName("SIGSTOP");
m_SIGSEGV = unix_signals.GetSignalNumberFromName("SIGSEGV");
m_SIGTRAP = unix_signals.GetSignalNumberFromName("SIGTRAP");
m_bSignalsInitialized = true;
}
}
}