Files
llvm/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

2616 lines
98 KiB
C++
Raw Normal View History

//===-- ProcessGDBRemote.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
#include <errno.h>
#include <spawn.h>
#include <stdlib.h>
#include <sys/mman.h> // for mmap
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
// C++ Includes
#include <algorithm>
#include <map>
// Other libraries and framework includes
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/InputReader.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
Added the ability to get the return value from a ThreadPlanCallFunction thread plan. In order to get the return value, you can call: void ThreadPlanCallFunction::RequestReturnValue (lldb::ValueSP &return_value_sp); This registers a shared pointer to a return value that will get filled in if everything goes well. After the thread plan is run the return value will be extracted for you. Added an ifdef to be able to switch between the LLVM MCJIT and the standand JIT. We currently have the standard JIT selected because we have some work to do to get the MCJIT fuctioning properly. Added the ability to call functions with 6 argument in the x86_64 ABI. Added the ability for GDBRemoteCommunicationClient to detect if the allocate and deallocate memory packets are supported and to not call allocate memory ("_M") or deallocate ("_m") if we find they aren't supported. Modified the ProcessGDBRemote::DoAllocateMemory(...) and ProcessGDBRemote::DoDeallocateMemory(...) to be able to deal with the allocate and deallocate memory packets not being supported. If they are not supported, ProcessGDBRemote will switch to calling "mmap" and "munmap" to allocate and deallocate memory instead using our trivial function call support. Modified the "void ProcessGDBRemote::DidLaunchOrAttach()" to correctly ignore the qHostInfo triple information if any was specified in the target. Currently if the target only specifies an architecture when creating the target: (lldb) target create --arch i386 a.out Then the vendor, os and environemnt will be adopted by the target. If the target was created with any triple that specifies more than the arch: (lldb) target create --arch i386-unknown-unknown a.out Then the target will maintain its triple and not adopt any new values. This can be used to help force bare board debugging where the dynamic loader for static files will get used and users can then use "target modules load ..." to set addressses for any files that are desired. Added back some convenience functions to the lldb_private::RegisterContext class for writing registers with unsigned values. Also made all RegisterContext constructors explicit to make sure we know when an integer is being converted to a RegisterValue. llvm-svn: 131370
2011-05-15 01:25:55 +00:00
#include "lldb/Core/Value.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Utility/PseudoTerminal.h"
// Project includes
#include "lldb/Host/Host.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "Utility/StringExtractorGDBRemote.h"
#include "GDBRemoteRegisterContext.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"
Abtracted the old "lldb_private::Thread::StopInfo" into an abtract class. This will allow debugger plug-ins to make any instance of "lldb_private::StopInfo" that can completely describe any stop reason. It also provides a framework for doing intelligent things with the stop info at important times in the lifetime of the inferior. Examples include the signal stop info in StopInfoUnixSignal. It will check with the process to see that the current action is for the signal. These actions include wether to stop for the signal, wether the notify that the signal was hit, and wether to pass the signal along to the inferior process. The StopInfoUnixSignal class overrides the "ShouldStop()" method of StopInfo and this allows the stop info to determine if it should stop at the signal or continue the process. StopInfo subclasses must override the following functions: virtual lldb::StopReason GetStopReason () const = 0; virtual const char * GetDescription () = 0; StopInfo subclasses can override the following functions: // If the subclass returns "false", the inferior will resume. The default // version of this function returns "true" which means the default stop // info will stop the process. The breakpoint subclass will check if // the breakpoint wants us to stop by calling any installed callback on // the breakpoint, and also checking if the breakpoint is for the current // thread. Signals will check if they should stop based off of the // UnixSignal settings in the process. virtual bool ShouldStop (Event *event_ptr); // Sublasses can state if they want to notify the debugger when "ShouldStop" // returns false. This would be handy for breakpoints where you want to // log information and continue and is also used by the signal stop info // to notify that a signal was received (after it checks with the process // signal settings). virtual bool ShouldNotify (Event *event_ptr) { return false; } // Allow subclasses to do something intelligent right before we resume. // The signal class will figure out if the signal should be propagated // to the inferior process and pass that along to the debugger plug-ins. virtual void WillResume (lldb::StateType resume_state) { // By default, don't do anything } The support the Mach exceptions was moved into the lldb/source/Plugins/Process/Utility folder and now doesn't polute the lldb_private::Thread class with platform specific code. llvm-svn: 110184
2010-08-04 01:40:35 +00:00
#include "StopInfoMachException.h"
#define DEBUGSERVER_BASENAME "debugserver"
using namespace lldb;
using namespace lldb_private;
static bool rand_initialized = false;
static inline uint16_t
get_random_port ()
{
if (!rand_initialized)
{
time_t seed = time(NULL);
rand_initialized = true;
srand(seed);
}
return (rand() % (UINT16_MAX - 1000u)) + 1000u;
}
const char *
ProcessGDBRemote::GetPluginNameStatic()
{
Added more platform support. There are now some new commands: platform status -- gets status information for the selected platform platform create <platform-name> -- creates a new instance of a remote platform platform list -- list all available platforms platform select -- select a platform instance as the current platform (not working yet) When using "platform create" it will create a remote platform and make it the selected platform. For instances for iPhone OS debugging on Mac OS X one can do: (lldb) platform create remote-ios --sdk-version=4.0 Remote platform: iOS platform SDK version: 4.0 SDK path: "/Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0" Not connected to a remote device. (lldb) file ~/Documents/a.out Current executable set to '~/Documents/a.out' (armv6). (lldb) image list [ 0] /Volumes/work/gclayton/Documents/devb/attach/a.out [ 1] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/dyld [ 2] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/libSystem.B.dylib Note that this is all happening prior to running _or_ connecting to a remote platform. Once connected to a remote platform the OS version might change which means we will need to update our dependecies. Also once we run, we will need to match up the actualy binaries with the actualy UUID's to files in the SDK, or download and cache them locally. This is just the start of the remote platforms, but this modification is the first iteration in getting the platforms really doing something. llvm-svn: 127934
2011-03-19 01:12:21 +00:00
return "gdb-remote";
}
const char *
ProcessGDBRemote::GetPluginDescriptionStatic()
{
return "GDB Remote protocol based debugging plug-in.";
}
void
ProcessGDBRemote::Terminate()
{
PluginManager::UnregisterPlugin (ProcessGDBRemote::CreateInstance);
}
First pass at mach-o core file support is in. It currently works for x86_64 user space programs. The core file support is implemented by making a process plug-in that will dress up the threads and stack frames by using the core file memory. Added many default implementations for the lldb_private::Process functions so that plug-ins like the ProcessMachCore don't need to override many many functions only to have to return an error. Added new virtual functions to the ObjectFile class for extracting the frozen thread states that might be stored in object files. The default implementations return no thread information, but any platforms that support core files that contain frozen thread states (like mach-o) can make a module using the core file and then extract the information. The object files can enumerate the threads and also provide the register state for each thread. Since each object file knows how the thread registers are stored, they are responsible for creating a suitable register context that can be used by the core file threads. Changed the process CreateInstace callbacks to return a shared pointer and to also take an "const FileSpec *core_file" parameter to allow for core file support. This will also allow for lldb_private::Process subclasses to be made that could load crash logs. This should be possible on darwin where the crash logs contain all of the stack frames for all of the threads, yet the crash logs only contain the registers for the crashed thrad. It should also allow some variables to be viewed for the thread that crashed. llvm-svn: 150154
2012-02-09 06:16:32 +00:00
lldb::ProcessSP
ProcessGDBRemote::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file_path)
{
First pass at mach-o core file support is in. It currently works for x86_64 user space programs. The core file support is implemented by making a process plug-in that will dress up the threads and stack frames by using the core file memory. Added many default implementations for the lldb_private::Process functions so that plug-ins like the ProcessMachCore don't need to override many many functions only to have to return an error. Added new virtual functions to the ObjectFile class for extracting the frozen thread states that might be stored in object files. The default implementations return no thread information, but any platforms that support core files that contain frozen thread states (like mach-o) can make a module using the core file and then extract the information. The object files can enumerate the threads and also provide the register state for each thread. Since each object file knows how the thread registers are stored, they are responsible for creating a suitable register context that can be used by the core file threads. Changed the process CreateInstace callbacks to return a shared pointer and to also take an "const FileSpec *core_file" parameter to allow for core file support. This will also allow for lldb_private::Process subclasses to be made that could load crash logs. This should be possible on darwin where the crash logs contain all of the stack frames for all of the threads, yet the crash logs only contain the registers for the crashed thrad. It should also allow some variables to be viewed for the thread that crashed. llvm-svn: 150154
2012-02-09 06:16:32 +00:00
lldb::ProcessSP process_sp;
if (crash_file_path == NULL)
process_sp.reset (new ProcessGDBRemote (target, listener));
return process_sp;
}
bool
ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)
{
if (plugin_specified_by_name)
return true;
// For now we are just making sure the file exists for a given module
Module *exe_module = target.GetExecutableModulePointer();
if (exe_module)
First pass at mach-o core file support is in. It currently works for x86_64 user space programs. The core file support is implemented by making a process plug-in that will dress up the threads and stack frames by using the core file memory. Added many default implementations for the lldb_private::Process functions so that plug-ins like the ProcessMachCore don't need to override many many functions only to have to return an error. Added new virtual functions to the ObjectFile class for extracting the frozen thread states that might be stored in object files. The default implementations return no thread information, but any platforms that support core files that contain frozen thread states (like mach-o) can make a module using the core file and then extract the information. The object files can enumerate the threads and also provide the register state for each thread. Since each object file knows how the thread registers are stored, they are responsible for creating a suitable register context that can be used by the core file threads. Changed the process CreateInstace callbacks to return a shared pointer and to also take an "const FileSpec *core_file" parameter to allow for core file support. This will also allow for lldb_private::Process subclasses to be made that could load crash logs. This should be possible on darwin where the crash logs contain all of the stack frames for all of the threads, yet the crash logs only contain the registers for the crashed thrad. It should also allow some variables to be viewed for the thread that crashed. llvm-svn: 150154
2012-02-09 06:16:32 +00:00
{
ObjectFile *exe_objfile = exe_module->GetObjectFile();
// We can't debug core files...
switch (exe_objfile->GetType())
{
case ObjectFile::eTypeInvalid:
case ObjectFile::eTypeCoreFile:
case ObjectFile::eTypeDebugInfo:
case ObjectFile::eTypeObjectFile:
case ObjectFile::eTypeSharedLibrary:
case ObjectFile::eTypeStubLibrary:
return false;
case ObjectFile::eTypeExecutable:
case ObjectFile::eTypeDynamicLinker:
case ObjectFile::eTypeUnknown:
break;
}
return exe_module->GetFileSpec().Exists();
First pass at mach-o core file support is in. It currently works for x86_64 user space programs. The core file support is implemented by making a process plug-in that will dress up the threads and stack frames by using the core file memory. Added many default implementations for the lldb_private::Process functions so that plug-ins like the ProcessMachCore don't need to override many many functions only to have to return an error. Added new virtual functions to the ObjectFile class for extracting the frozen thread states that might be stored in object files. The default implementations return no thread information, but any platforms that support core files that contain frozen thread states (like mach-o) can make a module using the core file and then extract the information. The object files can enumerate the threads and also provide the register state for each thread. Since each object file knows how the thread registers are stored, they are responsible for creating a suitable register context that can be used by the core file threads. Changed the process CreateInstace callbacks to return a shared pointer and to also take an "const FileSpec *core_file" parameter to allow for core file support. This will also allow for lldb_private::Process subclasses to be made that could load crash logs. This should be possible on darwin where the crash logs contain all of the stack frames for all of the threads, yet the crash logs only contain the registers for the crashed thrad. It should also allow some variables to be viewed for the thread that crashed. llvm-svn: 150154
2012-02-09 06:16:32 +00:00
}
// However, if there is no executable module, we return true since we might be preparing to attach.
return true;
}
//----------------------------------------------------------------------
// ProcessGDBRemote constructor
//----------------------------------------------------------------------
ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
Process (target, listener),
m_flags (0),
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
m_gdb_comm(false),
m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
m_last_stop_packet (),
m_last_stop_packet_mutex (Mutex::eMutexTypeNormal),
m_register_info (),
m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"),
m_async_thread (LLDB_INVALID_HOST_THREAD),
m_continue_c_tids (),
m_continue_C_tids (),
m_continue_s_tids (),
m_continue_S_tids (),
m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS),
m_max_memory_size (512),
m_waiting_for_attach (false),
m_thread_observation_bps()
{
m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
ProcessGDBRemote::~ProcessGDBRemote()
{
// m_mach_process.UnregisterNotificationCallbacks (this);
Clear();
// We need to call finalize on the process before destroying ourselves
// to make sure all of the broadcaster cleanup goes as planned. If we
// destruct this class, then Process::~Process() might have problems
// trying to fully destroy the broadcaster.
Finalize();
}
//----------------------------------------------------------------------
// PluginInterface
//----------------------------------------------------------------------
const char *
ProcessGDBRemote::GetPluginName()
{
return "Process debugging plug-in that uses the GDB remote protocol";
}
const char *
ProcessGDBRemote::GetShortPluginName()
{
return GetPluginNameStatic();
}
uint32_t
ProcessGDBRemote::GetPluginVersion()
{
return 1;
}
void
ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
{
if (!force && m_register_info.GetNumRegisters() > 0)
return;
char packet[128];
m_register_info.Clear();
uint32_t reg_offset = 0;
uint32_t reg_num = 0;
StringExtractorGDBRemote::ResponseType response_type;
for (response_type = StringExtractorGDBRemote::eResponse;
response_type == StringExtractorGDBRemote::eResponse;
++reg_num)
{
const int packet_len = ::snprintf (packet, sizeof(packet), "qRegisterInfo%x", reg_num);
assert (packet_len < sizeof(packet));
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
response_type = response.GetResponseType();
if (response_type == StringExtractorGDBRemote::eResponse)
{
std::string name;
std::string value;
ConstString reg_name;
ConstString alt_name;
ConstString set_name;
RegisterInfo reg_info = { NULL, // Name
NULL, // Alt name
0, // byte size
reg_offset, // offset
eEncodingUint, // encoding
eFormatHex, // formate
{
LLDB_INVALID_REGNUM, // GCC reg num
LLDB_INVALID_REGNUM, // DWARF reg num
LLDB_INVALID_REGNUM, // generic reg num
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 07:49:16 +00:00
reg_num, // GDB reg num
reg_num // native register number
}
};
while (response.GetNameColonValue(name, value))
{
if (name.compare("name") == 0)
{
reg_name.SetCString(value.c_str());
}
else if (name.compare("alt-name") == 0)
{
alt_name.SetCString(value.c_str());
}
else if (name.compare("bitsize") == 0)
{
reg_info.byte_size = Args::StringToUInt32(value.c_str(), 0, 0) / CHAR_BIT;
}
else if (name.compare("offset") == 0)
{
uint32_t offset = Args::StringToUInt32(value.c_str(), UINT32_MAX, 0);
if (reg_offset != offset)
{
reg_offset = offset;
}
}
else if (name.compare("encoding") == 0)
{
if (value.compare("uint") == 0)
reg_info.encoding = eEncodingUint;
else if (value.compare("sint") == 0)
reg_info.encoding = eEncodingSint;
else if (value.compare("ieee754") == 0)
reg_info.encoding = eEncodingIEEE754;
else if (value.compare("vector") == 0)
reg_info.encoding = eEncodingVector;
}
else if (name.compare("format") == 0)
{
if (value.compare("binary") == 0)
reg_info.format = eFormatBinary;
else if (value.compare("decimal") == 0)
reg_info.format = eFormatDecimal;
else if (value.compare("hex") == 0)
reg_info.format = eFormatHex;
else if (value.compare("float") == 0)
reg_info.format = eFormatFloat;
else if (value.compare("vector-sint8") == 0)
reg_info.format = eFormatVectorOfSInt8;
else if (value.compare("vector-uint8") == 0)
reg_info.format = eFormatVectorOfUInt8;
else if (value.compare("vector-sint16") == 0)
reg_info.format = eFormatVectorOfSInt16;
else if (value.compare("vector-uint16") == 0)
reg_info.format = eFormatVectorOfUInt16;
else if (value.compare("vector-sint32") == 0)
reg_info.format = eFormatVectorOfSInt32;
else if (value.compare("vector-uint32") == 0)
reg_info.format = eFormatVectorOfUInt32;
else if (value.compare("vector-float32") == 0)
reg_info.format = eFormatVectorOfFloat32;
else if (value.compare("vector-uint128") == 0)
reg_info.format = eFormatVectorOfUInt128;
}
else if (name.compare("set") == 0)
{
set_name.SetCString(value.c_str());
}
else if (name.compare("gcc") == 0)
{
reg_info.kinds[eRegisterKindGCC] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
}
else if (name.compare("dwarf") == 0)
{
reg_info.kinds[eRegisterKindDWARF] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
}
else if (name.compare("generic") == 0)
{
if (value.compare("pc") == 0)
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
else if (value.compare("sp") == 0)
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
else if (value.compare("fp") == 0)
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
else if (value.compare("ra") == 0)
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
else if (value.compare("flags") == 0)
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
Added functions to lldb_private::Address to set an address from a load address and set the address as an opcode address or as a callable address. This is needed in various places in the thread plans to make sure that addresses that might be found in symbols or runtime might already have extra bits set (ARM/Thumb). The new functions are: bool Address::SetCallableLoadAddress (lldb::addr_t load_addr, Target *target); bool Address::SetOpcodeLoadAddress (lldb::addr_t load_addr, Target *target); SetCallableLoadAddress will initialize a section offset address if it can, and if so it might possibly set some bits in the address to make the address callable (bit zero might get set for ARM for Thumb functions). SetOpcodeLoadAddress will initialize a section offset address using the specified target and it will strip any special address bits if needed depending on the target. Fixed the ABIMacOSX_arm::GetArgumentValues() function to require arguments 1-4 to be in the needed registers (previously this would incorrectly fallback to the stack) and return false if unable to get the register values. The function was also modified to first look for the generic argument registers and then fall back to finding the registers by name. Fixed the objective trampoline handler to use the new Address::SetOpcodeLoadAddress function when needed to avoid address mismatches when trying to complete steps into objective C methods. Make similar fixes inside the AppleThreadPlanStepThroughObjCTrampoline::ShouldStop() function. Modified ProcessGDBRemote::BuildDynamicRegisterInfo(...) to be able to deal with the new generic argument registers. Modified RNBRemote::HandlePacket_qRegisterInfo() to handle the new generic argument registers on the debugserver side. Modified DNBArchMachARM::NumSupportedHardwareBreakpoints() to be able to detect how many hardware breakpoint registers there are using a darwin sysctl. Did the same for hardware watchpoints in DNBArchMachARM::NumSupportedHardwareWatchpoints(). llvm-svn: 131834
2011-05-22 04:32:55 +00:00
else if (value.find("arg") == 0)
{
if (value.size() == 4)
{
switch (value[3])
{
case '1': reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG1; break;
case '2': reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG2; break;
case '3': reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG3; break;
case '4': reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG4; break;
case '5': reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG5; break;
case '6': reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG6; break;
case '7': reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG7; break;
case '8': reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG8; break;
}
}
}
}
}
reg_info.byte_offset = reg_offset;
assert (reg_info.byte_size != 0);
reg_offset += reg_info.byte_size;
m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
}
}
else
{
response_type = StringExtractorGDBRemote::eError;
Many improvements to the Platform base class and subclasses. The base Platform class now implements the Host functionality for a lot of things that make sense by default so that subclasses can check: int PlatformSubclass::Foo () { if (IsHost()) return Platform::Foo (); // Let the platform base class do the host specific stuff // Platform subclass specific code... int result = ... return result; } Added new functions to the platform: virtual const char *Platform::GetUserName (uint32_t uid); virtual const char *Platform::GetGroupName (uint32_t gid); The user and group names are cached locally so that remote platforms can avoid sending packets multiple times to resolve this information. Added the parent process ID to the ProcessInfo class. Added a new ProcessInfoMatch class which helps us to match processes up and changed the Host layer over to using this new class. The new class allows us to search for processs: 1 - by name (equal to, starts with, ends with, contains, and regex) 2 - by pid 3 - And further check for parent pid == value, uid == value, gid == value, euid == value, egid == value, arch == value, parent == value. This is all hookup up to the "platform process list" command which required adding dumping routines to dump process information. If the Host class implements the process lookup routines, you can now lists processes on your local machine: machine1.foo.com % lldb (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari 94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode 92742 92710 username usergroup username usergroup i386-apple-darwin debugserver This of course also works remotely with the lldb-platform: machine1.foo.com % lldb-platform --listen 1234 machine2.foo.com % lldb (lldb) platform create remote-macosx Platform: remote-macosx Connected: no (lldb) platform connect connect://localhost:1444 Platform: remote-macosx Triple: x86_64-apple-darwin OS Version: 10.6.7 (10J869) Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 Hostname: machine1.foo.com Connected: yes (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation 99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari The lldb-platform implements everything with the Host:: layer, so this should "just work" for linux. I will probably be adding more stuff to the Host layer for launching processes and attaching to processes so that this support should eventually just work as well. Modified the target to be able to be created with an architecture that differs from the main executable. This is needed for iOS debugging since we can have an "armv6" binary which can run on an "armv7" machine, so we want to be able to do: % lldb (lldb) platform create remote-ios (lldb) file --arch armv7 a.out Where "a.out" is an armv6 executable. The platform then can correctly decide to open all "armv7" images for all dependent shared libraries. Modified the disassembly to show the current PC value. Example output: (lldb) disassemble --frame a.out`main: 0x1eb7: pushl %ebp 0x1eb8: movl %esp, %ebp 0x1eba: pushl %ebx 0x1ebb: subl $20, %esp 0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18 0x1ec3: popl %ebx -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf 0x1edb: leal 213(%ebx), %eax 0x1ee1: movl %eax, (%esp) 0x1ee4: calll 0x1f1e ; puts 0x1ee9: calll 0x1f0c ; getchar 0x1eee: movl $20, (%esp) 0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6 0x1efa: movl $12, %eax 0x1eff: addl $20, %esp 0x1f02: popl %ebx 0x1f03: leave 0x1f04: ret This can be handy when dealing with the new --line options that was recently added: (lldb) disassemble --line a.out`main + 13 at test.c:19 18 { -> 19 printf("Process: %i\n\n", getpid()); 20 puts("Press any key to continue..."); getchar(); -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf Modified the ModuleList to have a lookup based solely on a UUID. Since the UUID is typically the MD5 checksum of a binary image, there is no need to give the path and architecture when searching for a pre-existing image in an image list. Now that we support remote debugging a bit better, our lldb_private::Module needs to be able to track what the original path for file was as the platform knows it, as well as where the file is locally. The module has the two following functions to retrieve both paths: const FileSpec &Module::GetFileSpec () const; const FileSpec &Module::GetPlatformFileSpec () const; llvm-svn: 128563
2011-03-30 18:16:51 +00:00
break;
}
}
if (reg_num == 0)
{
// We didn't get anything. See if we are debugging ARM and fill with
// a hard coded register set until we can get an updated debugserver
// down on the devices.
if (!GetTarget().GetArchitecture().IsValid()
&& m_gdb_comm.GetHostArchitecture().IsValid()
&& m_gdb_comm.GetHostArchitecture().GetMachine() == llvm::Triple::arm
&& m_gdb_comm.GetHostArchitecture().GetTriple().getVendor() == llvm::Triple::Apple)
{
m_register_info.HardcodeARMRegisters();
}
else if (GetTarget().GetArchitecture().GetMachine() == llvm::Triple::arm)
{
m_register_info.HardcodeARMRegisters();
}
}
m_register_info.Finalize ();
}
Error
ProcessGDBRemote::WillLaunch (Module* module)
{
return WillLaunchOrAttach ();
}
Error
2010-11-18 05:57:03 +00:00
ProcessGDBRemote::WillAttachToProcessWithID (lldb::pid_t pid)
{
return WillLaunchOrAttach ();
}
Error
2010-11-18 05:57:03 +00:00
ProcessGDBRemote::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch)
{
return WillLaunchOrAttach ();
}
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
Error
ProcessGDBRemote::DoConnectRemote (const char *remote_url)
{
Error error (WillLaunchOrAttach ());
if (error.Fail())
return error;
error = ConnectToDebugserver (remote_url);
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
if (error.Fail())
return error;
StartAsyncThread ();
lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
if (pid == LLDB_INVALID_PROCESS_ID)
{
// We don't have a valid process ID, so note that we are connected
// and could now request to launch or attach, or get remote process
// listings...
SetPrivateState (eStateConnected);
}
else
{
// We have a valid process
SetID (pid);
GetThreadList();
if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
{
const StateType state = SetThreadStopInfo (m_last_stop_packet);
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
if (state == eStateStopped)
{
SetPrivateState (state);
}
else
error.SetErrorStringWithFormat ("Process %llu was reported after connecting to '%s', but state was not stopped: %s", pid, remote_url, StateAsCString (state));
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
}
else
error.SetErrorStringWithFormat ("Process %llu was reported after connecting to '%s', but no stop reply packet was received", pid, remote_url);
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
}
return error;
}
Error
ProcessGDBRemote::WillLaunchOrAttach ()
{
Error error;
m_stdio_communication.Clear ();
return error;
}
//----------------------------------------------------------------------
// Process Control
//----------------------------------------------------------------------
Error
ProcessGDBRemote::DoLaunch (Module *exe_module, const ProcessLaunchInfo &launch_info)
{
Error error;
uint32_t launch_flags = launch_info.GetFlags().Get();
const char *stdin_path = NULL;
const char *stdout_path = NULL;
const char *stderr_path = NULL;
const char *working_dir = launch_info.GetWorkingDirectory();
const ProcessLaunchInfo::FileAction *file_action;
file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
if (file_action)
{
if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
stdin_path = file_action->GetPath();
}
file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
if (file_action)
{
if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
stdout_path = file_action->GetPath();
}
file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
if (file_action)
{
if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
stderr_path = file_action->GetPath();
}
// ::LogSetBitMask (GDBR_LOG_DEFAULT);
// ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
// ::LogSetLogFile ("/dev/stdout");
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
ObjectFile * object_file = exe_module->GetObjectFile();
if (object_file)
{
char host_port[128];
snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
char connect_url[128];
snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
// Make sure we aren't already connected?
if (!m_gdb_comm.IsConnected())
{
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
error = StartDebugserverProcess (host_port);
if (error.Fail())
{
if (log)
log->Printf("failed to start debugserver process: %s", error.AsCString());
return error;
}
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
error = ConnectToDebugserver (connect_url);
}
if (error.Success())
{
lldb_utility::PseudoTerminal pty;
const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
// If the debugserver is local and we aren't disabling STDIO, lets use
// a pseudo terminal to instead of relying on the 'O' packets for stdio
// since 'O' packets can really slow down debugging if the inferior
// does a lot of output.
PlatformSP platform_sp (m_target.GetPlatform());
if (platform_sp && platform_sp->IsHost() && !disable_stdio)
{
const char *slave_name = NULL;
if (stdin_path == NULL || stdout_path == NULL || stderr_path == NULL)
{
if (pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
slave_name = pty.GetSlaveName (NULL, 0);
}
if (stdin_path == NULL)
stdin_path = slave_name;
if (stdout_path == NULL)
stdout_path = slave_name;
if (stderr_path == NULL)
stderr_path = slave_name;
}
// Set STDIN to /dev/null if we want STDIO disabled or if either
// STDOUT or STDERR have been set to something and STDIN hasn't
if (disable_stdio || (stdin_path == NULL && (stdout_path || stderr_path)))
stdin_path = "/dev/null";
// Set STDOUT to /dev/null if we want STDIO disabled or if either
// STDIN or STDERR have been set to something and STDOUT hasn't
if (disable_stdio || (stdout_path == NULL && (stdin_path || stderr_path)))
stdout_path = "/dev/null";
// Set STDERR to /dev/null if we want STDIO disabled or if either
// STDIN or STDOUT have been set to something and STDERR hasn't
if (disable_stdio || (stderr_path == NULL && (stdin_path || stdout_path)))
stderr_path = "/dev/null";
if (stdin_path)
m_gdb_comm.SetSTDIN (stdin_path);
if (stdout_path)
m_gdb_comm.SetSTDOUT (stdout_path);
if (stderr_path)
m_gdb_comm.SetSTDERR (stderr_path);
m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
m_gdb_comm.SendLaunchArchPacket (m_target.GetArchitecture().GetArchitectureName());
if (working_dir && working_dir[0])
{
m_gdb_comm.SetWorkingDir (working_dir);
}
// Send the environment and the program + arguments after we connect
const Args &environment = launch_info.GetEnvironmentEntries();
if (environment.GetArgumentCount())
{
size_t num_environment_entries = environment.GetArgumentCount();
for (size_t i=0; i<num_environment_entries; ++i)
{
const char *env_entry = environment.GetArgumentAtIndex(i);
if (env_entry == NULL || m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
break;
}
}
const uint32_t old_packet_timeout = m_gdb_comm.SetPacketTimeout (10);
int arg_packet_err = m_gdb_comm.SendArgumentsPacket (launch_info.GetArguments().GetConstArgumentVector());
if (arg_packet_err == 0)
{
std::string error_str;
if (m_gdb_comm.GetLaunchSuccess (error_str))
{
SetID (m_gdb_comm.GetCurrentProcessID ());
}
else
{
error.SetErrorString (error_str.c_str());
}
}
else
{
error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err);
}
m_gdb_comm.SetPacketTimeout (old_packet_timeout);
if (GetID() == LLDB_INVALID_PROCESS_ID)
{
if (log)
log->Printf("failed to connect to debugserver: %s", error.AsCString());
KillDebugserverProcess ();
return error;
}
if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
{
SetPrivateState (SetThreadStopInfo (m_last_stop_packet));
if (!disable_stdio)
{
if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd)
SetSTDIOFileDescriptor (pty.ReleaseMasterFileDescriptor());
}
}
}
else
{
if (log)
log->Printf("failed to connect to debugserver: %s", error.AsCString());
}
}
else
{
// Set our user ID to an invalid process ID.
SetID(LLDB_INVALID_PROCESS_ID);
error.SetErrorStringWithFormat ("failed to get object file from '%s' for arch %s",
exe_module->GetFileSpec().GetFilename().AsCString(),
exe_module->GetArchitecture().GetArchitectureName());
}
return error;
}
Error
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
{
Error error;
// Sleep and wait a bit for debugserver to start to listen...
std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
if (conn_ap.get())
{
const uint32_t max_retry_count = 50;
uint32_t retry_count = 0;
while (!m_gdb_comm.IsConnected())
{
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
{
m_gdb_comm.SetConnection (conn_ap.release());
break;
}
retry_count++;
if (retry_count >= max_retry_count)
break;
usleep (100000);
}
}
if (!m_gdb_comm.IsConnected())
{
if (error.Success())
error.SetErrorString("not connected to remote gdb server");
return error;
}
Many improvements to the Platform base class and subclasses. The base Platform class now implements the Host functionality for a lot of things that make sense by default so that subclasses can check: int PlatformSubclass::Foo () { if (IsHost()) return Platform::Foo (); // Let the platform base class do the host specific stuff // Platform subclass specific code... int result = ... return result; } Added new functions to the platform: virtual const char *Platform::GetUserName (uint32_t uid); virtual const char *Platform::GetGroupName (uint32_t gid); The user and group names are cached locally so that remote platforms can avoid sending packets multiple times to resolve this information. Added the parent process ID to the ProcessInfo class. Added a new ProcessInfoMatch class which helps us to match processes up and changed the Host layer over to using this new class. The new class allows us to search for processs: 1 - by name (equal to, starts with, ends with, contains, and regex) 2 - by pid 3 - And further check for parent pid == value, uid == value, gid == value, euid == value, egid == value, arch == value, parent == value. This is all hookup up to the "platform process list" command which required adding dumping routines to dump process information. If the Host class implements the process lookup routines, you can now lists processes on your local machine: machine1.foo.com % lldb (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari 94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode 92742 92710 username usergroup username usergroup i386-apple-darwin debugserver This of course also works remotely with the lldb-platform: machine1.foo.com % lldb-platform --listen 1234 machine2.foo.com % lldb (lldb) platform create remote-macosx Platform: remote-macosx Connected: no (lldb) platform connect connect://localhost:1444 Platform: remote-macosx Triple: x86_64-apple-darwin OS Version: 10.6.7 (10J869) Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 Hostname: machine1.foo.com Connected: yes (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation 99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari The lldb-platform implements everything with the Host:: layer, so this should "just work" for linux. I will probably be adding more stuff to the Host layer for launching processes and attaching to processes so that this support should eventually just work as well. Modified the target to be able to be created with an architecture that differs from the main executable. This is needed for iOS debugging since we can have an "armv6" binary which can run on an "armv7" machine, so we want to be able to do: % lldb (lldb) platform create remote-ios (lldb) file --arch armv7 a.out Where "a.out" is an armv6 executable. The platform then can correctly decide to open all "armv7" images for all dependent shared libraries. Modified the disassembly to show the current PC value. Example output: (lldb) disassemble --frame a.out`main: 0x1eb7: pushl %ebp 0x1eb8: movl %esp, %ebp 0x1eba: pushl %ebx 0x1ebb: subl $20, %esp 0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18 0x1ec3: popl %ebx -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf 0x1edb: leal 213(%ebx), %eax 0x1ee1: movl %eax, (%esp) 0x1ee4: calll 0x1f1e ; puts 0x1ee9: calll 0x1f0c ; getchar 0x1eee: movl $20, (%esp) 0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6 0x1efa: movl $12, %eax 0x1eff: addl $20, %esp 0x1f02: popl %ebx 0x1f03: leave 0x1f04: ret This can be handy when dealing with the new --line options that was recently added: (lldb) disassemble --line a.out`main + 13 at test.c:19 18 { -> 19 printf("Process: %i\n\n", getpid()); 20 puts("Press any key to continue..."); getchar(); -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf Modified the ModuleList to have a lookup based solely on a UUID. Since the UUID is typically the MD5 checksum of a binary image, there is no need to give the path and architecture when searching for a pre-existing image in an image list. Now that we support remote debugging a bit better, our lldb_private::Module needs to be able to track what the original path for file was as the platform knows it, as well as where the file is locally. The module has the two following functions to retrieve both paths: const FileSpec &Module::GetFileSpec () const; const FileSpec &Module::GetPlatformFileSpec () const; llvm-svn: 128563
2011-03-30 18:16:51 +00:00
// We always seem to be able to open a connection to a local port
// so we need to make sure we can then send data to it. If we can't
// then we aren't actually connected to anything, so try and do the
// handshake with the remote GDB server and make sure that goes
// alright.
if (!m_gdb_comm.HandshakeWithServer (NULL))
{
Many improvements to the Platform base class and subclasses. The base Platform class now implements the Host functionality for a lot of things that make sense by default so that subclasses can check: int PlatformSubclass::Foo () { if (IsHost()) return Platform::Foo (); // Let the platform base class do the host specific stuff // Platform subclass specific code... int result = ... return result; } Added new functions to the platform: virtual const char *Platform::GetUserName (uint32_t uid); virtual const char *Platform::GetGroupName (uint32_t gid); The user and group names are cached locally so that remote platforms can avoid sending packets multiple times to resolve this information. Added the parent process ID to the ProcessInfo class. Added a new ProcessInfoMatch class which helps us to match processes up and changed the Host layer over to using this new class. The new class allows us to search for processs: 1 - by name (equal to, starts with, ends with, contains, and regex) 2 - by pid 3 - And further check for parent pid == value, uid == value, gid == value, euid == value, egid == value, arch == value, parent == value. This is all hookup up to the "platform process list" command which required adding dumping routines to dump process information. If the Host class implements the process lookup routines, you can now lists processes on your local machine: machine1.foo.com % lldb (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari 94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode 92742 92710 username usergroup username usergroup i386-apple-darwin debugserver This of course also works remotely with the lldb-platform: machine1.foo.com % lldb-platform --listen 1234 machine2.foo.com % lldb (lldb) platform create remote-macosx Platform: remote-macosx Connected: no (lldb) platform connect connect://localhost:1444 Platform: remote-macosx Triple: x86_64-apple-darwin OS Version: 10.6.7 (10J869) Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 Hostname: machine1.foo.com Connected: yes (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation 99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari The lldb-platform implements everything with the Host:: layer, so this should "just work" for linux. I will probably be adding more stuff to the Host layer for launching processes and attaching to processes so that this support should eventually just work as well. Modified the target to be able to be created with an architecture that differs from the main executable. This is needed for iOS debugging since we can have an "armv6" binary which can run on an "armv7" machine, so we want to be able to do: % lldb (lldb) platform create remote-ios (lldb) file --arch armv7 a.out Where "a.out" is an armv6 executable. The platform then can correctly decide to open all "armv7" images for all dependent shared libraries. Modified the disassembly to show the current PC value. Example output: (lldb) disassemble --frame a.out`main: 0x1eb7: pushl %ebp 0x1eb8: movl %esp, %ebp 0x1eba: pushl %ebx 0x1ebb: subl $20, %esp 0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18 0x1ec3: popl %ebx -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf 0x1edb: leal 213(%ebx), %eax 0x1ee1: movl %eax, (%esp) 0x1ee4: calll 0x1f1e ; puts 0x1ee9: calll 0x1f0c ; getchar 0x1eee: movl $20, (%esp) 0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6 0x1efa: movl $12, %eax 0x1eff: addl $20, %esp 0x1f02: popl %ebx 0x1f03: leave 0x1f04: ret This can be handy when dealing with the new --line options that was recently added: (lldb) disassemble --line a.out`main + 13 at test.c:19 18 { -> 19 printf("Process: %i\n\n", getpid()); 20 puts("Press any key to continue..."); getchar(); -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf Modified the ModuleList to have a lookup based solely on a UUID. Since the UUID is typically the MD5 checksum of a binary image, there is no need to give the path and architecture when searching for a pre-existing image in an image list. Now that we support remote debugging a bit better, our lldb_private::Module needs to be able to track what the original path for file was as the platform knows it, as well as where the file is locally. The module has the two following functions to retrieve both paths: const FileSpec &Module::GetFileSpec () const; const FileSpec &Module::GetPlatformFileSpec () const; llvm-svn: 128563
2011-03-30 18:16:51 +00:00
m_gdb_comm.Disconnect();
if (error.Success())
error.SetErrorString("not connected to remote gdb server");
return error;
}
Many improvements to the Platform base class and subclasses. The base Platform class now implements the Host functionality for a lot of things that make sense by default so that subclasses can check: int PlatformSubclass::Foo () { if (IsHost()) return Platform::Foo (); // Let the platform base class do the host specific stuff // Platform subclass specific code... int result = ... return result; } Added new functions to the platform: virtual const char *Platform::GetUserName (uint32_t uid); virtual const char *Platform::GetGroupName (uint32_t gid); The user and group names are cached locally so that remote platforms can avoid sending packets multiple times to resolve this information. Added the parent process ID to the ProcessInfo class. Added a new ProcessInfoMatch class which helps us to match processes up and changed the Host layer over to using this new class. The new class allows us to search for processs: 1 - by name (equal to, starts with, ends with, contains, and regex) 2 - by pid 3 - And further check for parent pid == value, uid == value, gid == value, euid == value, egid == value, arch == value, parent == value. This is all hookup up to the "platform process list" command which required adding dumping routines to dump process information. If the Host class implements the process lookup routines, you can now lists processes on your local machine: machine1.foo.com % lldb (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari 94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode 92742 92710 username usergroup username usergroup i386-apple-darwin debugserver This of course also works remotely with the lldb-platform: machine1.foo.com % lldb-platform --listen 1234 machine2.foo.com % lldb (lldb) platform create remote-macosx Platform: remote-macosx Connected: no (lldb) platform connect connect://localhost:1444 Platform: remote-macosx Triple: x86_64-apple-darwin OS Version: 10.6.7 (10J869) Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 Hostname: machine1.foo.com Connected: yes (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation 99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari The lldb-platform implements everything with the Host:: layer, so this should "just work" for linux. I will probably be adding more stuff to the Host layer for launching processes and attaching to processes so that this support should eventually just work as well. Modified the target to be able to be created with an architecture that differs from the main executable. This is needed for iOS debugging since we can have an "armv6" binary which can run on an "armv7" machine, so we want to be able to do: % lldb (lldb) platform create remote-ios (lldb) file --arch armv7 a.out Where "a.out" is an armv6 executable. The platform then can correctly decide to open all "armv7" images for all dependent shared libraries. Modified the disassembly to show the current PC value. Example output: (lldb) disassemble --frame a.out`main: 0x1eb7: pushl %ebp 0x1eb8: movl %esp, %ebp 0x1eba: pushl %ebx 0x1ebb: subl $20, %esp 0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18 0x1ec3: popl %ebx -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf 0x1edb: leal 213(%ebx), %eax 0x1ee1: movl %eax, (%esp) 0x1ee4: calll 0x1f1e ; puts 0x1ee9: calll 0x1f0c ; getchar 0x1eee: movl $20, (%esp) 0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6 0x1efa: movl $12, %eax 0x1eff: addl $20, %esp 0x1f02: popl %ebx 0x1f03: leave 0x1f04: ret This can be handy when dealing with the new --line options that was recently added: (lldb) disassemble --line a.out`main + 13 at test.c:19 18 { -> 19 printf("Process: %i\n\n", getpid()); 20 puts("Press any key to continue..."); getchar(); -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf Modified the ModuleList to have a lookup based solely on a UUID. Since the UUID is typically the MD5 checksum of a binary image, there is no need to give the path and architecture when searching for a pre-existing image in an image list. Now that we support remote debugging a bit better, our lldb_private::Module needs to be able to track what the original path for file was as the platform knows it, as well as where the file is locally. The module has the two following functions to retrieve both paths: const FileSpec &Module::GetFileSpec () const; const FileSpec &Module::GetPlatformFileSpec () const; llvm-svn: 128563
2011-03-30 18:16:51 +00:00
m_gdb_comm.ResetDiscoverableSettings();
m_gdb_comm.QueryNoAckModeSupported ();
m_gdb_comm.GetThreadSuffixSupported ();
m_gdb_comm.GetHostInfo ();
m_gdb_comm.GetVContSupported ('c');
return error;
}
void
ProcessGDBRemote::DidLaunchOrAttach ()
{
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::DidLaunch()");
if (GetID() != LLDB_INVALID_PROCESS_ID)
{
m_dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS;
BuildDynamicRegisterInfo (false);
2010-11-18 05:57:03 +00:00
// See if the GDB server supports the qHostInfo information
const ArchSpec &gdb_remote_arch = m_gdb_comm.GetHostArchitecture();
if (gdb_remote_arch.IsValid())
{
ArchSpec &target_arch = GetTarget().GetArchitecture();
if (target_arch.IsValid())
{
// If the remote host is ARM and we have apple as the vendor, then
// ARM executables and shared libraries can have mixed ARM architectures.
// You can have an armv6 executable, and if the host is armv7, then the
// system will load the best possible architecture for all shared libraries
// it has, so we really need to take the remote host architecture as our
// defacto architecture in this case.
if (gdb_remote_arch.GetMachine() == llvm::Triple::arm &&
gdb_remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)
{
target_arch = gdb_remote_arch;
}
else
{
// Fill in what is missing in the triple
const llvm::Triple &remote_triple = gdb_remote_arch.GetTriple();
llvm::Triple &target_triple = target_arch.GetTriple();
Added the ability to get the return value from a ThreadPlanCallFunction thread plan. In order to get the return value, you can call: void ThreadPlanCallFunction::RequestReturnValue (lldb::ValueSP &return_value_sp); This registers a shared pointer to a return value that will get filled in if everything goes well. After the thread plan is run the return value will be extracted for you. Added an ifdef to be able to switch between the LLVM MCJIT and the standand JIT. We currently have the standard JIT selected because we have some work to do to get the MCJIT fuctioning properly. Added the ability to call functions with 6 argument in the x86_64 ABI. Added the ability for GDBRemoteCommunicationClient to detect if the allocate and deallocate memory packets are supported and to not call allocate memory ("_M") or deallocate ("_m") if we find they aren't supported. Modified the ProcessGDBRemote::DoAllocateMemory(...) and ProcessGDBRemote::DoDeallocateMemory(...) to be able to deal with the allocate and deallocate memory packets not being supported. If they are not supported, ProcessGDBRemote will switch to calling "mmap" and "munmap" to allocate and deallocate memory instead using our trivial function call support. Modified the "void ProcessGDBRemote::DidLaunchOrAttach()" to correctly ignore the qHostInfo triple information if any was specified in the target. Currently if the target only specifies an architecture when creating the target: (lldb) target create --arch i386 a.out Then the vendor, os and environemnt will be adopted by the target. If the target was created with any triple that specifies more than the arch: (lldb) target create --arch i386-unknown-unknown a.out Then the target will maintain its triple and not adopt any new values. This can be used to help force bare board debugging where the dynamic loader for static files will get used and users can then use "target modules load ..." to set addressses for any files that are desired. Added back some convenience functions to the lldb_private::RegisterContext class for writing registers with unsigned values. Also made all RegisterContext constructors explicit to make sure we know when an integer is being converted to a RegisterValue. llvm-svn: 131370
2011-05-15 01:25:55 +00:00
if (target_triple.getVendorName().size() == 0)
{
target_triple.setVendor (remote_triple.getVendor());
Added the ability to get the return value from a ThreadPlanCallFunction thread plan. In order to get the return value, you can call: void ThreadPlanCallFunction::RequestReturnValue (lldb::ValueSP &return_value_sp); This registers a shared pointer to a return value that will get filled in if everything goes well. After the thread plan is run the return value will be extracted for you. Added an ifdef to be able to switch between the LLVM MCJIT and the standand JIT. We currently have the standard JIT selected because we have some work to do to get the MCJIT fuctioning properly. Added the ability to call functions with 6 argument in the x86_64 ABI. Added the ability for GDBRemoteCommunicationClient to detect if the allocate and deallocate memory packets are supported and to not call allocate memory ("_M") or deallocate ("_m") if we find they aren't supported. Modified the ProcessGDBRemote::DoAllocateMemory(...) and ProcessGDBRemote::DoDeallocateMemory(...) to be able to deal with the allocate and deallocate memory packets not being supported. If they are not supported, ProcessGDBRemote will switch to calling "mmap" and "munmap" to allocate and deallocate memory instead using our trivial function call support. Modified the "void ProcessGDBRemote::DidLaunchOrAttach()" to correctly ignore the qHostInfo triple information if any was specified in the target. Currently if the target only specifies an architecture when creating the target: (lldb) target create --arch i386 a.out Then the vendor, os and environemnt will be adopted by the target. If the target was created with any triple that specifies more than the arch: (lldb) target create --arch i386-unknown-unknown a.out Then the target will maintain its triple and not adopt any new values. This can be used to help force bare board debugging where the dynamic loader for static files will get used and users can then use "target modules load ..." to set addressses for any files that are desired. Added back some convenience functions to the lldb_private::RegisterContext class for writing registers with unsigned values. Also made all RegisterContext constructors explicit to make sure we know when an integer is being converted to a RegisterValue. llvm-svn: 131370
2011-05-15 01:25:55 +00:00
if (target_triple.getOSName().size() == 0)
{
target_triple.setOS (remote_triple.getOS());
Added the ability to get the return value from a ThreadPlanCallFunction thread plan. In order to get the return value, you can call: void ThreadPlanCallFunction::RequestReturnValue (lldb::ValueSP &return_value_sp); This registers a shared pointer to a return value that will get filled in if everything goes well. After the thread plan is run the return value will be extracted for you. Added an ifdef to be able to switch between the LLVM MCJIT and the standand JIT. We currently have the standard JIT selected because we have some work to do to get the MCJIT fuctioning properly. Added the ability to call functions with 6 argument in the x86_64 ABI. Added the ability for GDBRemoteCommunicationClient to detect if the allocate and deallocate memory packets are supported and to not call allocate memory ("_M") or deallocate ("_m") if we find they aren't supported. Modified the ProcessGDBRemote::DoAllocateMemory(...) and ProcessGDBRemote::DoDeallocateMemory(...) to be able to deal with the allocate and deallocate memory packets not being supported. If they are not supported, ProcessGDBRemote will switch to calling "mmap" and "munmap" to allocate and deallocate memory instead using our trivial function call support. Modified the "void ProcessGDBRemote::DidLaunchOrAttach()" to correctly ignore the qHostInfo triple information if any was specified in the target. Currently if the target only specifies an architecture when creating the target: (lldb) target create --arch i386 a.out Then the vendor, os and environemnt will be adopted by the target. If the target was created with any triple that specifies more than the arch: (lldb) target create --arch i386-unknown-unknown a.out Then the target will maintain its triple and not adopt any new values. This can be used to help force bare board debugging where the dynamic loader for static files will get used and users can then use "target modules load ..." to set addressses for any files that are desired. Added back some convenience functions to the lldb_private::RegisterContext class for writing registers with unsigned values. Also made all RegisterContext constructors explicit to make sure we know when an integer is being converted to a RegisterValue. llvm-svn: 131370
2011-05-15 01:25:55 +00:00
if (target_triple.getEnvironmentName().size() == 0)
target_triple.setEnvironment (remote_triple.getEnvironment());
}
}
}
}
else
{
// The target doesn't have a valid architecture yet, set it from
// the architecture we got from the remote GDB server
target_arch = gdb_remote_arch;
}
}
}
}
void
ProcessGDBRemote::DidLaunch ()
{
DidLaunchOrAttach ();
}
Error
ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
{
Error error;
// Clear out and clean up from any current state
Clear();
if (attach_pid != LLDB_INVALID_PROCESS_ID)
{
// Make sure we aren't already connected?
if (!m_gdb_comm.IsConnected())
{
char host_port[128];
snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
char connect_url[128];
snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
error = StartDebugserverProcess (host_port);
if (error.Fail())
{
const char *error_string = error.AsCString();
if (error_string == NULL)
error_string = "unable to launch " DEBUGSERVER_BASENAME;
SetExitStatus (-1, error_string);
}
else
{
error = ConnectToDebugserver (connect_url);
}
}
if (error.Success())
{
char packet[64];
const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%llx", attach_pid);
SetID (attach_pid);
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));
}
}
return error;
}
size_t
ProcessGDBRemote::AttachInputReaderCallback
(
void *baton,
InputReader *reader,
lldb::InputReaderAction notification,
const char *bytes,
size_t bytes_len
)
{
if (notification == eInputReaderGotToken)
{
ProcessGDBRemote *gdb_process = (ProcessGDBRemote *)baton;
if (gdb_process->m_waiting_for_attach)
gdb_process->m_waiting_for_attach = false;
reader->SetIsDone(true);
return 1;
}
return 0;
}
Error
ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait_for_launch)
{
Error error;
// Clear out and clean up from any current state
Clear();
if (process_name && process_name[0])
{
// Make sure we aren't already connected?
if (!m_gdb_comm.IsConnected())
{
char host_port[128];
snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
char connect_url[128];
snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
error = StartDebugserverProcess (host_port);
if (error.Fail())
{
const char *error_string = error.AsCString();
if (error_string == NULL)
error_string = "unable to launch " DEBUGSERVER_BASENAME;
SetExitStatus (-1, error_string);
}
else
{
error = ConnectToDebugserver (connect_url);
}
}
if (error.Success())
{
StreamString packet;
if (wait_for_launch)
packet.PutCString("vAttachWait");
else
packet.PutCString("vAttachName");
packet.PutChar(';');
packet.PutBytesAsRawHex8(process_name, strlen(process_name), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize()));
}
}
return error;
}
void
ProcessGDBRemote::DidAttach ()
{
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 01:58:07 +00:00
DidLaunchOrAttach ();
}
Error
ProcessGDBRemote::WillResume ()
{
m_continue_c_tids.clear();
m_continue_C_tids.clear();
m_continue_s_tids.clear();
m_continue_S_tids.clear();
return Error();
}
Error
ProcessGDBRemote::DoResume ()
{
Error error;
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::Resume()");
Fixed a race condition that could cause ProcessGDBRemote::DoResume() to return an error saying the resume timed out. Previously the thread that was trying to resume the process would eventually call ProcessGDBRemote::DoResume() which would broadcast an event over to the async GDB remote thread which would sent the continue packet to the remote gdb server. Right after this was sent, it would set a predicate boolean value (protected by a mutex and condition) and then the thread that issued the ProcessGDBRemote::DoResume() would then wait for that condition variable to be set. If the async gdb thread was too quick though, the predicate boolean value could have been set to true and back to false by the time the thread that issued the ProcessGDBRemote::DoResume() checks the boolean value. So we can't use the predicate value as a handshake. I have changed the code over to using a Event by having the GDB remote communication object post an event: GDBRemoteCommunication::eBroadcastBitRunPacketSent This allows reliable handshaking between the two threads and avoids the erroneous ProcessGDBRemote::DoResume() errors. Added a host backtrace service to allow in process backtraces when trying to track down tricky issues. I need to see if LLVM has any backtracing abilities abstracted in it already, and if so, use that, but I needed something ASAP for the current issue I was working on. The static function is: void Host::Backtrace (Stream &strm, uint32_t max_frames); And it will backtrace at most "max_frames" frames for the current thread and can be used with any of the Stream subclasses for logging. llvm-svn: 120793
2010-12-03 06:02:24 +00:00
Listener listener ("gdb-remote.resume-packet-sent");
if (listener.StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent))
{
StreamString continue_packet;
bool continue_packet_error = false;
if (m_gdb_comm.HasAnyVContSupport ())
{
continue_packet.PutCString ("vCont");
if (!m_continue_c_tids.empty())
{
if (m_gdb_comm.GetVContSupported ('c'))
{
for (tid_collection::const_iterator t_pos = m_continue_c_tids.begin(), t_end = m_continue_c_tids.end(); t_pos != t_end; ++t_pos)
continue_packet.Printf(";c:%4.4llx", *t_pos);
}
else
continue_packet_error = true;
}
if (!continue_packet_error && !m_continue_C_tids.empty())
{
if (m_gdb_comm.GetVContSupported ('C'))
{
for (tid_sig_collection::const_iterator s_pos = m_continue_C_tids.begin(), s_end = m_continue_C_tids.end(); s_pos != s_end; ++s_pos)
continue_packet.Printf(";C%2.2x:%4.4llx", s_pos->second, s_pos->first);
}
else
continue_packet_error = true;
}
if (!continue_packet_error && !m_continue_s_tids.empty())
{
if (m_gdb_comm.GetVContSupported ('s'))
{
for (tid_collection::const_iterator t_pos = m_continue_s_tids.begin(), t_end = m_continue_s_tids.end(); t_pos != t_end; ++t_pos)
continue_packet.Printf(";s:%4.4llx", *t_pos);
}
else
continue_packet_error = true;
}
if (!continue_packet_error && !m_continue_S_tids.empty())
{
if (m_gdb_comm.GetVContSupported ('S'))
{
for (tid_sig_collection::const_iterator s_pos = m_continue_S_tids.begin(), s_end = m_continue_S_tids.end(); s_pos != s_end; ++s_pos)
continue_packet.Printf(";S%2.2x:%4.4llx", s_pos->second, s_pos->first);
}
else
continue_packet_error = true;
}
if (continue_packet_error)
continue_packet.GetString().clear();
}
else
continue_packet_error = true;
if (continue_packet_error)
{
// Either no vCont support, or we tried to use part of the vCont
// packet that wasn't supported by the remote GDB server.
// We need to try and make a simple packet that can do our continue
const size_t num_threads = GetThreadList().GetSize();
const size_t num_continue_c_tids = m_continue_c_tids.size();
const size_t num_continue_C_tids = m_continue_C_tids.size();
const size_t num_continue_s_tids = m_continue_s_tids.size();
const size_t num_continue_S_tids = m_continue_S_tids.size();
if (num_continue_c_tids > 0)
{
if (num_continue_c_tids == num_threads)
{
// All threads are resuming...
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
m_gdb_comm.SetCurrentThreadForRun (-1);
continue_packet.PutChar ('c');
continue_packet_error = false;
}
else if (num_continue_c_tids == 1 &&
num_continue_C_tids == 0 &&
num_continue_s_tids == 0 &&
num_continue_S_tids == 0 )
{
// Only one thread is continuing
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
m_gdb_comm.SetCurrentThreadForRun (m_continue_c_tids.front());
continue_packet.PutChar ('c');
continue_packet_error = false;
}
}
if (continue_packet_error && num_continue_C_tids > 0)
{
if ((num_continue_C_tids + num_continue_c_tids) == num_threads &&
num_continue_C_tids > 0 &&
num_continue_s_tids == 0 &&
num_continue_S_tids == 0 )
{
const int continue_signo = m_continue_C_tids.front().second;
// Only one thread is continuing
if (num_continue_C_tids > 1)
{
// More that one thread with a signal, yet we don't have
// vCont support and we are being asked to resume each
// thread with a signal, we need to make sure they are
// all the same signal, or we can't issue the continue
// accurately with the current support...
if (num_continue_C_tids > 1)
{
continue_packet_error = false;
for (size_t i=1; i<m_continue_C_tids.size(); ++i)
{
if (m_continue_C_tids[i].second != continue_signo)
continue_packet_error = true;
}
}
if (!continue_packet_error)
m_gdb_comm.SetCurrentThreadForRun (-1);
}
else
{
// Set the continue thread ID
continue_packet_error = false;
m_gdb_comm.SetCurrentThreadForRun (m_continue_C_tids.front().first);
}
if (!continue_packet_error)
{
// Add threads continuing with the same signo...
continue_packet.Printf("C%2.2x", continue_signo);
}
}
}
if (continue_packet_error && num_continue_s_tids > 0)
{
if (num_continue_s_tids == num_threads)
{
// All threads are resuming...
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
m_gdb_comm.SetCurrentThreadForRun (-1);
continue_packet.PutChar ('s');
continue_packet_error = false;
}
else if (num_continue_c_tids == 0 &&
num_continue_C_tids == 0 &&
num_continue_s_tids == 1 &&
num_continue_S_tids == 0 )
{
// Only one thread is stepping
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
m_gdb_comm.SetCurrentThreadForRun (m_continue_s_tids.front());
continue_packet.PutChar ('s');
continue_packet_error = false;
}
}
if (!continue_packet_error && num_continue_S_tids > 0)
{
if (num_continue_S_tids == num_threads)
{
const int step_signo = m_continue_S_tids.front().second;
// Are all threads trying to step with the same signal?
continue_packet_error = false;
if (num_continue_S_tids > 1)
{
for (size_t i=1; i<num_threads; ++i)
{
if (m_continue_S_tids[i].second != step_signo)
continue_packet_error = true;
}
}
if (!continue_packet_error)
{
// Add threads stepping with the same signo...
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
m_gdb_comm.SetCurrentThreadForRun (-1);
continue_packet.Printf("S%2.2x", step_signo);
}
}
else if (num_continue_c_tids == 0 &&
num_continue_C_tids == 0 &&
num_continue_s_tids == 0 &&
num_continue_S_tids == 1 )
{
// Only one thread is stepping with signal
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
m_gdb_comm.SetCurrentThreadForRun (m_continue_S_tids.front().first);
continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
continue_packet_error = false;
}
}
}
if (continue_packet_error)
{
error.SetErrorString ("can't make continue packet for this resume");
}
else
{
EventSP event_sp;
TimeValue timeout;
timeout = TimeValue::Now();
timeout.OffsetWithSeconds (5);
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize()));
if (listener.WaitForEvent (&timeout, event_sp) == false)
error.SetErrorString("Resume timed out.");
}
Fixed a race condition that could cause ProcessGDBRemote::DoResume() to return an error saying the resume timed out. Previously the thread that was trying to resume the process would eventually call ProcessGDBRemote::DoResume() which would broadcast an event over to the async GDB remote thread which would sent the continue packet to the remote gdb server. Right after this was sent, it would set a predicate boolean value (protected by a mutex and condition) and then the thread that issued the ProcessGDBRemote::DoResume() would then wait for that condition variable to be set. If the async gdb thread was too quick though, the predicate boolean value could have been set to true and back to false by the time the thread that issued the ProcessGDBRemote::DoResume() checks the boolean value. So we can't use the predicate value as a handshake. I have changed the code over to using a Event by having the GDB remote communication object post an event: GDBRemoteCommunication::eBroadcastBitRunPacketSent This allows reliable handshaking between the two threads and avoids the erroneous ProcessGDBRemote::DoResume() errors. Added a host backtrace service to allow in process backtraces when trying to track down tricky issues. I need to see if LLVM has any backtracing abilities abstracted in it already, and if so, use that, but I needed something ASAP for the current issue I was working on. The static function is: void Host::Backtrace (Stream &strm, uint32_t max_frames); And it will backtrace at most "max_frames" frames for the current thread and can be used with any of the Stream subclasses for logging. llvm-svn: 120793
2010-12-03 06:02:24 +00:00
}
return error;
}
uint32_t
ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
{
// locker will keep a mutex locked until it goes out of scope
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD));
if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
log->Printf ("ProcessGDBRemote::%s (pid = %llu)", __FUNCTION__, GetID());
// Update the thread list's stop id immediately so we don't recurse into this function.
std::vector<lldb::tid_t> thread_ids;
bool sequence_mutex_unavailable = false;
const size_t num_thread_ids = m_gdb_comm.GetCurrentThreadIDs (thread_ids, sequence_mutex_unavailable);
if (num_thread_ids > 0)
{
for (size_t i=0; i<num_thread_ids; ++i)
{
tid_t tid = thread_ids[i];
ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
if (!thread_sp)
thread_sp.reset (new ThreadGDBRemote (*this, tid));
new_thread_list.AddThread(thread_sp);
}
}
if (sequence_mutex_unavailable == false)
SetThreadStopInfo (m_last_stop_packet);
return new_thread_list.GetSize(false);
}
StateType
ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
{
stop_packet.SetFilePos (0);
const char stop_type = stop_packet.GetChar();
switch (stop_type)
{
case 'T':
case 'S':
{
if (GetStopID() == 0)
{
// Our first stop, make sure we have a process ID, and also make
// sure we know about our registers
if (GetID() == LLDB_INVALID_PROCESS_ID)
{
lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
if (pid != LLDB_INVALID_PROCESS_ID)
SetID (pid);
}
BuildDynamicRegisterInfo (true);
}
// Stop with signal and thread info
const uint8_t signo = stop_packet.GetHexU8();
std::string name;
std::string value;
std::string thread_name;
std::string reason;
std::string description;
uint32_t exc_type = 0;
std::vector<addr_t> exc_data;
uint32_t tid = LLDB_INVALID_THREAD_ID;
addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
uint32_t exc_data_count = 0;
Put more smarts into the RegisterContext base class. Now the base class has a method: void RegisterContext::InvalidateIfNeeded (bool force); Each time this function is called, when "force" is false, it will only call the pure virtual "virtual void RegisterContext::InvalideAllRegisters()" if the register context's stop ID doesn't match that of the process. When the stop ID doesn't match, or "force" is true, the base class will clear its cached registers and the RegisterContext will update its stop ID to match that of the process. This helps make it easier to correctly flush the register context (possibly from multiple locations depending on when and where new registers are availabe) without inadvertently clearing the register cache when it doesn't need to be. Modified the ProcessGDBRemote plug-in to be much more efficient when it comes to: - caching the expedited registers in the stop reply packets (we were ignoring these before and it was causing us to read at least three registers every time we stopped that were already supplied in the stop reply packet). - When a thread has no stop reason, don't keep asking for the thread stopped info. Prior to this fix we would continually send a qThreadStopInfo packet over and over when any thread stop info was requested. We now note the stop ID that the stop info was requested for and avoid multiple requests. Cleaned up some of the expression code to not look for ClangExpressionVariable objects up by name since they are now shared pointers and we can just look for the exact pointer match and avoid possible errors. Fixed an bug in the ValueObject code that would cause children to not be displayed. llvm-svn: 123127
2011-01-09 21:07:35 +00:00
ThreadSP thread_sp;
while (stop_packet.GetNameColonValue(name, value))
{
if (name.compare("metype") == 0)
{
// exception type in big endian hex
exc_type = Args::StringToUInt32 (value.c_str(), 0, 16);
}
else if (name.compare("mecount") == 0)
{
// exception count in big endian hex
exc_data_count = Args::StringToUInt32 (value.c_str(), 0, 16);
}
else if (name.compare("medata") == 0)
{
// exception data in big endian hex
exc_data.push_back(Args::StringToUInt64 (value.c_str(), 0, 16));
}
else if (name.compare("thread") == 0)
{
// thread in big endian hex
tid = Args::StringToUInt32 (value.c_str(), 0, 16);
// m_thread_list does have its own mutex, but we need to
// hold onto the mutex between the call to m_thread_list.FindThreadByID(...)
// and the m_thread_list.AddThread(...) so it doesn't change on us
Mutex::Locker locker (m_thread_list.GetMutex ());
Put more smarts into the RegisterContext base class. Now the base class has a method: void RegisterContext::InvalidateIfNeeded (bool force); Each time this function is called, when "force" is false, it will only call the pure virtual "virtual void RegisterContext::InvalideAllRegisters()" if the register context's stop ID doesn't match that of the process. When the stop ID doesn't match, or "force" is true, the base class will clear its cached registers and the RegisterContext will update its stop ID to match that of the process. This helps make it easier to correctly flush the register context (possibly from multiple locations depending on when and where new registers are availabe) without inadvertently clearing the register cache when it doesn't need to be. Modified the ProcessGDBRemote plug-in to be much more efficient when it comes to: - caching the expedited registers in the stop reply packets (we were ignoring these before and it was causing us to read at least three registers every time we stopped that were already supplied in the stop reply packet). - When a thread has no stop reason, don't keep asking for the thread stopped info. Prior to this fix we would continually send a qThreadStopInfo packet over and over when any thread stop info was requested. We now note the stop ID that the stop info was requested for and avoid multiple requests. Cleaned up some of the expression code to not look for ClangExpressionVariable objects up by name since they are now shared pointers and we can just look for the exact pointer match and avoid possible errors. Fixed an bug in the ValueObject code that would cause children to not be displayed. llvm-svn: 123127
2011-01-09 21:07:35 +00:00
thread_sp = m_thread_list.FindThreadByID(tid, false);
if (!thread_sp)
{
// Create the thread if we need to
thread_sp.reset (new ThreadGDBRemote (*this, tid));
m_thread_list.AddThread(thread_sp);
}
}
else if (name.compare("hexname") == 0)
{
StringExtractor name_extractor;
// Swap "value" over into "name_extractor"
name_extractor.GetStringRef().swap(value);
// Now convert the HEX bytes into a string value
name_extractor.GetHexByteString (value);
thread_name.swap (value);
}
else if (name.compare("name") == 0)
{
thread_name.swap (value);
}
else if (name.compare("qaddr") == 0)
{
thread_dispatch_qaddr = Args::StringToUInt64 (value.c_str(), 0, 16);
}
else if (name.compare("reason") == 0)
{
reason.swap(value);
}
else if (name.compare("description") == 0)
{
StringExtractor desc_extractor;
// Swap "value" over into "name_extractor"
desc_extractor.GetStringRef().swap(value);
// Now convert the HEX bytes into a string value
desc_extractor.GetHexByteString (thread_name);
}
Put more smarts into the RegisterContext base class. Now the base class has a method: void RegisterContext::InvalidateIfNeeded (bool force); Each time this function is called, when "force" is false, it will only call the pure virtual "virtual void RegisterContext::InvalideAllRegisters()" if the register context's stop ID doesn't match that of the process. When the stop ID doesn't match, or "force" is true, the base class will clear its cached registers and the RegisterContext will update its stop ID to match that of the process. This helps make it easier to correctly flush the register context (possibly from multiple locations depending on when and where new registers are availabe) without inadvertently clearing the register cache when it doesn't need to be. Modified the ProcessGDBRemote plug-in to be much more efficient when it comes to: - caching the expedited registers in the stop reply packets (we were ignoring these before and it was causing us to read at least three registers every time we stopped that were already supplied in the stop reply packet). - When a thread has no stop reason, don't keep asking for the thread stopped info. Prior to this fix we would continually send a qThreadStopInfo packet over and over when any thread stop info was requested. We now note the stop ID that the stop info was requested for and avoid multiple requests. Cleaned up some of the expression code to not look for ClangExpressionVariable objects up by name since they are now shared pointers and we can just look for the exact pointer match and avoid possible errors. Fixed an bug in the ValueObject code that would cause children to not be displayed. llvm-svn: 123127
2011-01-09 21:07:35 +00:00
else if (name.size() == 2 && ::isxdigit(name[0]) && ::isxdigit(name[1]))
{
// We have a register number that contains an expedited
// register value. Lets supply this register to our thread
// so it won't have to go and read it.
if (thread_sp)
{
uint32_t reg = Args::StringToUInt32 (name.c_str(), UINT32_MAX, 16);
if (reg != UINT32_MAX)
{
StringExtractor reg_value_extractor;
// Swap "value" over into "reg_value_extractor"
reg_value_extractor.GetStringRef().swap(value);
if (!static_cast<ThreadGDBRemote *> (thread_sp.get())->PrivateSetRegisterValue (reg, reg_value_extractor))
{
Host::SetCrashDescriptionWithFormat("Setting thread register '%s' (decoded to %u (0x%x)) with value '%s' for stop packet: '%s'",
name.c_str(),
reg,
reg,
reg_value_extractor.GetStringRef().c_str(),
stop_packet.GetStringRef().c_str());
}
Put more smarts into the RegisterContext base class. Now the base class has a method: void RegisterContext::InvalidateIfNeeded (bool force); Each time this function is called, when "force" is false, it will only call the pure virtual "virtual void RegisterContext::InvalideAllRegisters()" if the register context's stop ID doesn't match that of the process. When the stop ID doesn't match, or "force" is true, the base class will clear its cached registers and the RegisterContext will update its stop ID to match that of the process. This helps make it easier to correctly flush the register context (possibly from multiple locations depending on when and where new registers are availabe) without inadvertently clearing the register cache when it doesn't need to be. Modified the ProcessGDBRemote plug-in to be much more efficient when it comes to: - caching the expedited registers in the stop reply packets (we were ignoring these before and it was causing us to read at least three registers every time we stopped that were already supplied in the stop reply packet). - When a thread has no stop reason, don't keep asking for the thread stopped info. Prior to this fix we would continually send a qThreadStopInfo packet over and over when any thread stop info was requested. We now note the stop ID that the stop info was requested for and avoid multiple requests. Cleaned up some of the expression code to not look for ClangExpressionVariable objects up by name since they are now shared pointers and we can just look for the exact pointer match and avoid possible errors. Fixed an bug in the ValueObject code that would cause children to not be displayed. llvm-svn: 123127
2011-01-09 21:07:35 +00:00
}
}
}
}
if (thread_sp)
{
ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr);
gdb_thread->SetName (thread_name.empty() ? NULL : thread_name.c_str());
if (exc_type != 0)
{
const size_t exc_data_size = exc_data.size();
Abtracted the old "lldb_private::Thread::StopInfo" into an abtract class. This will allow debugger plug-ins to make any instance of "lldb_private::StopInfo" that can completely describe any stop reason. It also provides a framework for doing intelligent things with the stop info at important times in the lifetime of the inferior. Examples include the signal stop info in StopInfoUnixSignal. It will check with the process to see that the current action is for the signal. These actions include wether to stop for the signal, wether the notify that the signal was hit, and wether to pass the signal along to the inferior process. The StopInfoUnixSignal class overrides the "ShouldStop()" method of StopInfo and this allows the stop info to determine if it should stop at the signal or continue the process. StopInfo subclasses must override the following functions: virtual lldb::StopReason GetStopReason () const = 0; virtual const char * GetDescription () = 0; StopInfo subclasses can override the following functions: // If the subclass returns "false", the inferior will resume. The default // version of this function returns "true" which means the default stop // info will stop the process. The breakpoint subclass will check if // the breakpoint wants us to stop by calling any installed callback on // the breakpoint, and also checking if the breakpoint is for the current // thread. Signals will check if they should stop based off of the // UnixSignal settings in the process. virtual bool ShouldStop (Event *event_ptr); // Sublasses can state if they want to notify the debugger when "ShouldStop" // returns false. This would be handy for breakpoints where you want to // log information and continue and is also used by the signal stop info // to notify that a signal was received (after it checks with the process // signal settings). virtual bool ShouldNotify (Event *event_ptr) { return false; } // Allow subclasses to do something intelligent right before we resume. // The signal class will figure out if the signal should be propagated // to the inferior process and pass that along to the debugger plug-ins. virtual void WillResume (lldb::StateType resume_state) { // By default, don't do anything } The support the Mach exceptions was moved into the lldb/source/Plugins/Process/Utility folder and now doesn't polute the lldb_private::Thread class with platform specific code. llvm-svn: 110184
2010-08-04 01:40:35 +00:00
gdb_thread->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp,
exc_type,
exc_data_size,
exc_data_size >= 1 ? exc_data[0] : 0,
exc_data_size >= 2 ? exc_data[1] : 0,
exc_data_size >= 3 ? exc_data[2] : 0));
}
else
{
bool handled = false;
if (!reason.empty())
{
if (reason.compare("trace") == 0)
{
gdb_thread->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
handled = true;
}
else if (reason.compare("breakpoint") == 0)
{
addr_t pc = gdb_thread->GetRegisterContext()->GetPC();
lldb::BreakpointSiteSP bp_site_sp = gdb_thread->GetProcess().GetBreakpointSiteList().FindByAddress(pc);
if (bp_site_sp)
{
// If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
// we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
// will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
if (bp_site_sp->ValidForThisThread (gdb_thread))
{
gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
handled = true;
}
}
if (!handled)
{
gdb_thread->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
}
}
else if (reason.compare("trap") == 0)
{
// Let the trap just use the standard signal stop reason below...
}
else if (reason.compare("watchpoint") == 0)
{
break_id_t watch_id = LLDB_INVALID_WATCH_ID;
// TODO: locate the watchpoint somehow...
gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id));
handled = true;
}
else if (reason.compare("exception") == 0)
{
gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str()));
handled = true;
}
}
if (signo)
{
if (signo == SIGTRAP)
{
// Currently we are going to assume SIGTRAP means we are either
// hitting a breakpoint or hardware single stepping.
addr_t pc = gdb_thread->GetRegisterContext()->GetPC();
lldb::BreakpointSiteSP bp_site_sp = gdb_thread->GetProcess().GetBreakpointSiteList().FindByAddress(pc);
if (bp_site_sp)
{
// If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
// we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
// will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
if (bp_site_sp->ValidForThisThread (gdb_thread))
{
gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
handled = true;
}
}
if (!handled)
{
// TODO: check for breakpoint or trap opcode in case there is a hard
// coded software trap
gdb_thread->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
handled = true;
}
}
if (!handled)
gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo));
}
else
{
Abtracted the old "lldb_private::Thread::StopInfo" into an abtract class. This will allow debugger plug-ins to make any instance of "lldb_private::StopInfo" that can completely describe any stop reason. It also provides a framework for doing intelligent things with the stop info at important times in the lifetime of the inferior. Examples include the signal stop info in StopInfoUnixSignal. It will check with the process to see that the current action is for the signal. These actions include wether to stop for the signal, wether the notify that the signal was hit, and wether to pass the signal along to the inferior process. The StopInfoUnixSignal class overrides the "ShouldStop()" method of StopInfo and this allows the stop info to determine if it should stop at the signal or continue the process. StopInfo subclasses must override the following functions: virtual lldb::StopReason GetStopReason () const = 0; virtual const char * GetDescription () = 0; StopInfo subclasses can override the following functions: // If the subclass returns "false", the inferior will resume. The default // version of this function returns "true" which means the default stop // info will stop the process. The breakpoint subclass will check if // the breakpoint wants us to stop by calling any installed callback on // the breakpoint, and also checking if the breakpoint is for the current // thread. Signals will check if they should stop based off of the // UnixSignal settings in the process. virtual bool ShouldStop (Event *event_ptr); // Sublasses can state if they want to notify the debugger when "ShouldStop" // returns false. This would be handy for breakpoints where you want to // log information and continue and is also used by the signal stop info // to notify that a signal was received (after it checks with the process // signal settings). virtual bool ShouldNotify (Event *event_ptr) { return false; } // Allow subclasses to do something intelligent right before we resume. // The signal class will figure out if the signal should be propagated // to the inferior process and pass that along to the debugger plug-ins. virtual void WillResume (lldb::StateType resume_state) { // By default, don't do anything } The support the Mach exceptions was moved into the lldb/source/Plugins/Process/Utility folder and now doesn't polute the lldb_private::Thread class with platform specific code. llvm-svn: 110184
2010-08-04 01:40:35 +00:00
StopInfoSP invalid_stop_info_sp;
gdb_thread->SetStopInfo (invalid_stop_info_sp);
}
if (!description.empty())
{
lldb::StopInfoSP stop_info_sp (gdb_thread->GetStopInfo ());
if (stop_info_sp)
{
stop_info_sp->SetDescription (description.c_str());
While tracking down memory consumption issue a few things were needed: the ability to dump more information about modules in "target modules list". We can now dump the shared pointer reference count for modules, the pointer to the module itself (in case performance tools can help track down who has references to said pointer), and the modification time. Added "target delete [target-idx ...]" to be able to delete targets when they are no longer needed. This will help track down memory usage issues and help to resolve when module ref counts keep getting incremented. If the command gets no arguments, the currently selected target will be deleted. If any arguments are given, they must all be valid target indexes (use the "target list" command to get the current target indexes). Took care of a bunch of "no newline at end of file" warnings. TimeValue objects can now dump their time to a lldb_private::Stream object. Modified the "target modules list --global" command to not error out if there are no targets since it doesn't require a target. Fixed an issue in the MacOSX DYLD dynamic loader plug-in where if a shared library was updated on disk, we would keep using the older one, even if it was updated. Don't allow the ModuleList::GetSharedModule(...) to return an empty module. Previously we could specify a valid path on disc to a module, and specify an architecture that wasn't contained in that module and get a shared pointer to a module that wouldn't be able to return an object file or a symbol file. We now make sure an object file can be extracted prior to adding the shared pointer to the module to get added to the shared list. llvm-svn: 137196
2011-08-10 02:10:13 +00:00
}
else
{
gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str()));
}
}
}
}
return eStateStopped;
}
break;
case 'W':
// process exited
return eStateExited;
default:
break;
}
return eStateInvalid;
}
void
ProcessGDBRemote::RefreshStateAfterStop ()
{
// Let all threads recover from stopping and do any clean up based
// on the previous thread state (if any).
m_thread_list.RefreshStateAfterStop();
SetThreadStopInfo (m_last_stop_packet);
}
Error
ProcessGDBRemote::DoHalt (bool &caused_stop)
{
Error error;
bool timed_out = false;
Mutex::Locker locker;
if (m_public_state.GetValue() == eStateAttaching)
2010-11-18 05:57:03 +00:00
{
// We are being asked to halt during an attach. We need to just close
// our file handle and debugserver will go away, and we can be done...
m_gdb_comm.Disconnect();
}
else
{
if (!m_gdb_comm.SendInterrupt (locker, 2, caused_stop, timed_out))
{
if (timed_out)
error.SetErrorString("timed out sending interrupt packet");
else
error.SetErrorString("unknown error sending interrupt packet");
}
2010-11-18 05:57:03 +00:00
}
return error;
}
Error
ProcessGDBRemote::InterruptIfRunning
(
bool discard_thread_plans,
bool catch_stop_event,
EventSP &stop_event_sp
)
{
Error error;
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
bool paused_private_state_thread = false;
const bool is_running = m_gdb_comm.IsRunning();
if (log)
log->Printf ("ProcessGDBRemote::InterruptIfRunning(discard_thread_plans=%i, catch_stop_event=%i) is_running=%i",
discard_thread_plans,
catch_stop_event,
is_running);
if (discard_thread_plans)
{
if (log)
log->Printf ("ProcessGDBRemote::InterruptIfRunning() discarding all thread plans");
m_thread_list.DiscardThreadPlans();
}
if (is_running)
{
if (catch_stop_event)
{
if (log)
log->Printf ("ProcessGDBRemote::InterruptIfRunning() pausing private state thread");
PausePrivateStateThread();
paused_private_state_thread = true;
}
bool timed_out = false;
bool sent_interrupt = false;
Mutex::Locker locker;
if (!m_gdb_comm.SendInterrupt (locker, 1, sent_interrupt, timed_out))
{
if (timed_out)
error.SetErrorString("timed out sending interrupt packet");
else
error.SetErrorString("unknown error sending interrupt packet");
if (paused_private_state_thread)
ResumePrivateStateThread();
return error;
}
if (catch_stop_event)
{
// LISTEN HERE
TimeValue timeout_time;
timeout_time = TimeValue::Now();
timeout_time.OffsetWithSeconds(5);
StateType state = WaitForStateChangedEventsPrivate (&timeout_time, stop_event_sp);
timed_out = state == eStateInvalid;
if (log)
log->Printf ("ProcessGDBRemote::InterruptIfRunning() catch stop event: state = %s, timed-out=%i", StateAsCString(state), timed_out);
if (timed_out)
error.SetErrorString("unable to verify target stopped");
}
if (paused_private_state_thread)
{
if (log)
log->Printf ("ProcessGDBRemote::InterruptIfRunning() resuming private state thread");
ResumePrivateStateThread();
}
}
return error;
}
Error
ProcessGDBRemote::WillDetach ()
{
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::WillDetach()");
bool discard_thread_plans = true;
bool catch_stop_event = true;
EventSP event_sp;
return InterruptIfRunning (discard_thread_plans, catch_stop_event, event_sp);
}
Error
ProcessGDBRemote::DoDetach()
{
Error error;
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::DoDetach()");
DisableAllBreakpointSites ();
m_thread_list.DiscardThreadPlans();
size_t response_size = m_gdb_comm.SendPacket ("D", 1);
if (log)
{
if (response_size)
log->PutCString ("ProcessGDBRemote::DoDetach() detach packet sent successfully");
else
log->PutCString ("ProcessGDBRemote::DoDetach() detach packet send failed");
}
// Sleep for one second to let the process get all detached...
StopAsyncThread ();
SetPrivateState (eStateDetached);
ResumePrivateStateThread();
//KillDebugserverProcess ();
return error;
}
Error
ProcessGDBRemote::DoDestroy ()
{
Error error;
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::DoDestroy()");
// Interrupt if our inferior is running...
if (m_gdb_comm.IsConnected())
{
if (m_public_state.GetValue() != eStateAttaching)
{
StringExtractorGDBRemote response;
bool send_async = true;
if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response, send_async))
{
char packet_cmd = response.GetChar(0);
if (packet_cmd == 'W' || packet_cmd == 'X')
{
SetLastStopPacket (response);
SetExitStatus(response.GetHexU8(), NULL);
}
}
else
{
SetExitStatus(SIGABRT, NULL);
//error.SetErrorString("kill packet failed");
}
}
}
StopAsyncThread ();
KillDebugserverProcess ();
return error;
}
//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------
bool
ProcessGDBRemote::IsAlive ()
{
return m_gdb_comm.IsConnected() && m_private_state.GetValue() != eStateExited;
}
addr_t
ProcessGDBRemote::GetImageInfoAddress()
{
if (!m_gdb_comm.IsRunning())
{
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse("qShlibInfoAddr", ::strlen ("qShlibInfoAddr"), response, false))
{
if (response.IsNormalResponse())
return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
}
}
return LLDB_INVALID_ADDRESS;
}
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
size_t
ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
{
if (size > m_max_memory_size)
{
// Keep memory read sizes down to a sane limit. This function will be
// called multiple times in order to complete the task by
// lldb_private::Process so it is ok to do this.
size = m_max_memory_size;
}
char packet[64];
const int packet_len = ::snprintf (packet, sizeof(packet), "m%llx,%zx", (uint64_t)addr, size);
assert (packet_len + 1 < sizeof(packet));
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true))
{
if (response.IsNormalResponse())
{
error.Clear();
return response.GetHexBytes(buf, size, '\xdd');
}
else if (response.IsErrorResponse())
error.SetErrorStringWithFormat("gdb remote returned an error: %s", response.GetStringRef().c_str());
else if (response.IsUnsupportedResponse())
error.SetErrorStringWithFormat("'%s' packet unsupported", packet);
else
error.SetErrorStringWithFormat("unexpected response to '%s': '%s'", packet, response.GetStringRef().c_str());
}
else
{
error.SetErrorStringWithFormat("failed to sent packet: '%s'", packet);
}
return 0;
}
size_t
ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
{
if (size > m_max_memory_size)
{
// Keep memory read sizes down to a sane limit. This function will be
// called multiple times in order to complete the task by
// lldb_private::Process so it is ok to do this.
size = m_max_memory_size;
}
StreamString packet;
packet.Printf("M%llx,%zx:", addr, size);
packet.PutBytesAsRawHex8(buf, size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true))
{
if (response.IsOKResponse())
{
error.Clear();
return size;
}
else if (response.IsErrorResponse())
error.SetErrorStringWithFormat("gdb remote returned an error: %s", response.GetStringRef().c_str());
else if (response.IsUnsupportedResponse())
error.SetErrorStringWithFormat("'%s' packet unsupported", packet.GetString().c_str());
else
error.SetErrorStringWithFormat("unexpected response to '%s': '%s'", packet.GetString().c_str(), response.GetStringRef().c_str());
}
else
{
error.SetErrorStringWithFormat("failed to sent packet: '%s'", packet.GetString().c_str());
}
return 0;
}
lldb::addr_t
ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
{
addr_t allocated_addr = LLDB_INVALID_ADDRESS;
Added the ability to get the return value from a ThreadPlanCallFunction thread plan. In order to get the return value, you can call: void ThreadPlanCallFunction::RequestReturnValue (lldb::ValueSP &return_value_sp); This registers a shared pointer to a return value that will get filled in if everything goes well. After the thread plan is run the return value will be extracted for you. Added an ifdef to be able to switch between the LLVM MCJIT and the standand JIT. We currently have the standard JIT selected because we have some work to do to get the MCJIT fuctioning properly. Added the ability to call functions with 6 argument in the x86_64 ABI. Added the ability for GDBRemoteCommunicationClient to detect if the allocate and deallocate memory packets are supported and to not call allocate memory ("_M") or deallocate ("_m") if we find they aren't supported. Modified the ProcessGDBRemote::DoAllocateMemory(...) and ProcessGDBRemote::DoDeallocateMemory(...) to be able to deal with the allocate and deallocate memory packets not being supported. If they are not supported, ProcessGDBRemote will switch to calling "mmap" and "munmap" to allocate and deallocate memory instead using our trivial function call support. Modified the "void ProcessGDBRemote::DidLaunchOrAttach()" to correctly ignore the qHostInfo triple information if any was specified in the target. Currently if the target only specifies an architecture when creating the target: (lldb) target create --arch i386 a.out Then the vendor, os and environemnt will be adopted by the target. If the target was created with any triple that specifies more than the arch: (lldb) target create --arch i386-unknown-unknown a.out Then the target will maintain its triple and not adopt any new values. This can be used to help force bare board debugging where the dynamic loader for static files will get used and users can then use "target modules load ..." to set addressses for any files that are desired. Added back some convenience functions to the lldb_private::RegisterContext class for writing registers with unsigned values. Also made all RegisterContext constructors explicit to make sure we know when an integer is being converted to a RegisterValue. llvm-svn: 131370
2011-05-15 01:25:55 +00:00
LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();
switch (supported)
{
case eLazyBoolCalculate:
case eLazyBoolYes:
allocated_addr = m_gdb_comm.AllocateMemory (size, permissions);
if (allocated_addr != LLDB_INVALID_ADDRESS || supported == eLazyBoolYes)
return allocated_addr;
case eLazyBoolNo:
// Call mmap() to create memory in the inferior..
unsigned prot = 0;
if (permissions & lldb::ePermissionsReadable)
prot |= eMmapProtRead;
if (permissions & lldb::ePermissionsWritable)
prot |= eMmapProtWrite;
if (permissions & lldb::ePermissionsExecutable)
prot |= eMmapProtExec;
if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0))
m_addr_to_mmap_size[allocated_addr] = size;
else
allocated_addr = LLDB_INVALID_ADDRESS;
break;
}
if (allocated_addr == LLDB_INVALID_ADDRESS)
error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
else
error.Clear();
return allocated_addr;
}
Error
ProcessGDBRemote::GetMemoryRegionInfo (addr_t load_addr,
MemoryRegionInfo &region_info)
{
Error error (m_gdb_comm.GetMemoryRegionInfo (load_addr, region_info));
return error;
}
Error
ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr)
{
Error error;
Added the ability to get the return value from a ThreadPlanCallFunction thread plan. In order to get the return value, you can call: void ThreadPlanCallFunction::RequestReturnValue (lldb::ValueSP &return_value_sp); This registers a shared pointer to a return value that will get filled in if everything goes well. After the thread plan is run the return value will be extracted for you. Added an ifdef to be able to switch between the LLVM MCJIT and the standand JIT. We currently have the standard JIT selected because we have some work to do to get the MCJIT fuctioning properly. Added the ability to call functions with 6 argument in the x86_64 ABI. Added the ability for GDBRemoteCommunicationClient to detect if the allocate and deallocate memory packets are supported and to not call allocate memory ("_M") or deallocate ("_m") if we find they aren't supported. Modified the ProcessGDBRemote::DoAllocateMemory(...) and ProcessGDBRemote::DoDeallocateMemory(...) to be able to deal with the allocate and deallocate memory packets not being supported. If they are not supported, ProcessGDBRemote will switch to calling "mmap" and "munmap" to allocate and deallocate memory instead using our trivial function call support. Modified the "void ProcessGDBRemote::DidLaunchOrAttach()" to correctly ignore the qHostInfo triple information if any was specified in the target. Currently if the target only specifies an architecture when creating the target: (lldb) target create --arch i386 a.out Then the vendor, os and environemnt will be adopted by the target. If the target was created with any triple that specifies more than the arch: (lldb) target create --arch i386-unknown-unknown a.out Then the target will maintain its triple and not adopt any new values. This can be used to help force bare board debugging where the dynamic loader for static files will get used and users can then use "target modules load ..." to set addressses for any files that are desired. Added back some convenience functions to the lldb_private::RegisterContext class for writing registers with unsigned values. Also made all RegisterContext constructors explicit to make sure we know when an integer is being converted to a RegisterValue. llvm-svn: 131370
2011-05-15 01:25:55 +00:00
LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();
switch (supported)
{
case eLazyBoolCalculate:
// We should never be deallocating memory without allocating memory
// first so we should never get eLazyBoolCalculate
error.SetErrorString ("tried to deallocate memory without ever allocating memory");
break;
case eLazyBoolYes:
if (!m_gdb_comm.DeallocateMemory (addr))
error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);
break;
case eLazyBoolNo:
// Call munmap() to deallocate memory in the inferior..
Added the ability to get the return value from a ThreadPlanCallFunction thread plan. In order to get the return value, you can call: void ThreadPlanCallFunction::RequestReturnValue (lldb::ValueSP &return_value_sp); This registers a shared pointer to a return value that will get filled in if everything goes well. After the thread plan is run the return value will be extracted for you. Added an ifdef to be able to switch between the LLVM MCJIT and the standand JIT. We currently have the standard JIT selected because we have some work to do to get the MCJIT fuctioning properly. Added the ability to call functions with 6 argument in the x86_64 ABI. Added the ability for GDBRemoteCommunicationClient to detect if the allocate and deallocate memory packets are supported and to not call allocate memory ("_M") or deallocate ("_m") if we find they aren't supported. Modified the ProcessGDBRemote::DoAllocateMemory(...) and ProcessGDBRemote::DoDeallocateMemory(...) to be able to deal with the allocate and deallocate memory packets not being supported. If they are not supported, ProcessGDBRemote will switch to calling "mmap" and "munmap" to allocate and deallocate memory instead using our trivial function call support. Modified the "void ProcessGDBRemote::DidLaunchOrAttach()" to correctly ignore the qHostInfo triple information if any was specified in the target. Currently if the target only specifies an architecture when creating the target: (lldb) target create --arch i386 a.out Then the vendor, os and environemnt will be adopted by the target. If the target was created with any triple that specifies more than the arch: (lldb) target create --arch i386-unknown-unknown a.out Then the target will maintain its triple and not adopt any new values. This can be used to help force bare board debugging where the dynamic loader for static files will get used and users can then use "target modules load ..." to set addressses for any files that are desired. Added back some convenience functions to the lldb_private::RegisterContext class for writing registers with unsigned values. Also made all RegisterContext constructors explicit to make sure we know when an integer is being converted to a RegisterValue. llvm-svn: 131370
2011-05-15 01:25:55 +00:00
{
MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
if (pos != m_addr_to_mmap_size.end() &&
InferiorCallMunmap(this, addr, pos->second))
m_addr_to_mmap_size.erase (pos);
else
error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);
Added the ability to get the return value from a ThreadPlanCallFunction thread plan. In order to get the return value, you can call: void ThreadPlanCallFunction::RequestReturnValue (lldb::ValueSP &return_value_sp); This registers a shared pointer to a return value that will get filled in if everything goes well. After the thread plan is run the return value will be extracted for you. Added an ifdef to be able to switch between the LLVM MCJIT and the standand JIT. We currently have the standard JIT selected because we have some work to do to get the MCJIT fuctioning properly. Added the ability to call functions with 6 argument in the x86_64 ABI. Added the ability for GDBRemoteCommunicationClient to detect if the allocate and deallocate memory packets are supported and to not call allocate memory ("_M") or deallocate ("_m") if we find they aren't supported. Modified the ProcessGDBRemote::DoAllocateMemory(...) and ProcessGDBRemote::DoDeallocateMemory(...) to be able to deal with the allocate and deallocate memory packets not being supported. If they are not supported, ProcessGDBRemote will switch to calling "mmap" and "munmap" to allocate and deallocate memory instead using our trivial function call support. Modified the "void ProcessGDBRemote::DidLaunchOrAttach()" to correctly ignore the qHostInfo triple information if any was specified in the target. Currently if the target only specifies an architecture when creating the target: (lldb) target create --arch i386 a.out Then the vendor, os and environemnt will be adopted by the target. If the target was created with any triple that specifies more than the arch: (lldb) target create --arch i386-unknown-unknown a.out Then the target will maintain its triple and not adopt any new values. This can be used to help force bare board debugging where the dynamic loader for static files will get used and users can then use "target modules load ..." to set addressses for any files that are desired. Added back some convenience functions to the lldb_private::RegisterContext class for writing registers with unsigned values. Also made all RegisterContext constructors explicit to make sure we know when an integer is being converted to a RegisterValue. llvm-svn: 131370
2011-05-15 01:25:55 +00:00
}
break;
}
return error;
}
//------------------------------------------------------------------
// Process STDIO
//------------------------------------------------------------------
size_t
ProcessGDBRemote::PutSTDIN (const char *src, size_t src_len, Error &error)
{
if (m_stdio_communication.IsConnected())
{
ConnectionStatus status;
m_stdio_communication.Write(src, src_len, status, NULL);
}
return 0;
}
Error
ProcessGDBRemote::EnableBreakpoint (BreakpointSite *bp_site)
{
Error error;
assert (bp_site != NULL);
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
user_id_t site_id = bp_site->GetID();
const addr_t addr = bp_site->GetLoadAddress();
if (log)
log->Printf ("ProcessGDBRemote::EnableBreakpoint (size_id = %llu) address = 0x%llx", site_id, (uint64_t)addr);
if (bp_site->IsEnabled())
{
if (log)
log->Printf ("ProcessGDBRemote::EnableBreakpoint (size_id = %llu) address = 0x%llx -- SUCCESS (already enabled)", site_id, (uint64_t)addr);
return error;
}
else
{
const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
if (bp_site->HardwarePreferred())
{
// Try and set hardware breakpoint, and if that fails, fall through
// and set a software breakpoint?
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointHardware))
{
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0)
{
bp_site->SetEnabled(true);
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
bp_site->SetType (BreakpointSite::eHardware);
return error;
}
}
}
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
{
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
{
bp_site->SetEnabled(true);
bp_site->SetType (BreakpointSite::eExternal);
return error;
}
}
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
return EnableSoftwareBreakpoint (bp_site);
}
if (log)
{
const char *err_string = error.AsCString();
log->Printf ("ProcessGDBRemote::EnableBreakpoint() error for breakpoint at 0x%8.8llx: %s",
bp_site->GetLoadAddress(),
err_string ? err_string : "NULL");
}
// We shouldn't reach here on a successful breakpoint enable...
if (error.Success())
error.SetErrorToGenericError();
return error;
}
Error
ProcessGDBRemote::DisableBreakpoint (BreakpointSite *bp_site)
{
Error error;
assert (bp_site != NULL);
addr_t addr = bp_site->GetLoadAddress();
user_id_t site_id = bp_site->GetID();
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
if (log)
log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %llu) addr = 0x%8.8llx", site_id, (uint64_t)addr);
if (bp_site->IsEnabled())
{
const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
BreakpointSite::Type bp_type = bp_site->GetType();
switch (bp_type)
{
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
case BreakpointSite::eSoftware:
error = DisableSoftwareBreakpoint (bp_site);
break;
case BreakpointSite::eHardware:
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
error.SetErrorToGenericError();
break;
case BreakpointSite::eExternal:
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
error.SetErrorToGenericError();
break;
}
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
if (error.Success())
bp_site->SetEnabled(false);
}
else
{
if (log)
log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %llu) addr = 0x%8.8llx -- SUCCESS (already disabled)", site_id, (uint64_t)addr);
return error;
}
if (error.Success())
error.SetErrorToGenericError();
return error;
}
// Pre-requisite: wp != NULL.
static GDBStoppointType
GetGDBStoppointType (Watchpoint *wp)
{
assert(wp);
bool watch_read = wp->WatchpointRead();
bool watch_write = wp->WatchpointWrite();
// watch_read and watch_write cannot both be false.
assert(watch_read || watch_write);
if (watch_read && watch_write)
return eWatchpointReadWrite;
else if (watch_read)
return eWatchpointRead;
else // Must be watch_write, then.
return eWatchpointWrite;
}
Error
ProcessGDBRemote::EnableWatchpoint (Watchpoint *wp)
{
Error error;
if (wp)
{
user_id_t watchID = wp->GetID();
addr_t addr = wp->GetLoadAddress();
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
if (log)
log->Printf ("ProcessGDBRemote::EnableWatchpoint(watchID = %llu)", watchID);
if (wp->IsEnabled())
{
if (log)
log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %llu) addr = 0x%8.8llx: watchpoint already enabled.", watchID, (uint64_t)addr);
return error;
}
GDBStoppointType type = GetGDBStoppointType(wp);
// Pass down an appropriate z/Z packet...
if (m_gdb_comm.SupportsGDBStoppointPacket (type))
{
if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, wp->GetByteSize()) == 0)
{
wp->SetEnabled(true);
return error;
}
else
error.SetErrorString("sending gdb watchpoint packet failed");
}
else
error.SetErrorString("watchpoints not supported");
}
else
{
error.SetErrorString("Watchpoint argument was NULL.");
}
if (error.Success())
error.SetErrorToGenericError();
return error;
}
Error
ProcessGDBRemote::DisableWatchpoint (Watchpoint *wp)
{
Error error;
if (wp)
{
user_id_t watchID = wp->GetID();
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
addr_t addr = wp->GetLoadAddress();
if (log)
log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %llu) addr = 0x%8.8llx", watchID, (uint64_t)addr);
if (!wp->IsEnabled())
{
if (log)
log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %llu) addr = 0x%8.8llx -- SUCCESS (already disabled)", watchID, (uint64_t)addr);
return error;
}
if (wp->IsHardware())
{
GDBStoppointType type = GetGDBStoppointType(wp);
// Pass down an appropriate z/Z packet...
if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, wp->GetByteSize()) == 0)
{
wp->SetEnabled(false);
return error;
}
else
error.SetErrorString("sending gdb watchpoint packet failed");
}
// TODO: clear software watchpoints if we implement them
}
else
{
error.SetErrorString("Watchpoint argument was NULL.");
}
if (error.Success())
error.SetErrorToGenericError();
return error;
}
void
ProcessGDBRemote::Clear()
{
m_flags = 0;
m_thread_list.Clear();
}
Error
ProcessGDBRemote::DoSignal (int signo)
{
Error error;
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::DoSignal (signal = %d)", signo);
if (!m_gdb_comm.SendAsyncSignal (signo))
error.SetErrorStringWithFormat("failed to send signal %i", signo);
return error;
}
Error
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
ProcessGDBRemote::StartDebugserverProcess (const char *debugserver_url) // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
{
Error error;
if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
{
// If we locate debugserver, keep that located version around
static FileSpec g_debugserver_file_spec;
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
ProcessLaunchInfo launch_info;
char debugserver_path[PATH_MAX];
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
// Always check to see if we have an environment override for the path
// to the debugserver to use and use it if we do.
const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
if (env_debugserver_path)
debugserver_file_spec.SetFile (env_debugserver_path, false);
else
debugserver_file_spec = g_debugserver_file_spec;
bool debugserver_exists = debugserver_file_spec.Exists();
if (!debugserver_exists)
{
// The debugserver binary is in the LLDB.framework/Resources
// directory.
Added a new Host call to find LLDB related paths: static bool Host::GetLLDBPath (lldb::PathType path_type, FileSpec &file_spec); This will fill in "file_spec" with an appropriate path that is appropriate for the current Host OS. MacOSX will return paths within the LLDB.framework, and other unixes will return the paths they want. The current PathType enums are: typedef enum PathType { ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) ePathTypeHeaderDir, // Find LLDB header file directory ePathTypePythonDir // Find Python modules (PYTHONPATH) directory } PathType; All places that were finding executables are and python paths are now updated to use this Host call. Added another new host call to launch the inferior in a terminal. This ability will be very host specific and doesn't need to be supported on all systems. MacOSX currently will create a new .command file and tell Terminal.app to open the .command file. It also uses the new "darwin-debug" app which is a small app that uses posix to exec (no fork) and stop at the entry point of the program. The GDB remote plug-in is almost able launch a process and attach to it, it currently will spawn the process, but it won't attach to it just yet. This will let LLDB not have to share the terminal with another process and a new terminal window will pop up when you launch. This won't get hooked up until we work out all of the kinks. The new Host function is: static lldb::pid_t Host::LaunchInNewTerminal ( const char **argv, // argv[0] is executable const char **envp, const ArchSpec *arch_spec, bool stop_at_entry, bool disable_aslr); Cleaned up FileSpec::GetPath to not use strncpy() as it was always zero filling the entire path buffer. Fixed an issue with the dynamic checker function where I missed a '$' prefix that should have been added. llvm-svn: 116690
2010-10-17 22:03:32 +00:00
if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
{
Added a new Host call to find LLDB related paths: static bool Host::GetLLDBPath (lldb::PathType path_type, FileSpec &file_spec); This will fill in "file_spec" with an appropriate path that is appropriate for the current Host OS. MacOSX will return paths within the LLDB.framework, and other unixes will return the paths they want. The current PathType enums are: typedef enum PathType { ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) ePathTypeHeaderDir, // Find LLDB header file directory ePathTypePythonDir // Find Python modules (PYTHONPATH) directory } PathType; All places that were finding executables are and python paths are now updated to use this Host call. Added another new host call to launch the inferior in a terminal. This ability will be very host specific and doesn't need to be supported on all systems. MacOSX currently will create a new .command file and tell Terminal.app to open the .command file. It also uses the new "darwin-debug" app which is a small app that uses posix to exec (no fork) and stop at the entry point of the program. The GDB remote plug-in is almost able launch a process and attach to it, it currently will spawn the process, but it won't attach to it just yet. This will let LLDB not have to share the terminal with another process and a new terminal window will pop up when you launch. This won't get hooked up until we work out all of the kinks. The new Host function is: static lldb::pid_t Host::LaunchInNewTerminal ( const char **argv, // argv[0] is executable const char **envp, const ArchSpec *arch_spec, bool stop_at_entry, bool disable_aslr); Cleaned up FileSpec::GetPath to not use strncpy() as it was always zero filling the entire path buffer. Fixed an issue with the dynamic checker function where I missed a '$' prefix that should have been added. llvm-svn: 116690
2010-10-17 22:03:32 +00:00
debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
debugserver_exists = debugserver_file_spec.Exists();
Added a new Host call to find LLDB related paths: static bool Host::GetLLDBPath (lldb::PathType path_type, FileSpec &file_spec); This will fill in "file_spec" with an appropriate path that is appropriate for the current Host OS. MacOSX will return paths within the LLDB.framework, and other unixes will return the paths they want. The current PathType enums are: typedef enum PathType { ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) ePathTypeHeaderDir, // Find LLDB header file directory ePathTypePythonDir // Find Python modules (PYTHONPATH) directory } PathType; All places that were finding executables are and python paths are now updated to use this Host call. Added another new host call to launch the inferior in a terminal. This ability will be very host specific and doesn't need to be supported on all systems. MacOSX currently will create a new .command file and tell Terminal.app to open the .command file. It also uses the new "darwin-debug" app which is a small app that uses posix to exec (no fork) and stop at the entry point of the program. The GDB remote plug-in is almost able launch a process and attach to it, it currently will spawn the process, but it won't attach to it just yet. This will let LLDB not have to share the terminal with another process and a new terminal window will pop up when you launch. This won't get hooked up until we work out all of the kinks. The new Host function is: static lldb::pid_t Host::LaunchInNewTerminal ( const char **argv, // argv[0] is executable const char **envp, const ArchSpec *arch_spec, bool stop_at_entry, bool disable_aslr); Cleaned up FileSpec::GetPath to not use strncpy() as it was always zero filling the entire path buffer. Fixed an issue with the dynamic checker function where I missed a '$' prefix that should have been added. llvm-svn: 116690
2010-10-17 22:03:32 +00:00
if (debugserver_exists)
{
g_debugserver_file_spec = debugserver_file_spec;
}
else
{
g_debugserver_file_spec.Clear();
debugserver_file_spec.Clear();
}
}
}
if (debugserver_exists)
{
debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
m_stdio_communication.Clear();
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
Args &debugserver_args = launch_info.GetArguments();
char arg_cstr[PATH_MAX];
// Start args with "debugserver /file/path -r --"
debugserver_args.AppendArgument(debugserver_path);
debugserver_args.AppendArgument(debugserver_url);
Added a new Host call to find LLDB related paths: static bool Host::GetLLDBPath (lldb::PathType path_type, FileSpec &file_spec); This will fill in "file_spec" with an appropriate path that is appropriate for the current Host OS. MacOSX will return paths within the LLDB.framework, and other unixes will return the paths they want. The current PathType enums are: typedef enum PathType { ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) ePathTypeHeaderDir, // Find LLDB header file directory ePathTypePythonDir // Find Python modules (PYTHONPATH) directory } PathType; All places that were finding executables are and python paths are now updated to use this Host call. Added another new host call to launch the inferior in a terminal. This ability will be very host specific and doesn't need to be supported on all systems. MacOSX currently will create a new .command file and tell Terminal.app to open the .command file. It also uses the new "darwin-debug" app which is a small app that uses posix to exec (no fork) and stop at the entry point of the program. The GDB remote plug-in is almost able launch a process and attach to it, it currently will spawn the process, but it won't attach to it just yet. This will let LLDB not have to share the terminal with another process and a new terminal window will pop up when you launch. This won't get hooked up until we work out all of the kinks. The new Host function is: static lldb::pid_t Host::LaunchInNewTerminal ( const char **argv, // argv[0] is executable const char **envp, const ArchSpec *arch_spec, bool stop_at_entry, bool disable_aslr); Cleaned up FileSpec::GetPath to not use strncpy() as it was always zero filling the entire path buffer. Fixed an issue with the dynamic checker function where I missed a '$' prefix that should have been added. llvm-svn: 116690
2010-10-17 22:03:32 +00:00
// use native registers, not the GDB registers
debugserver_args.AppendArgument("--native-regs");
// make debugserver run in its own session so signals generated by
// special terminal key sequences (^C) don't affect debugserver
debugserver_args.AppendArgument("--setsid");
const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
if (env_debugserver_log_file)
{
::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
debugserver_args.AppendArgument(arg_cstr);
}
const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
if (env_debugserver_log_flags)
{
::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
debugserver_args.AppendArgument(arg_cstr);
}
// debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
// debugserver_args.AppendArgument("--log-flags=0x802e0e");
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
// We currently send down all arguments, attach pids, or attach
// process names in dedicated GDB server packets, so we don't need
// to pass them as arguments. This is currently because of all the
// things we need to setup prior to launching: the environment,
// current working dir, file actions, etc.
#if 0
// Now append the program arguments
if (inferior_argv)
{
// Terminate the debugserver args so we can now append the inferior args
debugserver_args.AppendArgument("--");
for (int i = 0; inferior_argv[i] != NULL; ++i)
debugserver_args.AppendArgument (inferior_argv[i]);
}
else if (attach_pid != LLDB_INVALID_PROCESS_ID)
{
::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
debugserver_args.AppendArgument (arg_cstr);
}
else if (attach_name && attach_name[0])
{
if (wait_for_launch)
debugserver_args.AppendArgument ("--waitfor");
else
debugserver_args.AppendArgument ("--attach");
debugserver_args.AppendArgument (attach_name);
}
#endif
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
ProcessLaunchInfo::FileAction file_action;
// Close STDIN, STDOUT and STDERR. We might need to redirect them
// to "/dev/null" if we run into any problems.
file_action.Close (STDIN_FILENO);
launch_info.AppendFileAction (file_action);
file_action.Close (STDOUT_FILENO);
launch_info.AppendFileAction (file_action);
file_action.Close (STDERR_FILENO);
launch_info.AppendFileAction (file_action);
if (log)
{
StreamString strm;
debugserver_args.Dump (&strm);
log->Printf("%s arguments:\n%s", debugserver_args.GetArgumentAtIndex(0), strm.GetData());
}
launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false);
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
error = Host::LaunchProcess(launch_info);
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 05:54:46 +00:00
if (error.Success ())
m_debugserver_pid = launch_info.GetProcessID();
else
m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
if (error.Fail() || log)
error.PutToLog(log.get(), "Host::LaunchProcess (launch_info) => pid=%llu, path='%s'", m_debugserver_pid, debugserver_path);
}
else
{
error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME);
}
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
StartAsyncThread ();
}
return error;
}
bool
ProcessGDBRemote::MonitorDebugserverProcess
(
void *callback_baton,
lldb::pid_t debugserver_pid,
bool exited, // True if the process did exit
int signo, // Zero for no signal
int exit_status // Exit value of process if signal is zero
)
{
// The baton is a "ProcessGDBRemote *". Now this class might be gone
// and might not exist anymore, so we need to carefully try to get the
// target for this process first since we have a race condition when
// we are done running between getting the notice that the inferior
// process has died and the debugserver that was debugging this process.
// In our test suite, we are also continually running process after
// process, so we must be very careful to make sure:
// 1 - process object hasn't been deleted already
// 2 - that a new process object hasn't been recreated in its place
// "debugserver_pid" argument passed in is the process ID for
// debugserver that we are tracking...
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
ProcessGDBRemote *process = (ProcessGDBRemote *)callback_baton;
// Get a shared pointer to the target that has a matching process pointer.
// This target could be gone, or the target could already have a new process
// object inside of it
TargetSP target_sp (Debugger::FindTargetWithProcess(process));
if (log)
log->Printf ("ProcessGDBRemote::MonitorDebugserverProcess (baton=%p, pid=%llu, signo=%i (0x%x), exit_status=%i)", callback_baton, debugserver_pid, signo, signo, exit_status);
if (target_sp)
{
// We found a process in a target that matches, but another thread
// might be in the process of launching a new process that will
// soon replace it, so get a shared pointer to the process so we
// can keep it alive.
ProcessSP process_sp (target_sp->GetProcessSP());
// Now we have a shared pointer to the process that can't go away on us
// so we now make sure it was the same as the one passed in, and also make
// sure that our previous "process *" didn't get deleted and have a new
// "process *" created in its place with the same pointer. To verify this
// we make sure the process has our debugserver process ID. If we pass all
// of these tests, then we are sure that this process is the one we were
// looking for.
if (process_sp && process == process_sp.get() && process->m_debugserver_pid == debugserver_pid)
{
// Sleep for a half a second to make sure our inferior process has
// time to set its exit status before we set it incorrectly when
// both the debugserver and the inferior process shut down.
usleep (500000);
// If our process hasn't yet exited, debugserver might have died.
// If the process did exit, the we are reaping it.
const StateType state = process->GetState();
if (process->m_debugserver_pid != LLDB_INVALID_PROCESS_ID &&
state != eStateInvalid &&
state != eStateUnloaded &&
state != eStateExited &&
state != eStateDetached)
{
char error_str[1024];
if (signo)
{
const char *signal_cstr = process->GetUnixSignals().GetSignalAsCString (signo);
if (signal_cstr)
::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
else
::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %i", signo);
}
else
{
::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", exit_status);
}
process->SetExitStatus (-1, error_str);
}
// Debugserver has exited we need to let our ProcessGDBRemote
// know that it no longer has a debugserver instance
process->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
}
}
return true;
}
void
ProcessGDBRemote::KillDebugserverProcess ()
{
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
{
::kill (m_debugserver_pid, SIGINT);
m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
}
}
void
ProcessGDBRemote::Initialize()
{
static bool g_initialized = false;
if (g_initialized == false)
{
g_initialized = true;
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance);
Log::Callbacks log_callbacks = {
ProcessGDBRemoteLog::DisableLog,
ProcessGDBRemoteLog::EnableLog,
ProcessGDBRemoteLog::ListLogCategories
};
Log::RegisterLogChannel (ProcessGDBRemote::GetPluginNameStatic(), log_callbacks);
}
}
bool
ProcessGDBRemote::StartAsyncThread ()
{
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
// Create a thread that watches our internal state and controls which
// events make it to clients (into the DCProcess event queue).
m_async_thread = Host::ThreadCreate ("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
return IS_VALID_LLDB_HOST_THREAD(m_async_thread);
}
void
ProcessGDBRemote::StopAsyncThread ()
{
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
// This will shut down the async thread.
m_gdb_comm.Disconnect(); // Disconnect from the debug server.
// Stop the stdio thread
if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
{
Host::ThreadJoin (m_async_thread, NULL, NULL);
}
}
void *
ProcessGDBRemote::AsyncThread (void *arg)
{
ProcessGDBRemote *process = (ProcessGDBRemote*) arg;
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %llu) thread starting...", __FUNCTION__, arg, process->GetID());
Listener listener ("ProcessGDBRemote::AsyncThread");
EventSP event_sp;
const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
eBroadcastBitAsyncThreadShouldExit;
if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
{
listener.StartListeningForEvents (&process->m_gdb_comm, Communication::eBroadcastBitReadThreadDidExit);
bool done = false;
while (!done)
{
if (log)
log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %llu) listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
if (listener.WaitForEvent (NULL, event_sp))
{
const uint32_t event_type = event_sp->GetType();
if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
{
if (log)
log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %llu) Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
switch (event_type)
{
case eBroadcastBitAsyncContinue:
{
const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
if (continue_packet)
{
const char *continue_cstr = (const char *)continue_packet->GetBytes ();
const size_t continue_cstr_len = continue_packet->GetByteSize ();
if (log)
log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %llu) got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
if (::strstr (continue_cstr, "vAttach") == NULL)
process->SetPrivateState(eStateRunning);
StringExtractorGDBRemote response;
StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
switch (stop_state)
{
case eStateStopped:
case eStateCrashed:
case eStateSuspended:
process->SetLastStopPacket (response);
process->SetPrivateState (stop_state);
break;
case eStateExited:
process->SetLastStopPacket (response);
response.SetFilePos(1);
process->SetExitStatus(response.GetHexU8(), NULL);
done = true;
break;
case eStateInvalid:
process->SetExitStatus(-1, "lost connection");
break;
default:
process->SetPrivateState (stop_state);
break;
}
}
}
break;
case eBroadcastBitAsyncThreadShouldExit:
if (log)
log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %llu) got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
done = true;
break;
default:
if (log)
log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %llu) got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
done = true;
break;
}
}
else if (event_sp->BroadcasterIs (&process->m_gdb_comm))
{
if (event_type & Communication::eBroadcastBitReadThreadDidExit)
{
process->SetExitStatus (-1, "lost connection");
done = true;
}
}
}
else
{
if (log)
log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %llu) listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
done = true;
}
}
}
if (log)
log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %llu) thread exiting...", __FUNCTION__, arg, process->GetID());
process->m_async_thread = LLDB_INVALID_HOST_THREAD;
return NULL;
}
const char *
ProcessGDBRemote::GetDispatchQueueNameForThread
(
addr_t thread_dispatch_qaddr,
std::string &dispatch_queue_name
)
{
dispatch_queue_name.clear();
if (thread_dispatch_qaddr != 0 && thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
{
// Cache the dispatch_queue_offsets_addr value so we don't always have
// to look it up
if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
{
static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
const Symbol *dispatch_queue_offsets_symbol = NULL;
Many improvements to the Platform base class and subclasses. The base Platform class now implements the Host functionality for a lot of things that make sense by default so that subclasses can check: int PlatformSubclass::Foo () { if (IsHost()) return Platform::Foo (); // Let the platform base class do the host specific stuff // Platform subclass specific code... int result = ... return result; } Added new functions to the platform: virtual const char *Platform::GetUserName (uint32_t uid); virtual const char *Platform::GetGroupName (uint32_t gid); The user and group names are cached locally so that remote platforms can avoid sending packets multiple times to resolve this information. Added the parent process ID to the ProcessInfo class. Added a new ProcessInfoMatch class which helps us to match processes up and changed the Host layer over to using this new class. The new class allows us to search for processs: 1 - by name (equal to, starts with, ends with, contains, and regex) 2 - by pid 3 - And further check for parent pid == value, uid == value, gid == value, euid == value, egid == value, arch == value, parent == value. This is all hookup up to the "platform process list" command which required adding dumping routines to dump process information. If the Host class implements the process lookup routines, you can now lists processes on your local machine: machine1.foo.com % lldb (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari 94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode 92742 92710 username usergroup username usergroup i386-apple-darwin debugserver This of course also works remotely with the lldb-platform: machine1.foo.com % lldb-platform --listen 1234 machine2.foo.com % lldb (lldb) platform create remote-macosx Platform: remote-macosx Connected: no (lldb) platform connect connect://localhost:1444 Platform: remote-macosx Triple: x86_64-apple-darwin OS Version: 10.6.7 (10J869) Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 Hostname: machine1.foo.com Connected: yes (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation 99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari The lldb-platform implements everything with the Host:: layer, so this should "just work" for linux. I will probably be adding more stuff to the Host layer for launching processes and attaching to processes so that this support should eventually just work as well. Modified the target to be able to be created with an architecture that differs from the main executable. This is needed for iOS debugging since we can have an "armv6" binary which can run on an "armv7" machine, so we want to be able to do: % lldb (lldb) platform create remote-ios (lldb) file --arch armv7 a.out Where "a.out" is an armv6 executable. The platform then can correctly decide to open all "armv7" images for all dependent shared libraries. Modified the disassembly to show the current PC value. Example output: (lldb) disassemble --frame a.out`main: 0x1eb7: pushl %ebp 0x1eb8: movl %esp, %ebp 0x1eba: pushl %ebx 0x1ebb: subl $20, %esp 0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18 0x1ec3: popl %ebx -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf 0x1edb: leal 213(%ebx), %eax 0x1ee1: movl %eax, (%esp) 0x1ee4: calll 0x1f1e ; puts 0x1ee9: calll 0x1f0c ; getchar 0x1eee: movl $20, (%esp) 0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6 0x1efa: movl $12, %eax 0x1eff: addl $20, %esp 0x1f02: popl %ebx 0x1f03: leave 0x1f04: ret This can be handy when dealing with the new --line options that was recently added: (lldb) disassemble --line a.out`main + 13 at test.c:19 18 { -> 19 printf("Process: %i\n\n", getpid()); 20 puts("Press any key to continue..."); getchar(); -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf Modified the ModuleList to have a lookup based solely on a UUID. Since the UUID is typically the MD5 checksum of a binary image, there is no need to give the path and architecture when searching for a pre-existing image in an image list. Now that we support remote debugging a bit better, our lldb_private::Module needs to be able to track what the original path for file was as the platform knows it, as well as where the file is locally. The module has the two following functions to retrieve both paths: const FileSpec &Module::GetFileSpec () const; const FileSpec &Module::GetPlatformFileSpec () const; llvm-svn: 128563
2011-03-30 18:16:51 +00:00
ModuleSP module_sp(GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib", false), NULL, NULL));
if (module_sp)
dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
if (dispatch_queue_offsets_symbol == NULL)
{
Many improvements to the Platform base class and subclasses. The base Platform class now implements the Host functionality for a lot of things that make sense by default so that subclasses can check: int PlatformSubclass::Foo () { if (IsHost()) return Platform::Foo (); // Let the platform base class do the host specific stuff // Platform subclass specific code... int result = ... return result; } Added new functions to the platform: virtual const char *Platform::GetUserName (uint32_t uid); virtual const char *Platform::GetGroupName (uint32_t gid); The user and group names are cached locally so that remote platforms can avoid sending packets multiple times to resolve this information. Added the parent process ID to the ProcessInfo class. Added a new ProcessInfoMatch class which helps us to match processes up and changed the Host layer over to using this new class. The new class allows us to search for processs: 1 - by name (equal to, starts with, ends with, contains, and regex) 2 - by pid 3 - And further check for parent pid == value, uid == value, gid == value, euid == value, egid == value, arch == value, parent == value. This is all hookup up to the "platform process list" command which required adding dumping routines to dump process information. If the Host class implements the process lookup routines, you can now lists processes on your local machine: machine1.foo.com % lldb (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari 94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode 92742 92710 username usergroup username usergroup i386-apple-darwin debugserver This of course also works remotely with the lldb-platform: machine1.foo.com % lldb-platform --listen 1234 machine2.foo.com % lldb (lldb) platform create remote-macosx Platform: remote-macosx Connected: no (lldb) platform connect connect://localhost:1444 Platform: remote-macosx Triple: x86_64-apple-darwin OS Version: 10.6.7 (10J869) Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 Hostname: machine1.foo.com Connected: yes (lldb) platform process list PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME ====== ====== ========== ========== ========== ========== ======================== ============================ 99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation 99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb 99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge 94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker 94852 244 username usergroup username usergroup x86_64-apple-darwin Safari The lldb-platform implements everything with the Host:: layer, so this should "just work" for linux. I will probably be adding more stuff to the Host layer for launching processes and attaching to processes so that this support should eventually just work as well. Modified the target to be able to be created with an architecture that differs from the main executable. This is needed for iOS debugging since we can have an "armv6" binary which can run on an "armv7" machine, so we want to be able to do: % lldb (lldb) platform create remote-ios (lldb) file --arch armv7 a.out Where "a.out" is an armv6 executable. The platform then can correctly decide to open all "armv7" images for all dependent shared libraries. Modified the disassembly to show the current PC value. Example output: (lldb) disassemble --frame a.out`main: 0x1eb7: pushl %ebp 0x1eb8: movl %esp, %ebp 0x1eba: pushl %ebx 0x1ebb: subl $20, %esp 0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18 0x1ec3: popl %ebx -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf 0x1edb: leal 213(%ebx), %eax 0x1ee1: movl %eax, (%esp) 0x1ee4: calll 0x1f1e ; puts 0x1ee9: calll 0x1f0c ; getchar 0x1eee: movl $20, (%esp) 0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6 0x1efa: movl $12, %eax 0x1eff: addl $20, %esp 0x1f02: popl %ebx 0x1f03: leave 0x1f04: ret This can be handy when dealing with the new --line options that was recently added: (lldb) disassemble --line a.out`main + 13 at test.c:19 18 { -> 19 printf("Process: %i\n\n", getpid()); 20 puts("Press any key to continue..."); getchar(); -> 0x1ec4: calll 0x1f12 ; getpid 0x1ec9: movl %eax, 4(%esp) 0x1ecd: leal 199(%ebx), %eax 0x1ed3: movl %eax, (%esp) 0x1ed6: calll 0x1f18 ; printf Modified the ModuleList to have a lookup based solely on a UUID. Since the UUID is typically the MD5 checksum of a binary image, there is no need to give the path and architecture when searching for a pre-existing image in an image list. Now that we support remote debugging a bit better, our lldb_private::Module needs to be able to track what the original path for file was as the platform knows it, as well as where the file is locally. The module has the two following functions to retrieve both paths: const FileSpec &Module::GetFileSpec () const; const FileSpec &Module::GetPlatformFileSpec () const; llvm-svn: 128563
2011-03-30 18:16:51 +00:00
module_sp = GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libdispatch.dylib", false), NULL, NULL);
if (module_sp)
dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
}
if (dispatch_queue_offsets_symbol)
m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetValue().GetLoadAddress(&m_target);
if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
return NULL;
}
uint8_t memory_buffer[8];
DataExtractor data (memory_buffer,
sizeof(memory_buffer),
m_target.GetArchitecture().GetByteOrder(),
m_target.GetArchitecture().GetAddressByteSize());
// Excerpt from src/queue_private.h
struct dispatch_queue_offsets_s
{
uint16_t dqo_version;
uint16_t dqo_label;
uint16_t dqo_label_size;
} dispatch_queue_offsets;
Error error;
if (ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets), error) == sizeof(dispatch_queue_offsets))
{
uint32_t data_offset = 0;
if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t)))
{
if (ReadMemory (thread_dispatch_qaddr, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
{
data_offset = 0;
lldb::addr_t queue_addr = data.GetAddress(&data_offset);
lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label;
dispatch_queue_name.resize(dispatch_queue_offsets.dqo_label_size, '\0');
size_t bytes_read = ReadMemory (label_addr, &dispatch_queue_name[0], dispatch_queue_offsets.dqo_label_size, error);
if (bytes_read < dispatch_queue_offsets.dqo_label_size)
dispatch_queue_name.erase (bytes_read);
}
}
}
}
if (dispatch_queue_name.empty())
return NULL;
return dispatch_queue_name.c_str();
}
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-08 22:40:15 +00:00
//uint32_t
//ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
//{
// // If we are planning to launch the debugserver remotely, then we need to fire up a debugserver
// // process and ask it for the list of processes. But if we are local, we can let the Host do it.
// if (m_local_debugserver)
// {
// return Host::ListProcessesMatchingName (name, matches, pids);
// }
// else
// {
// // FIXME: Implement talking to the remote debugserver.
// return 0;
// }
//
//}
//
bool
ProcessGDBRemote::NewThreadNotifyBreakpointHit (void *baton,
lldb_private::StoppointCallbackContext *context,
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id)
{
// I don't think I have to do anything here, just make sure I notice the new thread when it starts to
// run so I can stop it if that's what I want to do.
LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
log->Printf("Hit New Thread Notification breakpoint.");
return false;
}
bool
ProcessGDBRemote::StartNoticingNewThreads()
{
static const char *bp_names[] =
{
"start_wqthread",
"_pthread_wqthread",
"_pthread_start",
NULL
};
LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
size_t num_bps = m_thread_observation_bps.size();
if (num_bps != 0)
{
for (int i = 0; i < num_bps; i++)
{
lldb::BreakpointSP break_sp = m_target.GetBreakpointByID(m_thread_observation_bps[i]);
if (break_sp)
{
if (log && log->GetVerbose())
log->Printf("Enabled noticing new thread breakpoint.");
break_sp->SetEnabled(true);
}
}
}
else
{
for (int i = 0; bp_names[i] != NULL; i++)
{
Breakpoint *breakpoint = m_target.CreateBreakpoint (NULL, NULL, bp_names[i], eFunctionNameTypeFull, true).get();
if (breakpoint)
{
if (log && log->GetVerbose())
log->Printf("Successfully created new thread notification breakpoint at \"%s\".", bp_names[i]);
m_thread_observation_bps.push_back(breakpoint->GetID());
breakpoint->SetCallback (ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true);
}
else
{
if (log)
log->Printf("Failed to create new thread notification breakpoint.");
return false;
}
}
}
return true;
}
bool
ProcessGDBRemote::StopNoticingNewThreads()
{
LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log && log->GetVerbose())
log->Printf ("Disabling new thread notification breakpoint.");
size_t num_bps = m_thread_observation_bps.size();
if (num_bps != 0)
{
for (int i = 0; i < num_bps; i++)
{
lldb::BreakpointSP break_sp = m_target.GetBreakpointByID(m_thread_observation_bps[i]);
if (break_sp)
{
break_sp->SetEnabled(false);
}
}
}
return true;
}