[Lldb-commits] [lldb] r280751 - *** This commit represents a complete reformatting of the LLDB source code
Kate Stone via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 6 13:58:36 PDT 2016
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Tue Sep 6 15:57:50 2016
@@ -14,7 +14,7 @@
#include <stdlib.h>
#ifndef LLDB_DISABLE_POSIX
#include <netinet/in.h>
-#include <sys/mman.h> // for mmap
+#include <sys/mman.h> // for mmap
#include <sys/socket.h>
#endif
#include <sys/stat.h>
@@ -28,11 +28,8 @@
#include <sstream>
#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Host/ConnectionFileDescriptor.h"
-#include "lldb/Host/FileSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
@@ -42,6 +39,8 @@
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
+#include "lldb/Host/FileSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/StringConvert.h"
@@ -49,133 +48,111 @@
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Host/XML.h"
+#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/OptionValueProperties.h"
-#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
-#include "lldb/Target/SystemRuntime.h"
#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/PseudoTerminal.h"
// Project includes
-#include "lldb/Host/Host.h"
+#include "GDBRemoteRegisterContext.h"
+#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "Plugins/Process/Utility/StopInfoMachException.h"
-#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
-#include "Utility/StringExtractorGDBRemote.h"
-#include "GDBRemoteRegisterContext.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"
+#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Host/Host.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/raw_ostream.h"
-#define DEBUGSERVER_BASENAME "debugserver"
+#define DEBUGSERVER_BASENAME "debugserver"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
-namespace lldb
-{
- // Provide a function that can easily dump the packet history if we know a
- // ProcessGDBRemote * value (which we can get from logs or from debugging).
- // We need the function in the lldb namespace so it makes it into the final
- // executable since the LLDB shared library only exports stuff in the lldb
- // namespace. This allows you to attach with a debugger and call this
- // function and get the packet history dumped to a file.
- void
- DumpProcessGDBRemotePacketHistory (void *p, const char *path)
- {
- StreamFile strm;
- Error error (strm.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate));
- if (error.Success())
- ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory (strm);
- }
+namespace lldb {
+// Provide a function that can easily dump the packet history if we know a
+// ProcessGDBRemote * value (which we can get from logs or from debugging).
+// We need the function in the lldb namespace so it makes it into the final
+// executable since the LLDB shared library only exports stuff in the lldb
+// namespace. This allows you to attach with a debugger and call this
+// function and get the packet history dumped to a file.
+void DumpProcessGDBRemotePacketHistory(void *p, const char *path) {
+ StreamFile strm;
+ Error error(strm.GetFile().Open(path, File::eOpenOptionWrite |
+ File::eOpenOptionCanCreate));
+ if (error.Success())
+ ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm);
+}
}
namespace {
- static PropertyDefinition
- g_properties[] =
- {
- { "packet-timeout" , OptionValue::eTypeUInt64 , true , 1, NULL, NULL, "Specify the default packet timeout in seconds." },
- { "target-definition-file" , OptionValue::eTypeFileSpec , true, 0 , NULL, NULL, "The file that provides the description for remote target registers." },
- { NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL }
- };
-
- enum
- {
- ePropertyPacketTimeout,
- ePropertyTargetDefinitionFile
- };
-
- class PluginProperties : public Properties
- {
- public:
-
- static ConstString
- GetSettingName ()
- {
- return ProcessGDBRemote::GetPluginNameStatic();
- }
-
- PluginProperties() :
- Properties ()
- {
- m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
- m_collection_sp->Initialize(g_properties);
- }
-
- virtual
- ~PluginProperties()
- {
- }
-
- uint64_t
- GetPacketTimeout()
- {
- const uint32_t idx = ePropertyPacketTimeout;
- return m_collection_sp->GetPropertyAtIndexAsUInt64(NULL, idx, g_properties[idx].default_uint_value);
- }
+static PropertyDefinition g_properties[] = {
+ {"packet-timeout", OptionValue::eTypeUInt64, true, 1, NULL, NULL,
+ "Specify the default packet timeout in seconds."},
+ {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, NULL,
+ "The file that provides the description for remote target registers."},
+ {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};
- bool
- SetPacketTimeout(uint64_t timeout)
- {
- const uint32_t idx = ePropertyPacketTimeout;
- return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout);
- }
+enum { ePropertyPacketTimeout, ePropertyTargetDefinitionFile };
- FileSpec
- GetTargetDefinitionFile () const
- {
- const uint32_t idx = ePropertyTargetDefinitionFile;
- return m_collection_sp->GetPropertyAtIndexAsFileSpec (NULL, idx);
- }
- };
+class PluginProperties : public Properties {
+public:
+ static ConstString GetSettingName() {
+ return ProcessGDBRemote::GetPluginNameStatic();
+ }
+
+ PluginProperties() : Properties() {
+ m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
+ m_collection_sp->Initialize(g_properties);
+ }
+
+ virtual ~PluginProperties() {}
+
+ uint64_t GetPacketTimeout() {
+ const uint32_t idx = ePropertyPacketTimeout;
+ return m_collection_sp->GetPropertyAtIndexAsUInt64(
+ NULL, idx, g_properties[idx].default_uint_value);
+ }
+
+ bool SetPacketTimeout(uint64_t timeout) {
+ const uint32_t idx = ePropertyPacketTimeout;
+ return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout);
+ }
+
+ FileSpec GetTargetDefinitionFile() const {
+ const uint32_t idx = ePropertyTargetDefinitionFile;
+ return m_collection_sp->GetPropertyAtIndexAsFileSpec(NULL, idx);
+ }
+};
- typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
+typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
- static const ProcessKDPPropertiesSP &
- GetGlobalPluginProperties()
- {
- static ProcessKDPPropertiesSP g_settings_sp;
- if (!g_settings_sp)
- g_settings_sp.reset (new PluginProperties ());
- return g_settings_sp;
- }
+static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() {
+ static ProcessKDPPropertiesSP g_settings_sp;
+ if (!g_settings_sp)
+ g_settings_sp.reset(new PluginProperties());
+ return g_settings_sp;
+}
} // anonymous namespace end
@@ -183,3870 +160,3561 @@ namespace {
// ephemeral port from the kernel and make sure we reserve it before passing
// it to debugserver.
-#if defined (__APPLE__)
-#define LOW_PORT (IPPORT_RESERVED)
-#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
+#if defined(__APPLE__)
+#define LOW_PORT (IPPORT_RESERVED)
+#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
#else
-#define LOW_PORT (1024u)
-#define HIGH_PORT (49151u)
+#define LOW_PORT (1024u)
+#define HIGH_PORT (49151u)
#endif
-#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
+#if defined(__APPLE__) && \
+ (defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
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() % (HIGH_PORT - LOW_PORT)) + LOW_PORT;
+static inline uint16_t get_random_port() {
+ if (!rand_initialized) {
+ time_t seed = time(NULL);
+
+ rand_initialized = true;
+ srand(seed);
+ }
+ return (rand() % (HIGH_PORT - LOW_PORT)) + LOW_PORT;
}
#endif
-ConstString
-ProcessGDBRemote::GetPluginNameStatic()
-{
- static ConstString g_name("gdb-remote");
- return g_name;
-}
-
-const char *
-ProcessGDBRemote::GetPluginDescriptionStatic()
-{
- return "GDB Remote protocol based debugging plug-in.";
-}
-
-void
-ProcessGDBRemote::Terminate()
-{
- PluginManager::UnregisterPlugin (ProcessGDBRemote::CreateInstance);
+ConstString ProcessGDBRemote::GetPluginNameStatic() {
+ static ConstString g_name("gdb-remote");
+ return g_name;
}
+const char *ProcessGDBRemote::GetPluginDescriptionStatic() {
+ return "GDB Remote protocol based debugging plug-in.";
+}
-lldb::ProcessSP
-ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file_path)
-{
- lldb::ProcessSP process_sp;
- if (crash_file_path == NULL)
- process_sp.reset (new ProcessGDBRemote (target_sp, listener_sp));
- return process_sp;
+void ProcessGDBRemote::Terminate() {
+ PluginManager::UnregisterPlugin(ProcessGDBRemote::CreateInstance);
}
-bool
-ProcessGDBRemote::CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name)
-{
- if (plugin_specified_by_name)
- return true;
+lldb::ProcessSP
+ProcessGDBRemote::CreateInstance(lldb::TargetSP target_sp,
+ ListenerSP listener_sp,
+ const FileSpec *crash_file_path) {
+ lldb::ProcessSP process_sp;
+ if (crash_file_path == NULL)
+ process_sp.reset(new ProcessGDBRemote(target_sp, listener_sp));
+ return process_sp;
+}
- // For now we are just making sure the file exists for a given module
- Module *exe_module = target_sp->GetExecutableModulePointer();
- if (exe_module)
- {
- 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:
- case ObjectFile::eTypeJIT:
- return false;
- case ObjectFile::eTypeExecutable:
- case ObjectFile::eTypeDynamicLinker:
- case ObjectFile::eTypeUnknown:
- break;
- }
- return exe_module->GetFileSpec().Exists();
- }
- // However, if there is no executable module, we return true since we might be preparing to attach.
+bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp,
+ 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_sp->GetExecutableModulePointer();
+ if (exe_module) {
+ 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:
+ case ObjectFile::eTypeJIT:
+ return false;
+ case ObjectFile::eTypeExecutable:
+ case ObjectFile::eTypeDynamicLinker:
+ case ObjectFile::eTypeUnknown:
+ break;
+ }
+ return exe_module->GetFileSpec().Exists();
+ }
+ // However, if there is no executable module, we return true since we might be
+ // preparing to attach.
+ return true;
}
//----------------------------------------------------------------------
// ProcessGDBRemote constructor
//----------------------------------------------------------------------
-ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, ListenerSP listener_sp)
- : Process(target_sp, listener_sp),
- m_flags(0),
- m_gdb_comm(),
- m_debugserver_pid(LLDB_INVALID_PROCESS_ID),
- m_last_stop_packet_mutex(),
+ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
+ ListenerSP listener_sp)
+ : Process(target_sp, listener_sp), m_flags(0), m_gdb_comm(),
+ m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_last_stop_packet_mutex(),
m_register_info(),
m_async_broadcaster(NULL, "lldb.process.gdb-remote.async-broadcaster"),
- m_async_listener_sp(Listener::MakeListener("lldb.process.gdb-remote.async-listener")),
- m_async_thread_state_mutex(),
- m_thread_ids(),
- m_thread_pcs(),
- m_jstopinfo_sp(),
- m_jthreadsinfo_sp(),
- m_continue_c_tids(),
- m_continue_C_tids(),
- m_continue_s_tids(),
- m_continue_S_tids(),
- m_max_memory_size(0),
- m_remote_stub_max_memory_size(0),
- m_addr_to_mmap_size(),
- m_thread_create_bp_sp(),
- m_waiting_for_attach(false),
- m_destroy_tried_resuming(false),
- m_command_sp(),
- m_breakpoint_pc_offset(0),
- m_initial_tid(LLDB_INVALID_THREAD_ID)
-{
- m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
- m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, "async thread continue");
- m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit, "async thread did exit");
+ m_async_listener_sp(
+ Listener::MakeListener("lldb.process.gdb-remote.async-listener")),
+ m_async_thread_state_mutex(), m_thread_ids(), m_thread_pcs(),
+ m_jstopinfo_sp(), m_jthreadsinfo_sp(), m_continue_c_tids(),
+ m_continue_C_tids(), m_continue_s_tids(), m_continue_S_tids(),
+ m_max_memory_size(0), m_remote_stub_max_memory_size(0),
+ m_addr_to_mmap_size(), m_thread_create_bp_sp(),
+ m_waiting_for_attach(false), m_destroy_tried_resuming(false),
+ m_command_sp(), m_breakpoint_pc_offset(0),
+ m_initial_tid(LLDB_INVALID_THREAD_ID) {
+ m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
+ "async thread should exit");
+ m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
+ "async thread continue");
+ m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit,
+ "async thread did exit");
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));
- const uint32_t async_event_mask = eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;
+ const uint32_t async_event_mask =
+ eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;
- if (m_async_listener_sp->StartListeningForEvents(&m_async_broadcaster, async_event_mask) != async_event_mask)
- {
- if (log)
- log->Printf("ProcessGDBRemote::%s failed to listen for m_async_broadcaster events", __FUNCTION__);
- }
-
- const uint32_t gdb_event_mask =
- Communication::eBroadcastBitReadThreadDidExit | GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify;
- if (m_async_listener_sp->StartListeningForEvents(&m_gdb_comm, gdb_event_mask) != gdb_event_mask)
- {
- if (log)
- log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", __FUNCTION__);
- }
-
- const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout();
- if (timeout_seconds > 0)
- m_gdb_comm.SetPacketTimeout(timeout_seconds);
+ if (m_async_listener_sp->StartListeningForEvents(
+ &m_async_broadcaster, async_event_mask) != async_event_mask) {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s failed to listen for "
+ "m_async_broadcaster events",
+ __FUNCTION__);
+ }
+
+ const uint32_t gdb_event_mask =
+ Communication::eBroadcastBitReadThreadDidExit |
+ GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify;
+ if (m_async_listener_sp->StartListeningForEvents(
+ &m_gdb_comm, gdb_event_mask) != gdb_event_mask) {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events",
+ __FUNCTION__);
+ }
+
+ const uint64_t timeout_seconds =
+ GetGlobalPluginProperties()->GetPacketTimeout();
+ if (timeout_seconds > 0)
+ m_gdb_comm.SetPacketTimeout(timeout_seconds);
}
//----------------------------------------------------------------------
// 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();
-
- // The general Finalize is going to try to destroy the process and that SHOULD
- // shut down the async thread. However, if we don't kill it it will get stranded and
- // its connection will go away so when it wakes up it will crash. So kill it for sure here.
- StopAsyncThread();
- KillDebugserverProcess();
+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();
+
+ // The general Finalize is going to try to destroy the process and that SHOULD
+ // shut down the async thread. However, if we don't kill it it will get
+ // stranded and
+ // its connection will go away so when it wakes up it will crash. So kill it
+ // for sure here.
+ StopAsyncThread();
+ KillDebugserverProcess();
}
//----------------------------------------------------------------------
// PluginInterface
//----------------------------------------------------------------------
-ConstString
-ProcessGDBRemote::GetPluginName()
-{
- return GetPluginNameStatic();
-}
-
-uint32_t
-ProcessGDBRemote::GetPluginVersion()
-{
- return 1;
-}
-
-bool
-ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_fspec)
-{
- ScriptInterpreter *interpreter = GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
- Error error;
- StructuredData::ObjectSP module_object_sp(interpreter->LoadPluginModule(target_definition_fspec, error));
- if (module_object_sp)
- {
- StructuredData::DictionarySP target_definition_sp(
- interpreter->GetDynamicSettings(module_object_sp, &GetTarget(), "gdb-server-target-definition", error));
+ConstString ProcessGDBRemote::GetPluginName() { return GetPluginNameStatic(); }
- if (target_definition_sp)
- {
- StructuredData::ObjectSP target_object(target_definition_sp->GetValueForKey("host-info"));
- if (target_object)
- {
- if (auto host_info_dict = target_object->GetAsDictionary())
- {
- StructuredData::ObjectSP triple_value = host_info_dict->GetValueForKey("triple");
- if (auto triple_string_value = triple_value->GetAsString())
- {
- std::string triple_string = triple_string_value->GetValue();
- ArchSpec host_arch(triple_string.c_str());
- if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture()))
- {
- GetTarget().SetArchitecture(host_arch);
- }
- }
- }
- }
- m_breakpoint_pc_offset = 0;
- StructuredData::ObjectSP breakpoint_pc_offset_value = target_definition_sp->GetValueForKey("breakpoint-pc-offset");
- if (breakpoint_pc_offset_value)
- {
- if (auto breakpoint_pc_int_value = breakpoint_pc_offset_value->GetAsInteger())
- m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue();
- }
+uint32_t ProcessGDBRemote::GetPluginVersion() { return 1; }
- if (m_register_info.SetRegisterInfo(*target_definition_sp, GetTarget().GetArchitecture()) > 0)
- {
- return true;
- }
- }
+bool ProcessGDBRemote::ParsePythonTargetDefinition(
+ const FileSpec &target_definition_fspec) {
+ ScriptInterpreter *interpreter =
+ GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ Error error;
+ StructuredData::ObjectSP module_object_sp(
+ interpreter->LoadPluginModule(target_definition_fspec, error));
+ if (module_object_sp) {
+ StructuredData::DictionarySP target_definition_sp(
+ interpreter->GetDynamicSettings(module_object_sp, &GetTarget(),
+ "gdb-server-target-definition", error));
+
+ if (target_definition_sp) {
+ StructuredData::ObjectSP target_object(
+ target_definition_sp->GetValueForKey("host-info"));
+ if (target_object) {
+ if (auto host_info_dict = target_object->GetAsDictionary()) {
+ StructuredData::ObjectSP triple_value =
+ host_info_dict->GetValueForKey("triple");
+ if (auto triple_string_value = triple_value->GetAsString()) {
+ std::string triple_string = triple_string_value->GetValue();
+ ArchSpec host_arch(triple_string.c_str());
+ if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture())) {
+ GetTarget().SetArchitecture(host_arch);
+ }
+ }
+ }
+ }
+ m_breakpoint_pc_offset = 0;
+ StructuredData::ObjectSP breakpoint_pc_offset_value =
+ target_definition_sp->GetValueForKey("breakpoint-pc-offset");
+ if (breakpoint_pc_offset_value) {
+ if (auto breakpoint_pc_int_value =
+ breakpoint_pc_offset_value->GetAsInteger())
+ m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue();
+ }
+
+ if (m_register_info.SetRegisterInfo(*target_definition_sp,
+ GetTarget().GetArchitecture()) > 0) {
+ return true;
+ }
}
- return false;
+ }
+ return false;
}
-// If the remote stub didn't give us eh_frame or DWARF register numbers for a register,
+// If the remote stub didn't give us eh_frame or DWARF register numbers for a
+// register,
// see if the ABI can provide them.
// DWARF and eh_frame register numbers are defined as a part of the ABI.
-static void
-AugmentRegisterInfoViaABI (RegisterInfo ®_info, ConstString reg_name, ABISP abi_sp)
-{
- if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM
- || reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM)
- {
- if (abi_sp)
- {
- RegisterInfo abi_reg_info;
- if (abi_sp->GetRegisterInfoByName (reg_name, abi_reg_info))
+static void AugmentRegisterInfoViaABI(RegisterInfo ®_info,
+ ConstString reg_name, ABISP abi_sp) {
+ if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM ||
+ reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) {
+ if (abi_sp) {
+ RegisterInfo abi_reg_info;
+ if (abi_sp->GetRegisterInfoByName(reg_name, abi_reg_info)) {
+ if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM &&
+ abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) {
+ reg_info.kinds[eRegisterKindEHFrame] =
+ abi_reg_info.kinds[eRegisterKindEHFrame];
+ }
+ if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM &&
+ abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) {
+ reg_info.kinds[eRegisterKindDWARF] =
+ abi_reg_info.kinds[eRegisterKindDWARF];
+ }
+ if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM &&
+ abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) {
+ reg_info.kinds[eRegisterKindGeneric] =
+ abi_reg_info.kinds[eRegisterKindGeneric];
+ }
+ }
+ }
+ }
+}
+
+static size_t SplitCommaSeparatedRegisterNumberString(
+ const llvm::StringRef &comma_separated_regiter_numbers,
+ std::vector<uint32_t> ®nums, int base) {
+ regnums.clear();
+ std::pair<llvm::StringRef, llvm::StringRef> value_pair;
+ value_pair.second = comma_separated_regiter_numbers;
+ do {
+ value_pair = value_pair.second.split(',');
+ if (!value_pair.first.empty()) {
+ uint32_t reg = StringConvert::ToUInt32(value_pair.first.str().c_str(),
+ LLDB_INVALID_REGNUM, base);
+ if (reg != LLDB_INVALID_REGNUM)
+ regnums.push_back(reg);
+ }
+ } while (!value_pair.second.empty());
+ return regnums.size();
+}
+
+void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
+ if (!force && m_register_info.GetNumRegisters() > 0)
+ return;
+
+ m_register_info.Clear();
+
+ // Check if qHostInfo specified a specific packet timeout for this connection.
+ // If so then lets update our setting so the user knows what the timeout is
+ // and can see it.
+ const uint32_t host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
+ if (host_packet_timeout) {
+ GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout);
+ }
+
+ // Register info search order:
+ // 1 - Use the target definition python file if one is specified.
+ // 2 - If the target definition doesn't have any of the info from the
+ // target.xml (registers) then proceed to read the target.xml.
+ // 3 - Fall back on the qRegisterInfo packets.
+
+ FileSpec target_definition_fspec =
+ GetGlobalPluginProperties()->GetTargetDefinitionFile();
+ if (!target_definition_fspec.Exists()) {
+ // If the filename doesn't exist, it may be a ~ not having been expanded -
+ // try to resolve it.
+ target_definition_fspec.ResolvePath();
+ }
+ if (target_definition_fspec) {
+ // See if we can get register definitions from a python file
+ if (ParsePythonTargetDefinition(target_definition_fspec)) {
+ return;
+ } else {
+ StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream();
+ stream_sp->Printf("ERROR: target description file %s failed to parse.\n",
+ target_definition_fspec.GetPath().c_str());
+ }
+ }
+
+ const ArchSpec &target_arch = GetTarget().GetArchitecture();
+ const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture();
+ const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
+
+ // Use the process' architecture instead of the host arch, if available
+ ArchSpec arch_to_use;
+ if (remote_process_arch.IsValid())
+ arch_to_use = remote_process_arch;
+ else
+ arch_to_use = remote_host_arch;
+
+ if (!arch_to_use.IsValid())
+ arch_to_use = target_arch;
+
+ if (GetGDBServerRegisterInfo(arch_to_use))
+ return;
+
+ char packet[128];
+ uint32_t reg_offset = 0;
+ uint32_t reg_num = 0;
+ for (StringExtractorGDBRemote::ResponseType 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 < (int)sizeof(packet));
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response,
+ false) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ response_type = response.GetResponseType();
+ if (response_type == StringExtractorGDBRemote::eResponse) {
+ llvm::StringRef name;
+ llvm::StringRef value;
+ ConstString reg_name;
+ ConstString alt_name;
+ ConstString set_name;
+ std::vector<uint32_t> value_regs;
+ std::vector<uint32_t> invalidate_regs;
+ std::vector<uint8_t> dwarf_opcode_bytes;
+ RegisterInfo reg_info = {
+ NULL, // Name
+ NULL, // Alt name
+ 0, // byte size
+ reg_offset, // offset
+ eEncodingUint, // encoding
+ eFormatHex, // format
{
- if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
- {
- reg_info.kinds[eRegisterKindEHFrame] = abi_reg_info.kinds[eRegisterKindEHFrame];
- }
- if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
- {
- reg_info.kinds[eRegisterKindDWARF] = abi_reg_info.kinds[eRegisterKindDWARF];
- }
- if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
- {
- reg_info.kinds[eRegisterKindGeneric] = abi_reg_info.kinds[eRegisterKindGeneric];
- }
- }
- }
- }
-}
+ LLDB_INVALID_REGNUM, // eh_frame reg num
+ LLDB_INVALID_REGNUM, // DWARF reg num
+ LLDB_INVALID_REGNUM, // generic reg num
+ reg_num, // process plugin reg num
+ reg_num // native register number
+ },
+ NULL,
+ NULL,
+ NULL, // Dwarf expression opcode bytes pointer
+ 0 // Dwarf expression opcode bytes length
+ };
-static size_t
-SplitCommaSeparatedRegisterNumberString(const llvm::StringRef &comma_separated_regiter_numbers, std::vector<uint32_t> ®nums, int base)
-{
- regnums.clear();
- std::pair<llvm::StringRef, llvm::StringRef> value_pair;
- value_pair.second = comma_separated_regiter_numbers;
- do
- {
- value_pair = value_pair.second.split(',');
- if (!value_pair.first.empty())
- {
- uint32_t reg = StringConvert::ToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, base);
- if (reg != LLDB_INVALID_REGNUM)
- regnums.push_back (reg);
- }
- } while (!value_pair.second.empty());
- return regnums.size();
-}
+ while (response.GetNameColonValue(name, value)) {
+ if (name.equals("name")) {
+ reg_name.SetString(value);
+ } else if (name.equals("alt-name")) {
+ alt_name.SetString(value);
+ } else if (name.equals("bitsize")) {
+ value.getAsInteger(0, reg_info.byte_size);
+ reg_info.byte_size /= CHAR_BIT;
+ } else if (name.equals("offset")) {
+ if (value.getAsInteger(0, reg_offset))
+ reg_offset = UINT32_MAX;
+ } else if (name.equals("encoding")) {
+ const Encoding encoding = Args::StringToEncoding(value);
+ if (encoding != eEncodingInvalid)
+ reg_info.encoding = encoding;
+ } else if (name.equals("format")) {
+ Format format = eFormatInvalid;
+ if (Args::StringToFormat(value.str().c_str(), format, NULL)
+ .Success())
+ reg_info.format = format;
+ else {
+ reg_info.format =
+ llvm::StringSwitch<Format>(value)
+ .Case("binary", eFormatBinary)
+ .Case("decimal", eFormatDecimal)
+ .Case("hex", eFormatHex)
+ .Case("float", eFormatFloat)
+ .Case("vector-sint8", eFormatVectorOfSInt8)
+ .Case("vector-uint8", eFormatVectorOfUInt8)
+ .Case("vector-sint16", eFormatVectorOfSInt16)
+ .Case("vector-uint16", eFormatVectorOfUInt16)
+ .Case("vector-sint32", eFormatVectorOfSInt32)
+ .Case("vector-uint32", eFormatVectorOfUInt32)
+ .Case("vector-float32", eFormatVectorOfFloat32)
+ .Case("vector-uint128", eFormatVectorOfUInt128)
+ .Default(eFormatInvalid);
+ }
+ } else if (name.equals("set")) {
+ set_name.SetString(value);
+ } else if (name.equals("gcc") || name.equals("ehframe")) {
+ if (value.getAsInteger(0, reg_info.kinds[eRegisterKindEHFrame]))
+ reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM;
+ } else if (name.equals("dwarf")) {
+ if (value.getAsInteger(0, reg_info.kinds[eRegisterKindDWARF]))
+ reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;
+ } else if (name.equals("generic")) {
+ reg_info.kinds[eRegisterKindGeneric] =
+ Args::StringToGenericRegister(value);
+ } else if (name.equals("container-regs")) {
+ SplitCommaSeparatedRegisterNumberString(value, value_regs, 16);
+ } else if (name.equals("invalidate-regs")) {
+ SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16);
+ } else if (name.equals("dynamic_size_dwarf_expr_bytes")) {
+ size_t dwarf_opcode_len = value.size() / 2;
+ assert(dwarf_opcode_len > 0);
+
+ dwarf_opcode_bytes.resize(dwarf_opcode_len);
+ reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;
+
+ StringExtractor opcode_extractor(value);
+ uint32_t ret_val =
+ opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes);
+ assert(dwarf_opcode_len == ret_val);
+ reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data();
+ }
+ }
-void
-ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
-{
- if (!force && m_register_info.GetNumRegisters() > 0)
- return;
+ reg_info.byte_offset = reg_offset;
+ assert(reg_info.byte_size != 0);
+ reg_offset += reg_info.byte_size;
+ if (!value_regs.empty()) {
+ value_regs.push_back(LLDB_INVALID_REGNUM);
+ reg_info.value_regs = value_regs.data();
+ }
+ if (!invalidate_regs.empty()) {
+ invalidate_regs.push_back(LLDB_INVALID_REGNUM);
+ reg_info.invalidate_regs = invalidate_regs.data();
+ }
+
+ // We have to make a temporary ABI here, and not use the GetABI because
+ // this code
+ // gets called in DidAttach, when the target architecture (and
+ // consequently the ABI we'll get from
+ // the process) may be wrong.
+ ABISP abi_to_use = ABI::FindPlugin(arch_to_use);
+
+ AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use);
+
+ m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
+ } else {
+ break; // ensure exit before reg_num is incremented
+ }
+ } else {
+ break;
+ }
+ }
- m_register_info.Clear();
+ if (m_register_info.GetNumRegisters() > 0) {
+ m_register_info.Finalize(GetTarget().GetArchitecture());
+ return;
+ }
- // Check if qHostInfo specified a specific packet timeout for this connection.
- // If so then lets update our setting so the user knows what the timeout is
- // and can see it.
- const uint32_t host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
- if (host_packet_timeout)
- {
- GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout);
- }
+ // We didn't get anything if the accumulated reg_num is zero. 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.
+ // On the other hand, if the accumulated reg_num is positive, see if we can
+ // add composite registers to the existing primordial ones.
+ bool from_scratch = (m_register_info.GetNumRegisters() == 0);
- // Register info search order:
- // 1 - Use the target definition python file if one is specified.
- // 2 - If the target definition doesn't have any of the info from the target.xml (registers) then proceed to read the target.xml.
- // 3 - Fall back on the qRegisterInfo packets.
+ if (!target_arch.IsValid()) {
+ if (arch_to_use.IsValid() &&
+ (arch_to_use.GetMachine() == llvm::Triple::arm ||
+ arch_to_use.GetMachine() == llvm::Triple::thumb) &&
+ arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple)
+ m_register_info.HardcodeARMRegisters(from_scratch);
+ } else if (target_arch.GetMachine() == llvm::Triple::arm ||
+ target_arch.GetMachine() == llvm::Triple::thumb) {
+ m_register_info.HardcodeARMRegisters(from_scratch);
+ }
- FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();
- if (!target_definition_fspec.Exists())
- {
- // If the filename doesn't exist, it may be a ~ not having been expanded - try to resolve it.
- target_definition_fspec.ResolvePath();
- }
- if (target_definition_fspec)
- {
- // See if we can get register definitions from a python file
- if (ParsePythonTargetDefinition (target_definition_fspec))
- {
- return;
- }
- else
- {
- StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream();
- stream_sp->Printf ("ERROR: target description file %s failed to parse.\n", target_definition_fspec.GetPath().c_str());
- }
- }
+ // At this point, we can finalize our register info.
+ m_register_info.Finalize(GetTarget().GetArchitecture());
+}
- const ArchSpec &target_arch = GetTarget().GetArchitecture();
- const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture();
- const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
+Error ProcessGDBRemote::WillLaunch(Module *module) {
+ return WillLaunchOrAttach();
+}
- // Use the process' architecture instead of the host arch, if available
- ArchSpec arch_to_use;
- if (remote_process_arch.IsValid ())
- arch_to_use = remote_process_arch;
- else
- arch_to_use = remote_host_arch;
-
- if (!arch_to_use.IsValid())
- arch_to_use = target_arch;
-
- if (GetGDBServerRegisterInfo (arch_to_use))
- return;
-
- char packet[128];
- uint32_t reg_offset = 0;
- uint32_t reg_num = 0;
- for (StringExtractorGDBRemote::ResponseType 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 < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
- {
- response_type = response.GetResponseType();
- if (response_type == StringExtractorGDBRemote::eResponse)
- {
- llvm::StringRef name;
- llvm::StringRef value;
- ConstString reg_name;
- ConstString alt_name;
- ConstString set_name;
- std::vector<uint32_t> value_regs;
- std::vector<uint32_t> invalidate_regs;
- std::vector<uint8_t> dwarf_opcode_bytes;
- RegisterInfo reg_info = { NULL, // Name
- NULL, // Alt name
- 0, // byte size
- reg_offset, // offset
- eEncodingUint, // encoding
- eFormatHex, // format
- {
- LLDB_INVALID_REGNUM, // eh_frame reg num
- LLDB_INVALID_REGNUM, // DWARF reg num
- LLDB_INVALID_REGNUM, // generic reg num
- reg_num, // process plugin reg num
- reg_num // native register number
- },
- NULL,
- NULL,
- NULL, // Dwarf expression opcode bytes pointer
- 0 // Dwarf expression opcode bytes length
- };
-
- while (response.GetNameColonValue(name, value))
- {
- if (name.equals("name"))
- {
- reg_name.SetString(value);
- }
- else if (name.equals("alt-name"))
- {
- alt_name.SetString(value);
- }
- else if (name.equals("bitsize"))
- {
- value.getAsInteger(0, reg_info.byte_size);
- reg_info.byte_size /= CHAR_BIT;
- }
- else if (name.equals("offset"))
- {
- if (value.getAsInteger(0, reg_offset))
- reg_offset = UINT32_MAX;
- }
- else if (name.equals("encoding"))
- {
- const Encoding encoding = Args::StringToEncoding(value);
- if (encoding != eEncodingInvalid)
- reg_info.encoding = encoding;
- }
- else if (name.equals("format"))
- {
- Format format = eFormatInvalid;
- if (Args::StringToFormat(value.str().c_str(), format, NULL).Success())
- reg_info.format = format;
- else
- {
- reg_info.format = llvm::StringSwitch<Format>(value)
- .Case("binary", eFormatBinary)
- .Case("decimal", eFormatDecimal)
- .Case("hex", eFormatHex)
- .Case("float", eFormatFloat)
- .Case("vector-sint8", eFormatVectorOfSInt8)
- .Case("vector-uint8", eFormatVectorOfUInt8)
- .Case("vector-sint16", eFormatVectorOfSInt16)
- .Case("vector-uint16", eFormatVectorOfUInt16)
- .Case("vector-sint32", eFormatVectorOfSInt32)
- .Case("vector-uint32", eFormatVectorOfUInt32)
- .Case("vector-float32", eFormatVectorOfFloat32)
- .Case("vector-uint128", eFormatVectorOfUInt128)
- .Default(eFormatInvalid);
- }
- }
- else if (name.equals("set"))
- {
- set_name.SetString(value);
- }
- else if (name.equals("gcc") || name.equals("ehframe"))
- {
- if (value.getAsInteger(0, reg_info.kinds[eRegisterKindEHFrame]))
- reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM;
- }
- else if (name.equals("dwarf"))
- {
- if (value.getAsInteger(0, reg_info.kinds[eRegisterKindDWARF]))
- reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;
- }
- else if (name.equals("generic"))
- {
- reg_info.kinds[eRegisterKindGeneric] = Args::StringToGenericRegister(value);
- }
- else if (name.equals("container-regs"))
- {
- SplitCommaSeparatedRegisterNumberString(value, value_regs, 16);
- }
- else if (name.equals("invalidate-regs"))
- {
- SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16);
- }
- else if (name.equals("dynamic_size_dwarf_expr_bytes"))
- {
- size_t dwarf_opcode_len = value.size() / 2;
- assert(dwarf_opcode_len > 0);
-
- dwarf_opcode_bytes.resize(dwarf_opcode_len);
- reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;
-
- StringExtractor opcode_extractor(value);
- uint32_t ret_val = opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes);
- assert(dwarf_opcode_len == ret_val);
+Error ProcessGDBRemote::WillAttachToProcessWithID(lldb::pid_t pid) {
+ return WillLaunchOrAttach();
+}
- reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data();
- }
- }
+Error ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name,
+ bool wait_for_launch) {
+ return WillLaunchOrAttach();
+}
- reg_info.byte_offset = reg_offset;
- assert (reg_info.byte_size != 0);
- reg_offset += reg_info.byte_size;
- if (!value_regs.empty())
- {
- value_regs.push_back(LLDB_INVALID_REGNUM);
- reg_info.value_regs = value_regs.data();
- }
- if (!invalidate_regs.empty())
- {
- invalidate_regs.push_back(LLDB_INVALID_REGNUM);
- reg_info.invalidate_regs = invalidate_regs.data();
- }
+Error ProcessGDBRemote::DoConnectRemote(Stream *strm, const char *remote_url) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ Error error(WillLaunchOrAttach());
- // We have to make a temporary ABI here, and not use the GetABI because this code
- // gets called in DidAttach, when the target architecture (and consequently the ABI we'll get from
- // the process) may be wrong.
- ABISP abi_to_use = ABI::FindPlugin(arch_to_use);
+ if (error.Fail())
+ return error;
- AugmentRegisterInfoViaABI (reg_info, reg_name, abi_to_use);
+ error = ConnectToDebugserver(remote_url);
- m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
- }
- else
- {
- break; // ensure exit before reg_num is incremented
- }
- }
- else
- {
- break;
- }
- }
+ if (error.Fail())
+ return error;
+ StartAsyncThread();
- if (m_register_info.GetNumRegisters() > 0)
- {
- m_register_info.Finalize(GetTarget().GetArchitecture());
- return;
- }
+ lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
+ 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();
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.GetStopReply(response)) {
+ SetLastStopPacket(response);
- // We didn't get anything if the accumulated reg_num is zero. 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.
- // On the other hand, if the accumulated reg_num is positive, see if we can
- // add composite registers to the existing primordial ones.
- bool from_scratch = (m_register_info.GetNumRegisters() == 0);
+ // '?' Packets must be handled differently in non-stop mode
+ if (GetTarget().GetNonStopModeEnabled())
+ HandleStopReplySequence();
+
+ Target &target = GetTarget();
+ if (!target.GetArchitecture().IsValid()) {
+ if (m_gdb_comm.GetProcessArchitecture().IsValid()) {
+ target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ } else {
+ target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
+ }
+ }
+
+ const StateType state = SetThreadStopInfo(response);
+ if (state != eStateInvalid) {
+ SetPrivateState(state);
+ } else
+ error.SetErrorStringWithFormat("Process %" PRIu64
+ " was reported after connecting to "
+ "'%s', but state was not stopped: %s",
+ pid, remote_url, StateAsCString(state));
+ } else
+ error.SetErrorStringWithFormat("Process %" PRIu64
+ " was reported after connecting to '%s', "
+ "but no stop reply packet was received",
+ pid, remote_url);
+ }
+
+ if (log)
+ log->Printf("ProcessGDBRemote::%s pid %" PRIu64
+ ": normalizing target architecture initial triple: %s "
+ "(GetTarget().GetArchitecture().IsValid() %s, "
+ "m_gdb_comm.GetHostArchitecture().IsValid(): %s)",
+ __FUNCTION__, GetID(),
+ GetTarget().GetArchitecture().GetTriple().getTriple().c_str(),
+ GetTarget().GetArchitecture().IsValid() ? "true" : "false",
+ m_gdb_comm.GetHostArchitecture().IsValid() ? "true" : "false");
+
+ if (error.Success() && !GetTarget().GetArchitecture().IsValid() &&
+ m_gdb_comm.GetHostArchitecture().IsValid()) {
+ // Prefer the *process'* architecture over that of the *host*, if available.
+ if (m_gdb_comm.GetProcessArchitecture().IsValid())
+ GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ else
+ GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture());
+ }
- if (!target_arch.IsValid())
- {
- if (arch_to_use.IsValid()
- && (arch_to_use.GetMachine() == llvm::Triple::arm || arch_to_use.GetMachine() == llvm::Triple::thumb)
- && arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple)
- m_register_info.HardcodeARMRegisters(from_scratch);
- }
- else if (target_arch.GetMachine() == llvm::Triple::arm
- || target_arch.GetMachine() == llvm::Triple::thumb)
- {
- m_register_info.HardcodeARMRegisters(from_scratch);
- }
+ if (log)
+ log->Printf("ProcessGDBRemote::%s pid %" PRIu64
+ ": normalized target architecture triple: %s",
+ __FUNCTION__, GetID(),
+ GetTarget().GetArchitecture().GetTriple().getTriple().c_str());
+
+ if (error.Success()) {
+ PlatformSP platform_sp = GetTarget().GetPlatform();
+ if (platform_sp && platform_sp->IsConnected())
+ SetUnixSignals(platform_sp->GetUnixSignals());
+ else
+ SetUnixSignals(UnixSignals::Create(GetTarget().GetArchitecture()));
+ }
- // At this point, we can finalize our register info.
- m_register_info.Finalize (GetTarget().GetArchitecture());
+ return error;
}
-Error
-ProcessGDBRemote::WillLaunch (Module* module)
-{
- return WillLaunchOrAttach ();
+Error ProcessGDBRemote::WillLaunchOrAttach() {
+ Error error;
+ m_stdio_communication.Clear();
+ return error;
}
-Error
-ProcessGDBRemote::WillAttachToProcessWithID (lldb::pid_t pid)
-{
- return WillLaunchOrAttach ();
-}
+//----------------------------------------------------------------------
+// Process Control
+//----------------------------------------------------------------------
+Error ProcessGDBRemote::DoLaunch(Module *exe_module,
+ ProcessLaunchInfo &launch_info) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ Error error;
+
+ if (log)
+ log->Printf("ProcessGDBRemote::%s() entered", __FUNCTION__);
+
+ uint32_t launch_flags = launch_info.GetFlags().Get();
+ FileSpec stdin_file_spec{};
+ FileSpec stdout_file_spec{};
+ FileSpec stderr_file_spec{};
+ FileSpec working_dir = launch_info.GetWorkingDirectory();
+
+ const FileAction *file_action;
+ file_action = launch_info.GetFileActionForFD(STDIN_FILENO);
+ if (file_action) {
+ if (file_action->GetAction() == FileAction::eFileActionOpen)
+ stdin_file_spec = file_action->GetFileSpec();
+ }
+ file_action = launch_info.GetFileActionForFD(STDOUT_FILENO);
+ if (file_action) {
+ if (file_action->GetAction() == FileAction::eFileActionOpen)
+ stdout_file_spec = file_action->GetFileSpec();
+ }
+ file_action = launch_info.GetFileActionForFD(STDERR_FILENO);
+ if (file_action) {
+ if (file_action->GetAction() == FileAction::eFileActionOpen)
+ stderr_file_spec = file_action->GetFileSpec();
+ }
+
+ if (log) {
+ if (stdin_file_spec || stdout_file_spec || stderr_file_spec)
+ log->Printf("ProcessGDBRemote::%s provided with STDIO paths via "
+ "launch_info: stdin=%s, stdout=%s, stderr=%s",
+ __FUNCTION__,
+ stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
+ stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
+ stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
+ else
+ log->Printf("ProcessGDBRemote::%s no STDIO paths given via launch_info",
+ __FUNCTION__);
+ }
+
+ const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
+ if (stdin_file_spec || disable_stdio) {
+ // the inferior will be reading stdin from the specified file
+ // or stdio is completely disabled
+ m_stdin_forward = false;
+ } else {
+ m_stdin_forward = true;
+ }
+
+ // ::LogSetBitMask (GDBR_LOG_DEFAULT);
+ // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE |
+ // LLDB_LOG_OPTION_PREPEND_TIMESTAMP |
+ // LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
+ // ::LogSetLogFile ("/dev/stdout");
+
+ ObjectFile *object_file = exe_module->GetObjectFile();
+ if (object_file) {
+ error = EstablishConnectionIfNeeded(launch_info);
+ if (error.Success()) {
+ lldb_utility::PseudoTerminal pty;
+ const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
+
+ PlatformSP platform_sp(GetTarget().GetPlatform());
+ if (disable_stdio) {
+ // set to /dev/null unless redirected to a file above
+ if (!stdin_file_spec)
+ stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ if (!stdout_file_spec)
+ stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ if (!stderr_file_spec)
+ stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ } else if (platform_sp && platform_sp->IsHost()) {
+ // 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.
+ if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&
+ pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, NULL, 0)) {
+ FileSpec slave_name{pty.GetSlaveName(NULL, 0), false};
-Error
-ProcessGDBRemote::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch)
-{
- return WillLaunchOrAttach ();
-}
+ if (!stdin_file_spec)
+ stdin_file_spec = slave_name;
-Error
-ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- Error error (WillLaunchOrAttach ());
+ if (!stdout_file_spec)
+ stdout_file_spec = slave_name;
- if (error.Fail())
- return error;
+ if (!stderr_file_spec)
+ stderr_file_spec = slave_name;
+ }
+ if (log)
+ log->Printf(
+ "ProcessGDBRemote::%s adjusted STDIO paths for local platform "
+ "(IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s",
+ __FUNCTION__,
+ stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
+ stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
+ stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
+ }
+
+ if (log)
+ log->Printf("ProcessGDBRemote::%s final STDIO paths after all "
+ "adjustments: stdin=%s, stdout=%s, stderr=%s",
+ __FUNCTION__,
+ stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
+ stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
+ stderr_file_spec ? stderr_file_spec.GetCString()
+ : "<null>");
+
+ if (stdin_file_spec)
+ m_gdb_comm.SetSTDIN(stdin_file_spec);
+ if (stdout_file_spec)
+ m_gdb_comm.SetSTDOUT(stdout_file_spec);
+ if (stderr_file_spec)
+ m_gdb_comm.SetSTDERR(stderr_file_spec);
+
+ m_gdb_comm.SetDisableASLR(launch_flags & eLaunchFlagDisableASLR);
+ m_gdb_comm.SetDetachOnError(launch_flags & eLaunchFlagDetachOnError);
+
+ m_gdb_comm.SendLaunchArchPacket(
+ GetTarget().GetArchitecture().GetArchitectureName());
+
+ const char *launch_event_data = launch_info.GetLaunchEventData();
+ if (launch_event_data != NULL && *launch_event_data != '\0')
+ m_gdb_comm.SendLaunchEventDataPacket(launch_event_data);
+
+ if (working_dir) {
+ 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;
+ }
+ }
- error = ConnectToDebugserver (remote_url);
+ {
+ // Scope for the scoped timeout object
+ GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, 10);
- if (error.Fail())
- return error;
- StartAsyncThread ();
+ int arg_packet_err = m_gdb_comm.SendArgumentsPacket(launch_info);
+ 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);
+ }
+ }
- lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
- 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();
- StringExtractorGDBRemote response;
- if (m_gdb_comm.GetStopReply(response))
- {
- SetLastStopPacket(response);
+ if (GetID() == LLDB_INVALID_PROCESS_ID) {
+ if (log)
+ log->Printf("failed to connect to debugserver: %s",
+ error.AsCString());
+ KillDebugserverProcess();
+ return error;
+ }
- // '?' Packets must be handled differently in non-stop mode
- if (GetTarget().GetNonStopModeEnabled())
- HandleStopReplySequence();
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.GetStopReply(response)) {
+ SetLastStopPacket(response);
+ // '?' Packets must be handled differently in non-stop mode
+ if (GetTarget().GetNonStopModeEnabled())
+ HandleStopReplySequence();
- Target &target = GetTarget();
- if (!target.GetArchitecture().IsValid())
- {
- if (m_gdb_comm.GetProcessArchitecture().IsValid())
- {
- target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
- }
- else
- {
- target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
- }
- }
+ const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture();
- const StateType state = SetThreadStopInfo (response);
- if (state != eStateInvalid)
- {
- SetPrivateState (state);
- }
- else
- error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but state was not stopped: %s", pid, remote_url, StateAsCString (state));
+ if (process_arch.IsValid()) {
+ GetTarget().MergeArchitecture(process_arch);
+ } else {
+ const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();
+ if (host_arch.IsValid())
+ GetTarget().MergeArchitecture(host_arch);
}
- else
- error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but no stop reply packet was received", pid, remote_url);
- }
-
- if (log)
- log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalizing target architecture initial triple: %s (GetTarget().GetArchitecture().IsValid() %s, m_gdb_comm.GetHostArchitecture().IsValid(): %s)", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str (), GetTarget ().GetArchitecture ().IsValid () ? "true" : "false", m_gdb_comm.GetHostArchitecture ().IsValid () ? "true" : "false");
+ SetPrivateState(SetThreadStopInfo(response));
- if (error.Success()
- && !GetTarget().GetArchitecture().IsValid()
- && m_gdb_comm.GetHostArchitecture().IsValid())
- {
- // Prefer the *process'* architecture over that of the *host*, if available.
- if (m_gdb_comm.GetProcessArchitecture().IsValid())
- GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture());
- else
- GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture());
+ 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 ProcessGDBRemote::ConnectToDebugserver(const char *connect_url) {
+ Error error;
+ // Only connect if we have a valid connect URL
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (connect_url && connect_url[0]) {
if (log)
- log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalized target architecture triple: %s", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str ());
+ log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__,
+ connect_url);
+ std::unique_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()) {
+ if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess) {
+ m_gdb_comm.SetConnection(conn_ap.release());
+ break;
+ } else if (error.WasInterrupted()) {
+ // If we were interrupted, don't keep retrying.
+ break;
+ }
+
+ retry_count++;
+
+ if (retry_count >= max_retry_count)
+ break;
- if (error.Success())
- {
- PlatformSP platform_sp = GetTarget().GetPlatform();
- if (platform_sp && platform_sp->IsConnected())
- SetUnixSignals(platform_sp->GetUnixSignals());
- else
- SetUnixSignals(UnixSignals::Create(GetTarget().GetArchitecture()));
+ usleep(100000);
+ }
}
+ }
+ if (!m_gdb_comm.IsConnected()) {
+ if (error.Success())
+ error.SetErrorString("not connected to remote gdb server");
return error;
-}
+ }
-Error
-ProcessGDBRemote::WillLaunchOrAttach ()
-{
- Error error;
- m_stdio_communication.Clear ();
+ // Start the communications read thread so all incoming data can be
+ // parsed into packets and queued as they arrive.
+ if (GetTarget().GetNonStopModeEnabled())
+ m_gdb_comm.StartReadThread();
+
+ // 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(&error)) {
+ m_gdb_comm.Disconnect();
+ if (error.Success())
+ error.SetErrorString("not connected to remote gdb server");
return error;
-}
+ }
-//----------------------------------------------------------------------
-// Process Control
-//----------------------------------------------------------------------
-Error
-ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- Error error;
+ // Send $QNonStop:1 packet on startup if required
+ if (GetTarget().GetNonStopModeEnabled())
+ GetTarget().SetNonStopModeEnabled(m_gdb_comm.SetNonStopMode(true));
+
+ m_gdb_comm.GetEchoSupported();
+ m_gdb_comm.GetThreadSuffixSupported();
+ m_gdb_comm.GetListThreadsInStopReplySupported();
+ m_gdb_comm.GetHostInfo();
+ m_gdb_comm.GetVContSupported('c');
+ m_gdb_comm.GetVAttachOrWaitSupported();
+
+ // Ask the remote server for the default thread id
+ if (GetTarget().GetNonStopModeEnabled())
+ m_gdb_comm.GetDefaultThreadId(m_initial_tid);
- if (log)
- log->Printf ("ProcessGDBRemote::%s() entered", __FUNCTION__);
+ size_t num_cmds = GetExtraStartupCommands().GetArgumentCount();
+ for (size_t idx = 0; idx < num_cmds; idx++) {
+ StringExtractorGDBRemote response;
+ m_gdb_comm.SendPacketAndWaitForResponse(
+ GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false);
+ }
+ return error;
+}
+
+void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::%s()", __FUNCTION__);
+ if (GetID() != LLDB_INVALID_PROCESS_ID) {
+ BuildDynamicRegisterInfo(false);
+
+ // See if the GDB server supports the qHostInfo information
+
+ // See if the GDB server supports the qProcessInfo packet, if so
+ // prefer that over the Host information as it will be more specific
+ // to our process.
- uint32_t launch_flags = launch_info.GetFlags().Get();
- FileSpec stdin_file_spec{};
- FileSpec stdout_file_spec{};
- FileSpec stderr_file_spec{};
- FileSpec working_dir = launch_info.GetWorkingDirectory();
-
- const FileAction *file_action;
- file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
- if (file_action)
- {
- if (file_action->GetAction() == FileAction::eFileActionOpen)
- stdin_file_spec = file_action->GetFileSpec();
- }
- file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
- if (file_action)
- {
- if (file_action->GetAction() == FileAction::eFileActionOpen)
- stdout_file_spec = file_action->GetFileSpec();
- }
- file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
- if (file_action)
- {
- if (file_action->GetAction() == FileAction::eFileActionOpen)
- stderr_file_spec = file_action->GetFileSpec();
+ const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
+ if (remote_process_arch.IsValid()) {
+ process_arch = remote_process_arch;
+ if (log)
+ log->Printf("ProcessGDBRemote::%s gdb-remote had process architecture, "
+ "using %s %s",
+ __FUNCTION__, process_arch.GetArchitectureName()
+ ? process_arch.GetArchitectureName()
+ : "<null>",
+ process_arch.GetTriple().getTriple().c_str()
+ ? process_arch.GetTriple().getTriple().c_str()
+ : "<null>");
+ } else {
+ process_arch = m_gdb_comm.GetHostArchitecture();
+ if (log)
+ log->Printf("ProcessGDBRemote::%s gdb-remote did not have process "
+ "architecture, using gdb-remote host architecture %s %s",
+ __FUNCTION__, process_arch.GetArchitectureName()
+ ? process_arch.GetArchitectureName()
+ : "<null>",
+ process_arch.GetTriple().getTriple().c_str()
+ ? process_arch.GetTriple().getTriple().c_str()
+ : "<null>");
}
- if (log)
- {
- if (stdin_file_spec || stdout_file_spec || stderr_file_spec)
- log->Printf ("ProcessGDBRemote::%s provided with STDIO paths via launch_info: stdin=%s, stdout=%s, stderr=%s",
- __FUNCTION__,
- stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
- stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
- stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
- else
- log->Printf ("ProcessGDBRemote::%s no STDIO paths given via launch_info", __FUNCTION__);
- }
+ if (process_arch.IsValid()) {
+ const ArchSpec &target_arch = GetTarget().GetArchitecture();
+ if (target_arch.IsValid()) {
+ if (log)
+ log->Printf(
+ "ProcessGDBRemote::%s analyzing target arch, currently %s %s",
+ __FUNCTION__, target_arch.GetArchitectureName()
+ ? target_arch.GetArchitectureName()
+ : "<null>",
+ target_arch.GetTriple().getTriple().c_str()
+ ? target_arch.GetTriple().getTriple().c_str()
+ : "<null>");
+
+ // 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 ((process_arch.GetMachine() == llvm::Triple::arm ||
+ process_arch.GetMachine() == llvm::Triple::thumb) &&
+ process_arch.GetTriple().getVendor() == llvm::Triple::Apple) {
+ GetTarget().SetArchitecture(process_arch);
+ if (log)
+ log->Printf("ProcessGDBRemote::%s remote process is ARM/Apple, "
+ "setting target arch to %s %s",
+ __FUNCTION__, process_arch.GetArchitectureName()
+ ? process_arch.GetArchitectureName()
+ : "<null>",
+ process_arch.GetTriple().getTriple().c_str()
+ ? process_arch.GetTriple().getTriple().c_str()
+ : "<null>");
+ } else {
+ // Fill in what is missing in the triple
+ const llvm::Triple &remote_triple = process_arch.GetTriple();
+ llvm::Triple new_target_triple = target_arch.GetTriple();
+ if (new_target_triple.getVendorName().size() == 0) {
+ new_target_triple.setVendor(remote_triple.getVendor());
+
+ if (new_target_triple.getOSName().size() == 0) {
+ new_target_triple.setOS(remote_triple.getOS());
+
+ if (new_target_triple.getEnvironmentName().size() == 0)
+ new_target_triple.setEnvironment(
+ remote_triple.getEnvironment());
+ }
+
+ ArchSpec new_target_arch = target_arch;
+ new_target_arch.SetTriple(new_target_triple);
+ GetTarget().SetArchitecture(new_target_arch);
+ }
+ }
- const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
- if (stdin_file_spec || disable_stdio)
- {
- // the inferior will be reading stdin from the specified file
- // or stdio is completely disabled
- m_stdin_forward = false;
- }
- else
- {
- m_stdin_forward = true;
- }
+ if (log)
+ log->Printf("ProcessGDBRemote::%s final target arch after "
+ "adjustments for remote architecture: %s %s",
+ __FUNCTION__, target_arch.GetArchitectureName()
+ ? target_arch.GetArchitectureName()
+ : "<null>",
+ target_arch.GetTriple().getTriple().c_str()
+ ? target_arch.GetTriple().getTriple().c_str()
+ : "<null>");
+ } else {
+ // The target doesn't have a valid architecture yet, set it from
+ // the architecture we got from the remote GDB server
+ GetTarget().SetArchitecture(process_arch);
+ }
+ }
+
+ // Find out which StructuredDataPlugins are supported by the
+ // debug monitor. These plugins transmit data over async $J packets.
+ auto supported_packets_array =
+ m_gdb_comm.GetSupportedStructuredDataPlugins();
+ if (supported_packets_array)
+ MapSupportedStructuredDataPlugins(*supported_packets_array);
+ }
+}
+
+void ProcessGDBRemote::DidLaunch() {
+ ArchSpec process_arch;
+ DidLaunchOrAttach(process_arch);
+}
+
+Error ProcessGDBRemote::DoAttachToProcessWithID(
+ lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ Error error;
+
+ if (log)
+ log->Printf("ProcessGDBRemote::%s()", __FUNCTION__);
+
+ // Clear out and clean up from any current state
+ Clear();
+ if (attach_pid != LLDB_INVALID_PROCESS_ID) {
+ error = EstablishConnectionIfNeeded(attach_info);
+ if (error.Success()) {
+ m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
+
+ char packet[64];
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid);
+ SetID(attach_pid);
+ m_async_broadcaster.BroadcastEvent(
+ eBroadcastBitAsyncContinue, new EventDataBytes(packet, packet_len));
+ } else
+ SetExitStatus(-1, error.AsCString());
+ }
+
+ return error;
+}
+
+Error ProcessGDBRemote::DoAttachToProcessWithName(
+ const char *process_name, const ProcessAttachInfo &attach_info) {
+ Error error;
+ // Clear out and clean up from any current state
+ Clear();
+
+ if (process_name && process_name[0]) {
+ error = EstablishConnectionIfNeeded(attach_info);
+ if (error.Success()) {
+ StreamString packet;
+
+ m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
+
+ if (attach_info.GetWaitForLaunch()) {
+ if (!m_gdb_comm.GetVAttachOrWaitSupported()) {
+ packet.PutCString("vAttachWait");
+ } else {
+ if (attach_info.GetIgnoreExisting())
+ packet.PutCString("vAttachWait");
+ else
+ packet.PutCString("vAttachOrWait");
+ }
+ } else
+ packet.PutCString("vAttachName");
+ packet.PutChar(';');
+ packet.PutBytesAsRawHex8(process_name, strlen(process_name),
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
+
+ m_async_broadcaster.BroadcastEvent(
+ eBroadcastBitAsyncContinue,
+ new EventDataBytes(packet.GetData(), packet.GetSize()));
+
+ } else
+ SetExitStatus(-1, error.AsCString());
+ }
+ return error;
+}
+
+void ProcessGDBRemote::DidExit() {
+ // When we exit, disconnect from the GDB server communications
+ m_gdb_comm.Disconnect();
+}
+
+void ProcessGDBRemote::DidAttach(ArchSpec &process_arch) {
+ // If you can figure out what the architecture is, fill it in here.
+ process_arch.Clear();
+ DidLaunchOrAttach(process_arch);
+}
+
+Error ProcessGDBRemote::WillResume() {
+ m_continue_c_tids.clear();
+ m_continue_C_tids.clear();
+ m_continue_s_tids.clear();
+ m_continue_S_tids.clear();
+ m_jstopinfo_sp.reset();
+ m_jthreadsinfo_sp.reset();
+ return Error();
+}
+
+Error ProcessGDBRemote::DoResume() {
+ Error error;
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::Resume()");
+
+ ListenerSP listener_sp(
+ Listener::MakeListener("gdb-remote.resume-packet-sent"));
+ if (listener_sp->StartListeningForEvents(
+ &m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent)) {
+ listener_sp->StartListeningForEvents(
+ &m_async_broadcaster,
+ ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit);
+
+ const size_t num_threads = GetThreadList().GetSize();
+
+ StreamString continue_packet;
+ bool continue_packet_error = false;
+ if (m_gdb_comm.HasAnyVContSupport()) {
+ if (!GetTarget().GetNonStopModeEnabled() &&
+ (m_continue_c_tids.size() == num_threads ||
+ (m_continue_c_tids.empty() && m_continue_C_tids.empty() &&
+ m_continue_s_tids.empty() && m_continue_S_tids.empty()))) {
+ // All threads are continuing, just send a "c" packet
+ continue_packet.PutCString("c");
+ } else {
+ 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.4" PRIx64, *t_pos);
+ } else
+ continue_packet_error = true;
+ }
- // ::LogSetBitMask (GDBR_LOG_DEFAULT);
- // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
- // ::LogSetLogFile ("/dev/stdout");
+ 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.4" PRIx64, s_pos->second,
+ s_pos->first);
+ } else
+ continue_packet_error = true;
+ }
- ObjectFile * object_file = exe_module->GetObjectFile();
- if (object_file)
- {
- error = EstablishConnectionIfNeeded (launch_info);
- if (error.Success())
- {
- lldb_utility::PseudoTerminal pty;
- const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
+ 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.4" PRIx64, *t_pos);
+ } else
+ continue_packet_error = true;
+ }
- PlatformSP platform_sp (GetTarget().GetPlatform());
- if (disable_stdio)
- {
- // set to /dev/null unless redirected to a file above
- if (!stdin_file_spec)
- stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);
- if (!stdout_file_spec)
- stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);
- if (!stderr_file_spec)
- stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);
- }
- else if (platform_sp && platform_sp->IsHost())
- {
- // 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.
- if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&
- pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
- {
- FileSpec slave_name{pty.GetSlaveName(NULL, 0), false};
+ 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.4" PRIx64, s_pos->second,
+ s_pos->first);
+ } else
+ continue_packet_error = true;
+ }
- if (!stdin_file_spec)
- stdin_file_spec = slave_name;
+ 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_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...
+ 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
+ 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...
+ m_gdb_comm.SetCurrentThreadForRun(-1);
+
+ // If in Non-Stop-Mode use vCont when stepping
+ if (GetTarget().GetNonStopModeEnabled()) {
+ if (m_gdb_comm.GetVContSupported('s'))
+ continue_packet.PutCString("vCont;s");
+ else
+ continue_packet.PutChar('s');
+ } else
+ 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
+ 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...
+ 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
+ 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 (!stdout_file_spec)
- stdout_file_spec = slave_name;
+ if (continue_packet_error) {
+ error.SetErrorString("can't make continue packet for this resume");
+ } else {
+ EventSP event_sp;
+ if (!m_async_thread.IsJoinable()) {
+ error.SetErrorString("Trying to resume but the async thread is dead.");
+ if (log)
+ log->Printf("ProcessGDBRemote::DoResume: Trying to resume but the "
+ "async thread is dead.");
+ return error;
+ }
- if (!stderr_file_spec)
- stderr_file_spec = slave_name;
- }
- if (log)
- log->Printf ("ProcessGDBRemote::%s adjusted STDIO paths for local platform (IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s",
- __FUNCTION__,
- stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
- stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
- stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
- }
-
- if (log)
- log->Printf ("ProcessGDBRemote::%s final STDIO paths after all adjustments: stdin=%s, stdout=%s, stderr=%s",
- __FUNCTION__,
- stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
- stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
- stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
-
- if (stdin_file_spec)
- m_gdb_comm.SetSTDIN(stdin_file_spec);
- if (stdout_file_spec)
- m_gdb_comm.SetSTDOUT(stdout_file_spec);
- if (stderr_file_spec)
- m_gdb_comm.SetSTDERR(stderr_file_spec);
-
- m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
- m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError);
-
- m_gdb_comm.SendLaunchArchPacket (GetTarget().GetArchitecture().GetArchitectureName());
-
- const char * launch_event_data = launch_info.GetLaunchEventData();
- if (launch_event_data != NULL && *launch_event_data != '\0')
- m_gdb_comm.SendLaunchEventDataPacket (launch_event_data);
-
- if (working_dir)
- {
- 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;
- }
- }
-
- {
- // Scope for the scoped timeout object
- GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10);
-
- int arg_packet_err = m_gdb_comm.SendArgumentsPacket (launch_info);
- 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);
- }
- }
-
- if (GetID() == LLDB_INVALID_PROCESS_ID)
- {
- if (log)
- log->Printf("failed to connect to debugserver: %s", error.AsCString());
- KillDebugserverProcess ();
- return error;
- }
-
- StringExtractorGDBRemote response;
- if (m_gdb_comm.GetStopReply(response))
- {
- SetLastStopPacket(response);
- // '?' Packets must be handled differently in non-stop mode
- if (GetTarget().GetNonStopModeEnabled())
- HandleStopReplySequence();
-
- const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture();
-
- if (process_arch.IsValid())
- {
- GetTarget().MergeArchitecture(process_arch);
- }
- else
- {
- const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();
- if (host_arch.IsValid())
- GetTarget().MergeArchitecture(host_arch);
- }
-
- SetPrivateState (SetThreadStopInfo (response));
-
- 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
-ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
-{
- Error error;
- // Only connect if we have a valid connect URL
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
-
- if (connect_url && connect_url[0])
- {
- if (log)
- log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, connect_url);
- std::unique_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())
- {
- if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
- {
- m_gdb_comm.SetConnection (conn_ap.release());
- break;
- }
- else if (error.WasInterrupted())
- {
- // If we were interrupted, don't keep retrying.
- 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;
- }
-
-
- // Start the communications read thread so all incoming data can be
- // parsed into packets and queued as they arrive.
- if (GetTarget().GetNonStopModeEnabled())
- m_gdb_comm.StartReadThread();
-
- // 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 (&error))
- {
- m_gdb_comm.Disconnect();
- if (error.Success())
- error.SetErrorString("not connected to remote gdb server");
- return error;
- }
-
- // Send $QNonStop:1 packet on startup if required
- if (GetTarget().GetNonStopModeEnabled())
- GetTarget().SetNonStopModeEnabled (m_gdb_comm.SetNonStopMode(true));
-
- m_gdb_comm.GetEchoSupported ();
- m_gdb_comm.GetThreadSuffixSupported ();
- m_gdb_comm.GetListThreadsInStopReplySupported ();
- m_gdb_comm.GetHostInfo ();
- m_gdb_comm.GetVContSupported ('c');
- m_gdb_comm.GetVAttachOrWaitSupported();
-
- // Ask the remote server for the default thread id
- if (GetTarget().GetNonStopModeEnabled())
- m_gdb_comm.GetDefaultThreadId(m_initial_tid);
-
-
- size_t num_cmds = GetExtraStartupCommands().GetArgumentCount();
- for (size_t idx = 0; idx < num_cmds; idx++)
- {
- StringExtractorGDBRemote response;
- m_gdb_comm.SendPacketAndWaitForResponse (GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false);
- }
- return error;
-}
-
-void
-ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::%s()", __FUNCTION__);
- if (GetID() != LLDB_INVALID_PROCESS_ID)
- {
- BuildDynamicRegisterInfo (false);
-
- // See if the GDB server supports the qHostInfo information
-
-
- // See if the GDB server supports the qProcessInfo packet, if so
- // prefer that over the Host information as it will be more specific
- // to our process.
-
- const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
- if (remote_process_arch.IsValid())
- {
- process_arch = remote_process_arch;
- if (log)
- log->Printf ("ProcessGDBRemote::%s gdb-remote had process architecture, using %s %s",
- __FUNCTION__,
- process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
- process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
- }
- else
- {
- process_arch = m_gdb_comm.GetHostArchitecture();
- if (log)
- log->Printf ("ProcessGDBRemote::%s gdb-remote did not have process architecture, using gdb-remote host architecture %s %s",
- __FUNCTION__,
- process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
- process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
- }
-
- if (process_arch.IsValid())
- {
- const ArchSpec &target_arch = GetTarget().GetArchitecture();
- if (target_arch.IsValid())
- {
- if (log)
- log->Printf ("ProcessGDBRemote::%s analyzing target arch, currently %s %s",
- __FUNCTION__,
- target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>",
- target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>");
-
- // 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 ((process_arch.GetMachine() == llvm::Triple::arm || process_arch.GetMachine() == llvm::Triple::thumb)
- && process_arch.GetTriple().getVendor() == llvm::Triple::Apple)
- {
- GetTarget().SetArchitecture (process_arch);
- if (log)
- log->Printf ("ProcessGDBRemote::%s remote process is ARM/Apple, setting target arch to %s %s",
- __FUNCTION__,
- process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
- process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
- }
- else
- {
- // Fill in what is missing in the triple
- const llvm::Triple &remote_triple = process_arch.GetTriple();
- llvm::Triple new_target_triple = target_arch.GetTriple();
- if (new_target_triple.getVendorName().size() == 0)
- {
- new_target_triple.setVendor (remote_triple.getVendor());
-
- if (new_target_triple.getOSName().size() == 0)
- {
- new_target_triple.setOS (remote_triple.getOS());
-
- if (new_target_triple.getEnvironmentName().size() == 0)
- new_target_triple.setEnvironment (remote_triple.getEnvironment());
- }
-
- ArchSpec new_target_arch = target_arch;
- new_target_arch.SetTriple(new_target_triple);
- GetTarget().SetArchitecture(new_target_arch);
- }
- }
-
- if (log)
- log->Printf ("ProcessGDBRemote::%s final target arch after adjustments for remote architecture: %s %s",
- __FUNCTION__,
- target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>",
- target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>");
- }
- else
- {
- // The target doesn't have a valid architecture yet, set it from
- // the architecture we got from the remote GDB server
- GetTarget().SetArchitecture (process_arch);
- }
- }
-
- // Find out which StructuredDataPlugins are supported by the
- // debug monitor. These plugins transmit data over async $J packets.
- auto supported_packets_array =
- m_gdb_comm.GetSupportedStructuredDataPlugins();
- if (supported_packets_array)
- MapSupportedStructuredDataPlugins(*supported_packets_array);
- }
-}
-
-void
-ProcessGDBRemote::DidLaunch ()
-{
- ArchSpec process_arch;
- DidLaunchOrAttach (process_arch);
-}
-
-Error
-ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- Error error;
-
- if (log)
- log->Printf ("ProcessGDBRemote::%s()", __FUNCTION__);
-
- // Clear out and clean up from any current state
- Clear();
- if (attach_pid != LLDB_INVALID_PROCESS_ID)
- {
- error = EstablishConnectionIfNeeded (attach_info);
- if (error.Success())
- {
- m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
-
- char packet[64];
- const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid);
- SetID (attach_pid);
- m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));
- }
- else
- SetExitStatus (-1, error.AsCString());
- }
-
- return error;
-}
-
-Error
-ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const ProcessAttachInfo &attach_info)
-{
- Error error;
- // Clear out and clean up from any current state
- Clear();
-
- if (process_name && process_name[0])
- {
- error = EstablishConnectionIfNeeded (attach_info);
- if (error.Success())
- {
- StreamString packet;
-
- m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
-
- if (attach_info.GetWaitForLaunch())
- {
- if (!m_gdb_comm.GetVAttachOrWaitSupported())
- {
- packet.PutCString ("vAttachWait");
- }
- else
- {
- if (attach_info.GetIgnoreExisting())
- packet.PutCString("vAttachWait");
- else
- packet.PutCString ("vAttachOrWait");
- }
- }
- else
- packet.PutCString("vAttachName");
- packet.PutChar(';');
- packet.PutBytesAsRawHex8(process_name, strlen(process_name), endian::InlHostByteOrder(), endian::InlHostByteOrder());
-
- m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize()));
-
- }
- else
- SetExitStatus (-1, error.AsCString());
- }
- return error;
-}
-
-void
-ProcessGDBRemote::DidExit ()
-{
- // When we exit, disconnect from the GDB server communications
- m_gdb_comm.Disconnect();
-}
-
-void
-ProcessGDBRemote::DidAttach (ArchSpec &process_arch)
-{
- // If you can figure out what the architecture is, fill it in here.
- process_arch.Clear();
- DidLaunchOrAttach (process_arch);
-}
-
-
-Error
-ProcessGDBRemote::WillResume ()
-{
- m_continue_c_tids.clear();
- m_continue_C_tids.clear();
- m_continue_s_tids.clear();
- m_continue_S_tids.clear();
- m_jstopinfo_sp.reset();
- m_jthreadsinfo_sp.reset();
- return Error();
-}
-
-Error
-ProcessGDBRemote::DoResume ()
-{
- Error error;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::Resume()");
-
- ListenerSP listener_sp (Listener::MakeListener("gdb-remote.resume-packet-sent"));
- if (listener_sp->StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent))
- {
- listener_sp->StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit);
-
- const size_t num_threads = GetThreadList().GetSize();
-
- StreamString continue_packet;
- bool continue_packet_error = false;
- if (m_gdb_comm.HasAnyVContSupport ())
- {
- if (!GetTarget().GetNonStopModeEnabled() &&
- (m_continue_c_tids.size() == num_threads ||
- (m_continue_c_tids.empty() &&
- m_continue_C_tids.empty() &&
- m_continue_s_tids.empty() &&
- m_continue_S_tids.empty())))
- {
- // All threads are continuing, just send a "c" packet
- continue_packet.PutCString ("c");
- }
- else
- {
- 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.4" PRIx64, *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.4" PRIx64, 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.4" PRIx64, *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.4" PRIx64, 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_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...
- 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
- 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...
- m_gdb_comm.SetCurrentThreadForRun (-1);
-
- // If in Non-Stop-Mode use vCont when stepping
- if (GetTarget().GetNonStopModeEnabled())
- {
- if (m_gdb_comm.GetVContSupported('s'))
- continue_packet.PutCString("vCont;s");
- else
- continue_packet.PutChar('s');
- }
- else
- 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
- 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...
- 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
- 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;
- if (!m_async_thread.IsJoinable())
- {
- error.SetErrorString ("Trying to resume but the async thread is dead.");
- if (log)
- log->Printf ("ProcessGDBRemote::DoResume: Trying to resume but the async thread is dead.");
- return error;
- }
-
- m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize()));
-
- if (listener_sp->WaitForEvent(std::chrono::seconds(5), event_sp) == false)
- {
- error.SetErrorString("Resume timed out.");
- if (log)
- log->Printf ("ProcessGDBRemote::DoResume: Resume timed out.");
- }
- else if (event_sp->BroadcasterIs (&m_async_broadcaster))
- {
- error.SetErrorString ("Broadcast continue, but the async thread was killed before we got an ack back.");
- if (log)
- log->Printf ("ProcessGDBRemote::DoResume: Broadcast continue, but the async thread was killed before we got an ack back.");
- return error;
- }
- }
- }
-
- return error;
-}
-
-void
-ProcessGDBRemote::HandleStopReplySequence ()
-{
- while(true)
- {
- // Send vStopped
- StringExtractorGDBRemote response;
- m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false);
-
- // OK represents end of signal list
- if (response.IsOKResponse())
- break;
-
- // If not OK or a normal packet we have a problem
- if (!response.IsNormalResponse())
- break;
-
- SetLastStopPacket(response);
- }
-}
-
-void
-ProcessGDBRemote::ClearThreadIDList ()
-{
- std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
- m_thread_ids.clear();
- m_thread_pcs.clear();
-}
-
-size_t
-ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)
-{
- m_thread_ids.clear();
- m_thread_pcs.clear();
- size_t comma_pos;
- lldb::tid_t tid;
- while ((comma_pos = value.find(',')) != std::string::npos)
- {
- value[comma_pos] = '\0';
- // thread in big endian hex
- tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
- if (tid != LLDB_INVALID_THREAD_ID)
- m_thread_ids.push_back (tid);
- value.erase(0, comma_pos + 1);
- }
- tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
- if (tid != LLDB_INVALID_THREAD_ID)
- m_thread_ids.push_back (tid);
- return m_thread_ids.size();
-}
-
-size_t
-ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue (std::string &value)
-{
- m_thread_pcs.clear();
- size_t comma_pos;
- lldb::addr_t pc;
- while ((comma_pos = value.find(',')) != std::string::npos)
- {
- value[comma_pos] = '\0';
- pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
- if (pc != LLDB_INVALID_ADDRESS)
- m_thread_pcs.push_back (pc);
- value.erase(0, comma_pos + 1);
- }
- pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
- if (pc != LLDB_INVALID_THREAD_ID)
- m_thread_pcs.push_back (pc);
- return m_thread_pcs.size();
-}
-
-bool
-ProcessGDBRemote::UpdateThreadIDList ()
-{
- std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
-
- if (m_jthreadsinfo_sp)
- {
- // If we have the JSON threads info, we can get the thread list from that
- StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
- if (thread_infos && thread_infos->GetSize() > 0)
- {
- m_thread_ids.clear();
- m_thread_pcs.clear();
- thread_infos->ForEach([this](StructuredData::Object* object) -> bool {
- StructuredData::Dictionary *thread_dict = object->GetAsDictionary();
- if (thread_dict)
- {
- // Set the thread stop info from the JSON dictionary
- SetThreadStopInfo (thread_dict);
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid))
- m_thread_ids.push_back(tid);
- }
- return true; // Keep iterating through all thread_info objects
- });
- }
- if (!m_thread_ids.empty())
- return true;
- }
- else
- {
- // See if we can get the thread IDs from the current stop reply packets
- // that might contain a "threads" key/value pair
-
- // Lock the thread stack while we access it
- //Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
- std::unique_lock<std::recursive_mutex> stop_stack_lock(m_last_stop_packet_mutex, std::defer_lock);
- if (stop_stack_lock.try_lock())
- {
- // Get the number of stop packets on the stack
- int nItems = m_stop_packet_stack.size();
- // Iterate over them
- for (int i = 0; i < nItems; i++)
- {
- // Get the thread stop info
- StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i];
- const std::string &stop_info_str = stop_info.GetStringRef();
-
- m_thread_pcs.clear();
- const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:");
- if (thread_pcs_pos != std::string::npos)
- {
- const size_t start = thread_pcs_pos + strlen(";thread-pcs:");
- const size_t end = stop_info_str.find(';', start);
- if (end != std::string::npos)
- {
- std::string value = stop_info_str.substr(start, end - start);
- UpdateThreadPCsFromStopReplyThreadsValue(value);
- }
- }
-
- const size_t threads_pos = stop_info_str.find(";threads:");
- if (threads_pos != std::string::npos)
- {
- const size_t start = threads_pos + strlen(";threads:");
- const size_t end = stop_info_str.find(';', start);
- if (end != std::string::npos)
- {
- std::string value = stop_info_str.substr(start, end - start);
- if (UpdateThreadIDsFromStopReplyThreadsValue(value))
- return true;
- }
- }
- }
- }
- }
-
- bool sequence_mutex_unavailable = false;
- m_gdb_comm.GetCurrentThreadIDs (m_thread_ids, sequence_mutex_unavailable);
- if (sequence_mutex_unavailable)
- {
- return false; // We just didn't get the list
- }
- return true;
-}
-
-bool
-ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
-{
- // locker will keep a mutex locked until it goes out of scope
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD));
- if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
- log->Printf ("ProcessGDBRemote::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());
-
- size_t num_thread_ids = m_thread_ids.size();
- // The "m_thread_ids" thread ID list should always be updated after each stop
- // reply packet, but in case it isn't, update it here.
- if (num_thread_ids == 0)
- {
- if (!UpdateThreadIDList ())
- return false;
- num_thread_ids = m_thread_ids.size();
- }
-
- ThreadList old_thread_list_copy(old_thread_list);
- if (num_thread_ids > 0)
- {
- for (size_t i=0; i<num_thread_ids; ++i)
- {
- tid_t tid = m_thread_ids[i];
- ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByProtocolID(tid, false));
- if (!thread_sp)
- {
- thread_sp.reset (new ThreadGDBRemote (*this, tid));
- if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
- log->Printf(
- "ProcessGDBRemote::%s Making new thread: %p for thread ID: 0x%" PRIx64 ".\n",
- __FUNCTION__, static_cast<void*>(thread_sp.get()),
- thread_sp->GetID());
- }
- else
- {
- if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
- log->Printf(
- "ProcessGDBRemote::%s Found old thread: %p for thread ID: 0x%" PRIx64 ".\n",
- __FUNCTION__, static_cast<void*>(thread_sp.get()),
- thread_sp->GetID());
- }
- // The m_thread_pcs vector has pc values in big-endian order, not target-endian, unlike most
- // of the register read/write packets in gdb-remote protocol.
- // Early in the process startup, we may not yet have set the process ByteOrder so we ignore these;
- // they are a performance improvement over fetching thread register values individually, the
- // method we will fall back to if needed.
- if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && GetByteOrder() != eByteOrderInvalid)
- {
- ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
- RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext());
- if (reg_ctx_sp)
- {
- uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber
- (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- if (pc_regnum != LLDB_INVALID_REGNUM)
- {
- gdb_thread->PrivateSetRegisterValue (pc_regnum, m_thread_pcs[i]);
- }
- }
- }
- new_thread_list.AddThreadSortedByIndexID (thread_sp);
- }
- }
-
- // Whatever that is left in old_thread_list_copy are not
- // present in new_thread_list. Remove non-existent threads from internal id table.
- size_t old_num_thread_ids = old_thread_list_copy.GetSize(false);
- for (size_t i=0; i<old_num_thread_ids; i++)
- {
- ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex (i, false));
- if (old_thread_sp)
- {
- lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID();
- m_thread_id_to_index_id_map.erase(old_thread_id);
- }
- }
-
- return true;
-}
-
-
-bool
-ProcessGDBRemote::GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp)
-{
- // See if we got thread stop infos for all threads via the "jThreadsInfo" packet
- if (thread_infos_sp)
- {
- StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray();
- if (thread_infos)
- {
- lldb::tid_t tid;
- const size_t n = thread_infos->GetSize();
- for (size_t i=0; i<n; ++i)
- {
- StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary();
- if (thread_dict)
- {
- if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid, LLDB_INVALID_THREAD_ID))
- {
- if (tid == thread->GetID())
- return (bool)SetThreadStopInfo(thread_dict);
- }
- }
- }
- }
- }
- return false;
-}
-
-bool
-ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)
-{
- // See if we got thread stop infos for all threads via the "jThreadsInfo" packet
- if (GetThreadStopInfoFromJSON (thread, m_jthreadsinfo_sp))
- return true;
-
- // See if we got thread stop info for any threads valid stop info reasons threads
- // via the "jstopinfo" packet stop reply packet key/value pair?
- if (m_jstopinfo_sp)
- {
- // If we have "jstopinfo" then we have stop descriptions for all threads
- // that have stop reasons, and if there is no entry for a thread, then
- // it has no stop reason.
- thread->GetRegisterContext()->InvalidateIfNeeded(true);
- if (!GetThreadStopInfoFromJSON (thread, m_jstopinfo_sp))
- {
- thread->SetStopInfo (StopInfoSP());
- }
- return true;
- }
-
- // Fall back to using the qThreadStopInfo packet
- StringExtractorGDBRemote stop_packet;
- if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet))
- return SetThreadStopInfo (stop_packet) == eStateStopped;
- return false;
-}
-
-
-ThreadSP
-ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
- ExpeditedRegisterMap &expedited_register_map,
- uint8_t signo,
- const std::string &thread_name,
- const std::string &reason,
- const std::string &description,
- uint32_t exc_type,
- const std::vector<addr_t> &exc_data,
- addr_t thread_dispatch_qaddr,
- bool queue_vars_valid, // Set to true if queue_name, queue_kind and queue_serial are valid
- LazyBool associated_with_dispatch_queue,
- addr_t dispatch_queue_t,
- std::string &queue_name,
- QueueKind queue_kind,
- uint64_t queue_serial)
-{
- ThreadSP thread_sp;
- if (tid != LLDB_INVALID_THREAD_ID)
- {
- // Scope for "locker" below
- {
- // m_thread_list_real does have its own mutex, but we need to
- // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...)
- // and the m_thread_list_real.AddThread(...) so it doesn't change on us
- std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
- thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false);
-
- if (!thread_sp)
- {
- // Create the thread if we need to
- thread_sp.reset (new ThreadGDBRemote (*this, tid));
- m_thread_list_real.AddThread(thread_sp);
- }
- }
-
- if (thread_sp)
- {
- ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
- gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true);
-
- for (const auto &pair : expedited_register_map)
- {
- StringExtractor reg_value_extractor;
- reg_value_extractor.GetStringRef() = pair.second;
- DataBufferSP buffer_sp(new DataBufferHeap(reg_value_extractor.GetStringRef().size() / 2, 0));
- reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc');
- gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData());
- }
-
- thread_sp->SetName (thread_name.empty() ? NULL : thread_name.c_str());
-
- gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr);
- // Check if the GDB server was able to provide the queue name, kind and serial number
- if (queue_vars_valid)
- gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial, dispatch_queue_t, associated_with_dispatch_queue);
- else
- gdb_thread->ClearQueueInfo();
-
- gdb_thread->SetAssociatedWithLibdispatchQueue (associated_with_dispatch_queue);
-
- if (dispatch_queue_t != LLDB_INVALID_ADDRESS)
- gdb_thread->SetQueueLibdispatchQueueAddress (dispatch_queue_t);
-
- // Make sure we update our thread stop reason just once
- if (!thread_sp->StopInfoIsUpToDate())
- {
- thread_sp->SetStopInfo (StopInfoSP());
- // If there's a memory thread backed by this thread, we need to use it to calcualte StopInfo.
- ThreadSP memory_thread_sp = m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID());
- if (memory_thread_sp)
- thread_sp = memory_thread_sp;
-
- if (exc_type != 0)
- {
- const size_t exc_data_size = exc_data.size();
-
- thread_sp->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;
- bool did_exec = false;
- if (!reason.empty())
- {
- if (reason.compare("trace") == 0)
- {
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
- lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
-
- // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint
- // Otherwise, it will be set to Trace.
- if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get()))
- {
- thread_sp->SetStopInfo(
- StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID()));
- }
- else
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
- handled = true;
- }
- else if (reason.compare("breakpoint") == 0)
- {
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
- lldb::BreakpointSiteSP bp_site_sp = thread_sp->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.
- handled = true;
- if (bp_site_sp->ValidForThisThread (thread_sp.get()))
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
- }
- else
- {
- StopInfoSP invalid_stop_info_sp;
- thread_sp->SetStopInfo (invalid_stop_info_sp);
- }
- }
- }
- else if (reason.compare("trap") == 0)
- {
- // Let the trap just use the standard signal stop reason below...
- }
- else if (reason.compare("watchpoint") == 0)
- {
- StringExtractor desc_extractor(description.c_str());
- addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
- uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
- addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
- watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
- if (wp_addr != LLDB_INVALID_ADDRESS)
- {
- WatchpointSP wp_sp;
- ArchSpec::Core core = GetTarget().GetArchitecture().GetCore();
- if ((core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) ||
- (core >= ArchSpec::eCore_arm_generic && core <= ArchSpec::eCore_arm_aarch64))
- wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr);
- if (!wp_sp)
- wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);
- if (wp_sp)
- {
- wp_sp->SetHardwareIndex(wp_index);
- watch_id = wp_sp->GetID();
- }
- }
- if (watch_id == LLDB_INVALID_WATCH_ID)
- {
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS));
- if (log) log->Printf ("failed to find watchpoint");
- }
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr));
- handled = true;
- }
- else if (reason.compare("exception") == 0)
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str()));
- handled = true;
- }
- else if (reason.compare("exec") == 0)
- {
- did_exec = true;
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp));
- handled = true;
- }
- }
- else if (!signo)
- {
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
- lldb::BreakpointSiteSP bp_site_sp =
- thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
-
- // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint
- // even though the remote stub did not set it as such. This can happen when
- // the thread is involuntarily interrupted (e.g. due to stops on other
- // threads) just as it is about to execute the breakpoint instruction.
- if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get()))
- {
- thread_sp->SetStopInfo(
- StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID()));
- handled = true;
- }
- }
-
- if (!handled && signo && did_exec == false)
- {
- if (signo == SIGTRAP)
- {
- // Currently we are going to assume SIGTRAP means we are either
- // hitting a breakpoint or hardware single stepping.
- handled = true;
- addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
- lldb::BreakpointSiteSP bp_site_sp = thread_sp->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 (thread_sp.get()))
- {
- if(m_breakpoint_pc_offset != 0)
- thread_sp->GetRegisterContext()->SetPC(pc);
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
- }
- else
- {
- StopInfoSP invalid_stop_info_sp;
- thread_sp->SetStopInfo (invalid_stop_info_sp);
- }
- }
- else
- {
- // If we were stepping then assume the stop was the result of the trace. If we were
- // not stepping then report the SIGTRAP.
- // FIXME: We are still missing the case where we single step over a trap instruction.
- if (thread_sp->GetTemporaryResumeState() == eStateStepping)
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
- else
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str()));
- }
- }
- if (!handled)
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str()));
- }
-
- if (!description.empty())
- {
- lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
- if (stop_info_sp)
- {
- const char *stop_info_desc = stop_info_sp->GetDescription();
- if (!stop_info_desc || !stop_info_desc[0])
- stop_info_sp->SetDescription (description.c_str());
- }
- else
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str()));
- }
- }
- }
- }
- }
- }
- return thread_sp;
-}
-
-lldb::ThreadSP
-ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
-{
- static ConstString g_key_tid("tid");
- static ConstString g_key_name("name");
- static ConstString g_key_reason("reason");
- static ConstString g_key_metype("metype");
- static ConstString g_key_medata("medata");
- static ConstString g_key_qaddr("qaddr");
- static ConstString g_key_dispatch_queue_t("dispatch_queue_t");
- static ConstString g_key_associated_with_dispatch_queue("associated_with_dispatch_queue");
- static ConstString g_key_queue_name("qname");
- static ConstString g_key_queue_kind("qkind");
- static ConstString g_key_queue_serial_number("qserialnum");
- static ConstString g_key_registers("registers");
- static ConstString g_key_memory("memory");
- static ConstString g_key_address("address");
- static ConstString g_key_bytes("bytes");
- static ConstString g_key_description("description");
- static ConstString g_key_signal("signal");
-
- // Stop with signal and thread info
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- uint8_t signo = 0;
- std::string value;
- std::string thread_name;
- std::string reason;
- std::string description;
- uint32_t exc_type = 0;
- std::vector<addr_t> exc_data;
- addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
- ExpeditedRegisterMap expedited_register_map;
- bool queue_vars_valid = false;
- addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
- LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
- std::string queue_name;
- QueueKind queue_kind = eQueueKindUnknown;
- uint64_t queue_serial_number = 0;
- // Iterate through all of the thread dictionary key/value pairs from the structured data dictionary
-
- thread_dict->ForEach([this,
- &tid,
- &expedited_register_map,
- &thread_name,
- &signo,
- &reason,
- &description,
- &exc_type,
- &exc_data,
- &thread_dispatch_qaddr,
- &queue_vars_valid,
- &associated_with_dispatch_queue,
- &dispatch_queue_t,
- &queue_name,
- &queue_kind,
- &queue_serial_number]
- (ConstString key, StructuredData::Object* object) -> bool
- {
- if (key == g_key_tid)
- {
- // thread in big endian hex
- tid = object->GetIntegerValue(LLDB_INVALID_THREAD_ID);
- }
- else if (key == g_key_metype)
- {
- // exception type in big endian hex
- exc_type = object->GetIntegerValue(0);
- }
- else if (key == g_key_medata)
- {
- // exception data in big endian hex
- StructuredData::Array *array = object->GetAsArray();
- if (array)
- {
- array->ForEach([&exc_data](StructuredData::Object* object) -> bool {
- exc_data.push_back(object->GetIntegerValue());
- return true; // Keep iterating through all array items
- });
- }
- }
- else if (key == g_key_name)
- {
- thread_name = object->GetStringValue();
- }
- else if (key == g_key_qaddr)
- {
- thread_dispatch_qaddr = object->GetIntegerValue(LLDB_INVALID_ADDRESS);
- }
- else if (key == g_key_queue_name)
- {
- queue_vars_valid = true;
- queue_name = object->GetStringValue();
- }
- else if (key == g_key_queue_kind)
- {
- std::string queue_kind_str = object->GetStringValue();
- if (queue_kind_str == "serial")
- {
- queue_vars_valid = true;
- queue_kind = eQueueKindSerial;
- }
- else if (queue_kind_str == "concurrent")
- {
- queue_vars_valid = true;
- queue_kind = eQueueKindConcurrent;
- }
- }
- else if (key == g_key_queue_serial_number)
- {
- queue_serial_number = object->GetIntegerValue(0);
- if (queue_serial_number != 0)
- queue_vars_valid = true;
- }
- else if (key == g_key_dispatch_queue_t)
- {
- dispatch_queue_t = object->GetIntegerValue(0);
- if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS)
- queue_vars_valid = true;
- }
- else if (key == g_key_associated_with_dispatch_queue)
- {
- queue_vars_valid = true;
- bool associated = object->GetBooleanValue ();
- if (associated)
- associated_with_dispatch_queue = eLazyBoolYes;
- else
- associated_with_dispatch_queue = eLazyBoolNo;
- }
- else if (key == g_key_reason)
- {
- reason = object->GetStringValue();
- }
- else if (key == g_key_description)
- {
- description = object->GetStringValue();
- }
- else if (key == g_key_registers)
- {
- StructuredData::Dictionary *registers_dict = object->GetAsDictionary();
-
- if (registers_dict)
- {
- registers_dict->ForEach([&expedited_register_map](ConstString key, StructuredData::Object* object) -> bool {
- const uint32_t reg = StringConvert::ToUInt32 (key.GetCString(), UINT32_MAX, 10);
- if (reg != UINT32_MAX)
- expedited_register_map[reg] = object->GetStringValue();
- return true; // Keep iterating through all array items
- });
- }
- }
- else if (key == g_key_memory)
- {
- StructuredData::Array *array = object->GetAsArray();
- if (array)
- {
- array->ForEach([this](StructuredData::Object* object) -> bool {
- StructuredData::Dictionary *mem_cache_dict = object->GetAsDictionary();
- if (mem_cache_dict)
- {
- lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS;
- if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>("address", mem_cache_addr))
- {
- if (mem_cache_addr != LLDB_INVALID_ADDRESS)
- {
- StringExtractor bytes;
- if (mem_cache_dict->GetValueForKeyAsString("bytes", bytes.GetStringRef()))
- {
- bytes.SetFilePos(0);
-
- const size_t byte_size = bytes.GetStringRef().size()/2;
- DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
- const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetData(), 0);
- if (bytes_copied == byte_size)
- m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp);
- }
- }
- }
- }
- return true; // Keep iterating through all array items
- });
- }
-
- }
- else if (key == g_key_signal)
- signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER);
- return true; // Keep iterating through all dictionary key/value pairs
- });
-
- return SetThreadStopInfo (tid,
- expedited_register_map,
- signo,
- thread_name,
- reason,
- description,
- exc_type,
- exc_data,
- thread_dispatch_qaddr,
- queue_vars_valid,
- associated_with_dispatch_queue,
- dispatch_queue_t,
- queue_name,
- queue_kind,
- queue_serial_number);
-}
-
-StateType
-ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
-{
- stop_packet.SetFilePos (0);
- const char stop_type = stop_packet.GetChar();
- switch (stop_type)
- {
- case 'T':
- case 'S':
- {
- // This is a bit of a hack, but is is required. If we did exec, we
- // need to clear our thread lists and also know to rebuild our dynamic
- // register info before we lookup and threads and populate the expedited
- // register values so we need to know this right away so we can cleanup
- // and update our registers.
- const uint32_t stop_id = GetStopID();
- if (stop_id == 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
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- const uint8_t signo = stop_packet.GetHexU8();
- llvm::StringRef key;
- llvm::StringRef value;
- std::string thread_name;
- std::string reason;
- std::string description;
- uint32_t exc_type = 0;
- std::vector<addr_t> exc_data;
- addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
- bool queue_vars_valid = false; // says if locals below that start with "queue_" are valid
- addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
- LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
- std::string queue_name;
- QueueKind queue_kind = eQueueKindUnknown;
- uint64_t queue_serial_number = 0;
- ExpeditedRegisterMap expedited_register_map;
- while (stop_packet.GetNameColonValue(key, value))
- {
- if (key.compare("metype") == 0)
- {
- // exception type in big endian hex
- value.getAsInteger(16, exc_type);
- }
- else if (key.compare("medata") == 0)
- {
- // exception data in big endian hex
- uint64_t x;
- value.getAsInteger(16, x);
- exc_data.push_back(x);
- }
- else if (key.compare("thread") == 0)
- {
- // thread in big endian hex
- if (value.getAsInteger(16, tid))
- tid = LLDB_INVALID_THREAD_ID;
- }
- else if (key.compare("threads") == 0)
- {
- std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
-
- m_thread_ids.clear();
- // A comma separated list of all threads in the current
- // process that includes the thread for this stop reply
- // packet
- lldb::tid_t tid;
- while (!value.empty())
- {
- llvm::StringRef tid_str;
- std::tie(tid_str, value) = value.split(',');
- if (tid_str.getAsInteger(16, tid))
- tid = LLDB_INVALID_THREAD_ID;
- m_thread_ids.push_back(tid);
- }
- }
- else if (key.compare("thread-pcs") == 0)
- {
- m_thread_pcs.clear();
- // A comma separated list of all threads in the current
- // process that includes the thread for this stop reply
- // packet
- lldb::addr_t pc;
- while (!value.empty())
- {
- llvm::StringRef pc_str;
- std::tie(pc_str, value) = value.split(',');
- if (pc_str.getAsInteger(16, pc))
- pc = LLDB_INVALID_ADDRESS;
- m_thread_pcs.push_back(pc);
- }
- }
- else if (key.compare("jstopinfo") == 0)
- {
- StringExtractor json_extractor(value);
- std::string json;
- // Now convert the HEX bytes into a string value
- json_extractor.GetHexByteString(json);
-
- // This JSON contains thread IDs and thread stop info for all threads.
- // It doesn't contain expedited registers, memory or queue info.
- m_jstopinfo_sp = StructuredData::ParseJSON(json);
- }
- else if (key.compare("hexname") == 0)
- {
- StringExtractor name_extractor(value);
- std::string name;
- // Now convert the HEX bytes into a string value
- name_extractor.GetHexByteString(thread_name);
- }
- else if (key.compare("name") == 0)
- {
- thread_name = value;
- }
- else if (key.compare("qaddr") == 0)
- {
- value.getAsInteger(16, thread_dispatch_qaddr);
- }
- else if (key.compare("dispatch_queue_t") == 0)
- {
- queue_vars_valid = true;
- value.getAsInteger(16, dispatch_queue_t);
- }
- else if (key.compare("qname") == 0)
- {
- queue_vars_valid = true;
- StringExtractor name_extractor(value);
- // Now convert the HEX bytes into a string value
- name_extractor.GetHexByteString(queue_name);
- }
- else if (key.compare("qkind") == 0)
- {
- queue_kind = llvm::StringSwitch<QueueKind>(value)
- .Case("serial", eQueueKindSerial)
- .Case("concurrent", eQueueKindConcurrent)
- .Default(eQueueKindUnknown);
- queue_vars_valid = queue_kind != eQueueKindUnknown;
- }
- else if (key.compare("qserialnum") == 0)
- {
- if (!value.getAsInteger(0, queue_serial_number))
- queue_vars_valid = true;
- }
- else if (key.compare("reason") == 0)
- {
- reason = value;
- }
- else if (key.compare("description") == 0)
- {
- StringExtractor desc_extractor(value);
- // Now convert the HEX bytes into a string value
- desc_extractor.GetHexByteString(description);
- }
- else if (key.compare("memory") == 0)
- {
- // Expedited memory. GDB servers can choose to send back expedited memory
- // that can populate the L1 memory cache in the process so that things like
- // the frame pointer backchain can be expedited. This will help stack
- // backtracing be more efficient by not having to send as many memory read
- // requests down the remote GDB server.
-
- // Key/value pair format: memory:<addr>=<bytes>;
- // <addr> is a number whose base will be interpreted by the prefix:
- // "0x[0-9a-fA-F]+" for hex
- // "0[0-7]+" for octal
- // "[1-9]+" for decimal
- // <bytes> is native endian ASCII hex bytes just like the register values
- llvm::StringRef addr_str, bytes_str;
- std::tie(addr_str, bytes_str) = value.split('=');
- if (!addr_str.empty() && !bytes_str.empty())
- {
- lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS;
- if (!addr_str.getAsInteger(0, mem_cache_addr))
- {
- StringExtractor bytes(bytes_str);
- const size_t byte_size = bytes.GetBytesLeft() / 2;
- DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
- const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetData(), 0);
- if (bytes_copied == byte_size)
- m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp);
- }
- }
- }
- else if (key.compare("watch") == 0 || key.compare("rwatch") == 0 || key.compare("awatch") == 0)
- {
- // Support standard GDB remote stop reply packet 'TAAwatch:addr'
- lldb::addr_t wp_addr = LLDB_INVALID_ADDRESS;
- value.getAsInteger(16, wp_addr);
-
- WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);
- uint32_t wp_index = LLDB_INVALID_INDEX32;
-
- if (wp_sp)
- wp_index = wp_sp->GetHardwareIndex();
-
- reason = "watchpoint";
- StreamString ostr;
- ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index);
- description = ostr.GetString().c_str();
- }
- else if (key.compare("library") == 0)
- {
- LoadModules();
- }
- else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1]))
- {
- uint32_t reg = UINT32_MAX;
- if (!key.getAsInteger(16, reg))
- expedited_register_map[reg] = std::move(value);
- }
- }
-
- if (tid == LLDB_INVALID_THREAD_ID)
- {
- // A thread id may be invalid if the response is old style 'S' packet which does not provide the
- // thread information. So update the thread list and choose the first one.
- UpdateThreadIDList ();
-
- if (!m_thread_ids.empty ())
- {
- tid = m_thread_ids.front ();
- }
- }
-
- ThreadSP thread_sp = SetThreadStopInfo (tid,
- expedited_register_map,
- signo,
- thread_name,
- reason,
- description,
- exc_type,
- exc_data,
- thread_dispatch_qaddr,
- queue_vars_valid,
- associated_with_dispatch_queue,
- dispatch_queue_t,
- queue_name,
- queue_kind,
- queue_serial_number);
-
- return eStateStopped;
- }
- break;
-
- case 'W':
- case 'X':
- // process exited
- return eStateExited;
-
- default:
- break;
- }
- return eStateInvalid;
-}
-
-void
-ProcessGDBRemote::RefreshStateAfterStop ()
-{
- std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
-
- m_thread_ids.clear();
- m_thread_pcs.clear();
- // Set the thread stop info. It might have a "threads" key whose value is
- // a list of all thread IDs in the current process, so m_thread_ids might
- // get set.
-
- // Scope for the lock
- {
- // Lock the thread stack while we access it
- std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
- // Get the number of stop packets on the stack
- int nItems = m_stop_packet_stack.size();
- // Iterate over them
- for (int i = 0; i < nItems; i++)
- {
- // Get the thread stop info
- StringExtractorGDBRemote stop_info = m_stop_packet_stack[i];
- // Process thread stop info
- SetThreadStopInfo(stop_info);
- }
- // Clear the thread stop stack
- m_stop_packet_stack.clear();
- }
-
- // Check to see if SetThreadStopInfo() filled in m_thread_ids?
- if (m_thread_ids.empty())
- {
- // No, we need to fetch the thread list manually
- UpdateThreadIDList();
- }
-
- // If we have queried for a default thread id
- if (m_initial_tid != LLDB_INVALID_THREAD_ID)
- {
- m_thread_list.SetSelectedThreadByID(m_initial_tid);
- m_initial_tid = LLDB_INVALID_THREAD_ID;
- }
-
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
- m_thread_list_real.RefreshStateAfterStop();
-
-}
-
-Error
-ProcessGDBRemote::DoHalt (bool &caused_stop)
-{
- Error error;
-
- if (m_public_state.GetValue() == eStateAttaching)
- {
- // 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
- caused_stop = m_gdb_comm.Interrupt();
- return error;
-}
-
-Error
-ProcessGDBRemote::DoDetach(bool keep_stopped)
-{
- Error error;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped);
-
- error = m_gdb_comm.Detach (keep_stopped);
- if (log)
- {
- if (error.Success())
- log->PutCString ("ProcessGDBRemote::DoDetach() detach packet sent successfully");
- else
- log->Printf ("ProcessGDBRemote::DoDetach() detach packet send failed: %s", error.AsCString() ? error.AsCString() : "<unknown error>");
- }
-
- if (!error.Success())
- return error;
-
- // Sleep for one second to let the process get all detached...
- StopAsyncThread ();
-
- SetPrivateState (eStateDetached);
- ResumePrivateStateThread();
-
- //KillDebugserverProcess ();
- return error;
-}
-
-
-Error
-ProcessGDBRemote::DoDestroy ()
-{
- Error error;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy()");
-
- // There is a bug in older iOS debugservers where they don't shut down the process
- // they are debugging properly. If the process is sitting at a breakpoint or an exception,
- // this can cause problems with restarting. So we check to see if any of our threads are stopped
- // at a breakpoint, and if so we remove all the breakpoints, resume the process, and THEN
- // destroy it again.
- //
- // Note, we don't have a good way to test the version of debugserver, but I happen to know that
- // the set of all the iOS debugservers which don't support GetThreadSuffixSupported() and that of
- // the debugservers with this bug are equal. There really should be a better way to test this!
- //
- // We also use m_destroy_tried_resuming to make sure we only do this once, if we resume and then halt and
- // get called here to destroy again and we're still at a breakpoint or exception, then we should
- // just do the straight-forward kill.
- //
- // And of course, if we weren't able to stop the process by the time we get here, it isn't
- // necessary (or helpful) to do any of this.
-
- if (!m_gdb_comm.GetThreadSuffixSupported() && m_public_state.GetValue() != eStateRunning)
- {
- PlatformSP platform_sp = GetTarget().GetPlatform();
-
- // FIXME: These should be ConstStrings so we aren't doing strcmp'ing.
- if (platform_sp
- && platform_sp->GetName()
- && platform_sp->GetName() == PlatformRemoteiOS::GetPluginNameStatic())
- {
- if (m_destroy_tried_resuming)
- {
- if (log)
- log->PutCString ("ProcessGDBRemote::DoDestroy() - Tried resuming to destroy once already, not doing it again.");
- }
- else
- {
- // At present, the plans are discarded and the breakpoints disabled Process::Destroy,
- // but we really need it to happen here and it doesn't matter if we do it twice.
- m_thread_list.DiscardThreadPlans();
- DisableAllBreakpointSites();
-
- bool stop_looks_like_crash = false;
- ThreadList &threads = GetThreadList();
-
- {
- std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
-
- size_t num_threads = threads.GetSize();
- for (size_t i = 0; i < num_threads; i++)
- {
- ThreadSP thread_sp = threads.GetThreadAtIndex(i);
- StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
- StopReason reason = eStopReasonInvalid;
- if (stop_info_sp)
- reason = stop_info_sp->GetStopReason();
- if (reason == eStopReasonBreakpoint
- || reason == eStopReasonException)
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 " stopped with reason: %s.",
- thread_sp->GetProtocolID(),
- stop_info_sp->GetDescription());
- stop_looks_like_crash = true;
- break;
- }
- }
- }
-
- if (stop_looks_like_crash)
- {
- if (log)
- log->PutCString ("ProcessGDBRemote::DoDestroy() - Stopped at a breakpoint, continue and then kill.");
- m_destroy_tried_resuming = true;
-
- // If we are going to run again before killing, it would be good to suspend all the threads
- // before resuming so they won't get into more trouble. Sadly, for the threads stopped with
- // the breakpoint or exception, the exception doesn't get cleared if it is suspended, so we do
- // have to run the risk of letting those threads proceed a bit.
-
- {
- std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
-
- size_t num_threads = threads.GetSize();
- for (size_t i = 0; i < num_threads; i++)
- {
- ThreadSP thread_sp = threads.GetThreadAtIndex(i);
- StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
- StopReason reason = eStopReasonInvalid;
- if (stop_info_sp)
- reason = stop_info_sp->GetStopReason();
- if (reason != eStopReasonBreakpoint
- && reason != eStopReasonException)
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy() - Suspending thread: 0x%4.4" PRIx64 " before running.",
- thread_sp->GetProtocolID());
- thread_sp->SetResumeState(eStateSuspended);
- }
- }
- }
- Resume ();
- return Destroy(false);
- }
- }
- }
- }
-
- // Interrupt if our inferior is running...
- int exit_status = SIGABRT;
- std::string exit_string;
-
- if (m_gdb_comm.IsConnected())
- {
- if (m_public_state.GetValue() != eStateAttaching)
- {
- StringExtractorGDBRemote response;
- bool send_async = true;
- GDBRemoteCommunication::ScopedTimeout (m_gdb_comm, 3);
-
- if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response, send_async) == GDBRemoteCommunication::PacketResult::Success)
- {
- char packet_cmd = response.GetChar(0);
-
- if (packet_cmd == 'W' || packet_cmd == 'X')
- {
-#if defined(__APPLE__)
- // For Native processes on Mac OS X, we launch through the Host Platform, then hand the process off
- // to debugserver, which becomes the parent process through "PT_ATTACH". Then when we go to kill
- // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we call waitpid which returns
- // with no error and the correct status. But amusingly enough that doesn't seem to actually reap
- // the process, but instead it is left around as a Zombie. Probably the kernel is in the process of
- // switching ownership back to lldb which was the original parent, and gets confused in the handoff.
- // Anyway, so call waitpid here to finally reap it.
- PlatformSP platform_sp(GetTarget().GetPlatform());
- if (platform_sp && platform_sp->IsHost())
- {
- int status;
- ::pid_t reap_pid;
- reap_pid = waitpid (GetID(), &status, WNOHANG);
- if (log)
- log->Printf ("Reaped pid: %d, status: %d.\n", reap_pid, status);
- }
-#endif
- SetLastStopPacket (response);
- ClearThreadIDList ();
- exit_status = response.GetHexU8();
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy - got unexpected response to k packet: %s", response.GetStringRef().c_str());
- exit_string.assign("got unexpected response to k packet: ");
- exit_string.append(response.GetStringRef());
- }
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy - failed to send k packet");
- exit_string.assign("failed to send the k packet");
- }
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy - killed or interrupted while attaching");
- exit_string.assign ("killed or interrupted while attaching.");
- }
- }
- else
- {
- // If we missed setting the exit status on the way out, do it here.
- // NB set exit status can be called multiple times, the first one sets the status.
- exit_string.assign("destroying when not connected to debugserver");
+ m_async_broadcaster.BroadcastEvent(
+ eBroadcastBitAsyncContinue,
+ new EventDataBytes(continue_packet.GetData(),
+ continue_packet.GetSize()));
+
+ if (listener_sp->WaitForEvent(std::chrono::seconds(5), event_sp) ==
+ false) {
+ error.SetErrorString("Resume timed out.");
+ if (log)
+ log->Printf("ProcessGDBRemote::DoResume: Resume timed out.");
+ } else if (event_sp->BroadcasterIs(&m_async_broadcaster)) {
+ error.SetErrorString("Broadcast continue, but the async thread was "
+ "killed before we got an ack back.");
+ if (log)
+ log->Printf("ProcessGDBRemote::DoResume: Broadcast continue, but the "
+ "async thread was killed before we got an ack back.");
+ return error;
+ }
}
+ }
- SetExitStatus(exit_status, exit_string.c_str());
-
- StopAsyncThread ();
- KillDebugserverProcess ();
- return error;
+ return error;
}
-void
-ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
-{
- const bool did_exec = response.GetStringRef().find(";reason:exec;") != std::string::npos;
- if (did_exec)
- {
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::SetLastStopPacket () - detected exec");
-
- m_thread_list_real.Clear();
- m_thread_list.Clear();
- BuildDynamicRegisterInfo (true);
- m_gdb_comm.ResetDiscoverableSettings (did_exec);
- }
+void ProcessGDBRemote::HandleStopReplySequence() {
+ while (true) {
+ // Send vStopped
+ StringExtractorGDBRemote response;
+ m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false);
- // Scope the lock
- {
- // Lock the thread stack while we access it
- std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
+ // OK represents end of signal list
+ if (response.IsOKResponse())
+ break;
- // We are are not using non-stop mode, there can only be one last stop
- // reply packet, so clear the list.
- if (GetTarget().GetNonStopModeEnabled() == false)
- m_stop_packet_stack.clear();
+ // If not OK or a normal packet we have a problem
+ if (!response.IsNormalResponse())
+ break;
- // Add this stop packet to the stop packet stack
- // This stack will get popped and examined when we switch to the
- // Stopped state
- m_stop_packet_stack.push_back(response);
- }
+ SetLastStopPacket(response);
+ }
}
-void
-ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp)
-{
- Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp));
+void ProcessGDBRemote::ClearThreadIDList() {
+ std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
+ m_thread_ids.clear();
+ m_thread_pcs.clear();
}
-//------------------------------------------------------------------
-// Process Queries
-//------------------------------------------------------------------
-
-bool
-ProcessGDBRemote::IsAlive ()
-{
- return m_gdb_comm.IsConnected() && Process::IsAlive();
+size_t
+ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(std::string &value) {
+ m_thread_ids.clear();
+ m_thread_pcs.clear();
+ size_t comma_pos;
+ lldb::tid_t tid;
+ while ((comma_pos = value.find(',')) != std::string::npos) {
+ value[comma_pos] = '\0';
+ // thread in big endian hex
+ tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16);
+ if (tid != LLDB_INVALID_THREAD_ID)
+ m_thread_ids.push_back(tid);
+ value.erase(0, comma_pos + 1);
+ }
+ tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16);
+ if (tid != LLDB_INVALID_THREAD_ID)
+ m_thread_ids.push_back(tid);
+ return m_thread_ids.size();
}
-addr_t
-ProcessGDBRemote::GetImageInfoAddress()
-{
- // request the link map address via the $qShlibInfoAddr packet
- lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr();
+size_t
+ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue(std::string &value) {
+ m_thread_pcs.clear();
+ size_t comma_pos;
+ lldb::addr_t pc;
+ while ((comma_pos = value.find(',')) != std::string::npos) {
+ value[comma_pos] = '\0';
+ pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_ADDRESS)
+ m_thread_pcs.push_back(pc);
+ value.erase(0, comma_pos + 1);
+ }
+ pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_THREAD_ID)
+ m_thread_pcs.push_back(pc);
+ return m_thread_pcs.size();
+}
+
+bool ProcessGDBRemote::UpdateThreadIDList() {
+ std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
+
+ if (m_jthreadsinfo_sp) {
+ // If we have the JSON threads info, we can get the thread list from that
+ StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
+ if (thread_infos && thread_infos->GetSize() > 0) {
+ m_thread_ids.clear();
+ m_thread_pcs.clear();
+ thread_infos->ForEach([this](StructuredData::Object *object) -> bool {
+ StructuredData::Dictionary *thread_dict = object->GetAsDictionary();
+ if (thread_dict) {
+ // Set the thread stop info from the JSON dictionary
+ SetThreadStopInfo(thread_dict);
+ lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+ if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid))
+ m_thread_ids.push_back(tid);
+ }
+ return true; // Keep iterating through all thread_info objects
+ });
+ }
+ if (!m_thread_ids.empty())
+ return true;
+ } else {
+ // See if we can get the thread IDs from the current stop reply packets
+ // that might contain a "threads" key/value pair
+
+ // Lock the thread stack while we access it
+ // Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
+ std::unique_lock<std::recursive_mutex> stop_stack_lock(
+ m_last_stop_packet_mutex, std::defer_lock);
+ if (stop_stack_lock.try_lock()) {
+ // Get the number of stop packets on the stack
+ int nItems = m_stop_packet_stack.size();
+ // Iterate over them
+ for (int i = 0; i < nItems; i++) {
+ // Get the thread stop info
+ StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i];
+ const std::string &stop_info_str = stop_info.GetStringRef();
+
+ m_thread_pcs.clear();
+ const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:");
+ if (thread_pcs_pos != std::string::npos) {
+ const size_t start = thread_pcs_pos + strlen(";thread-pcs:");
+ const size_t end = stop_info_str.find(';', start);
+ if (end != std::string::npos) {
+ std::string value = stop_info_str.substr(start, end - start);
+ UpdateThreadPCsFromStopReplyThreadsValue(value);
+ }
+ }
+
+ const size_t threads_pos = stop_info_str.find(";threads:");
+ if (threads_pos != std::string::npos) {
+ const size_t start = threads_pos + strlen(";threads:");
+ const size_t end = stop_info_str.find(';', start);
+ if (end != std::string::npos) {
+ std::string value = stop_info_str.substr(start, end - start);
+ if (UpdateThreadIDsFromStopReplyThreadsValue(value))
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ bool sequence_mutex_unavailable = false;
+ m_gdb_comm.GetCurrentThreadIDs(m_thread_ids, sequence_mutex_unavailable);
+ if (sequence_mutex_unavailable) {
+ return false; // We just didn't get the list
+ }
+ return true;
+}
+
+bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) {
+ // locker will keep a mutex locked until it goes out of scope
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_THREAD));
+ if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
+ log->Printf("ProcessGDBRemote::%s (pid = %" PRIu64 ")", __FUNCTION__,
+ GetID());
+
+ size_t num_thread_ids = m_thread_ids.size();
+ // The "m_thread_ids" thread ID list should always be updated after each stop
+ // reply packet, but in case it isn't, update it here.
+ if (num_thread_ids == 0) {
+ if (!UpdateThreadIDList())
+ return false;
+ num_thread_ids = m_thread_ids.size();
+ }
+
+ ThreadList old_thread_list_copy(old_thread_list);
+ if (num_thread_ids > 0) {
+ for (size_t i = 0; i < num_thread_ids; ++i) {
+ tid_t tid = m_thread_ids[i];
+ ThreadSP thread_sp(
+ old_thread_list_copy.RemoveThreadByProtocolID(tid, false));
+ if (!thread_sp) {
+ thread_sp.reset(new ThreadGDBRemote(*this, tid));
+ if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
+ log->Printf("ProcessGDBRemote::%s Making new thread: %p for thread "
+ "ID: 0x%" PRIx64 ".\n",
+ __FUNCTION__, static_cast<void *>(thread_sp.get()),
+ thread_sp->GetID());
+ } else {
+ if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
+ log->Printf("ProcessGDBRemote::%s Found old thread: %p for thread "
+ "ID: 0x%" PRIx64 ".\n",
+ __FUNCTION__, static_cast<void *>(thread_sp.get()),
+ thread_sp->GetID());
+ }
+ // The m_thread_pcs vector has pc values in big-endian order, not
+ // target-endian, unlike most
+ // of the register read/write packets in gdb-remote protocol.
+ // Early in the process startup, we may not yet have set the process
+ // ByteOrder so we ignore these;
+ // they are a performance improvement over fetching thread register values
+ // individually, the
+ // method we will fall back to if needed.
+ if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() &&
+ GetByteOrder() != eByteOrderInvalid) {
+ ThreadGDBRemote *gdb_thread =
+ static_cast<ThreadGDBRemote *>(thread_sp.get());
+ RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
+ if (reg_ctx_sp) {
+ uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ if (pc_regnum != LLDB_INVALID_REGNUM) {
+ gdb_thread->PrivateSetRegisterValue(pc_regnum, m_thread_pcs[i]);
+ }
+ }
+ }
+ new_thread_list.AddThreadSortedByIndexID(thread_sp);
+ }
+ }
+
+ // Whatever that is left in old_thread_list_copy are not
+ // present in new_thread_list. Remove non-existent threads from internal id
+ // table.
+ size_t old_num_thread_ids = old_thread_list_copy.GetSize(false);
+ for (size_t i = 0; i < old_num_thread_ids; i++) {
+ ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
+ if (old_thread_sp) {
+ lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID();
+ m_thread_id_to_index_id_map.erase(old_thread_id);
+ }
+ }
+
+ return true;
+}
+
+bool ProcessGDBRemote::GetThreadStopInfoFromJSON(
+ ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp) {
+ // See if we got thread stop infos for all threads via the "jThreadsInfo"
+ // packet
+ if (thread_infos_sp) {
+ StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray();
+ if (thread_infos) {
+ lldb::tid_t tid;
+ const size_t n = thread_infos->GetSize();
+ for (size_t i = 0; i < n; ++i) {
+ StructuredData::Dictionary *thread_dict =
+ thread_infos->GetItemAtIndex(i)->GetAsDictionary();
+ if (thread_dict) {
+ if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>(
+ "tid", tid, LLDB_INVALID_THREAD_ID)) {
+ if (tid == thread->GetID())
+ return (bool)SetThreadStopInfo(thread_dict);
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) {
+ // See if we got thread stop infos for all threads via the "jThreadsInfo"
+ // packet
+ if (GetThreadStopInfoFromJSON(thread, m_jthreadsinfo_sp))
+ return true;
- // the loaded module list can also provides a link map address
- if (addr == LLDB_INVALID_ADDRESS)
- {
- LoadedModuleInfoList list;
- if (GetLoadedModuleList (list).Success())
- addr = list.m_link_map;
- }
-
- return addr;
-}
-
-void
-ProcessGDBRemote::WillPublicStop ()
-{
- // See if the GDB remote client supports the JSON threads info.
- // If so, we gather stop info for all threads, expedited registers,
- // expedited memory, runtime queue information (iOS and MacOSX only),
- // and more. Expediting memory will help stack backtracing be much
- // faster. Expediting registers will make sure we don't have to read
- // the thread registers for GPRs.
- m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo();
+ // See if we got thread stop info for any threads valid stop info reasons
+ // threads
+ // via the "jstopinfo" packet stop reply packet key/value pair?
+ if (m_jstopinfo_sp) {
+ // If we have "jstopinfo" then we have stop descriptions for all threads
+ // that have stop reasons, and if there is no entry for a thread, then
+ // it has no stop reason.
+ thread->GetRegisterContext()->InvalidateIfNeeded(true);
+ if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp)) {
+ thread->SetStopInfo(StopInfoSP());
+ }
+ return true;
+ }
- if (m_jthreadsinfo_sp)
- {
- // Now set the stop info for each thread and also expedite any registers
- // and memory that was in the jThreadsInfo response.
- StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
- if (thread_infos)
- {
- const size_t n = thread_infos->GetSize();
- for (size_t i=0; i<n; ++i)
- {
- StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary();
- if (thread_dict)
- SetThreadStopInfo(thread_dict);
+ // Fall back to using the qThreadStopInfo packet
+ StringExtractorGDBRemote stop_packet;
+ if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet))
+ return SetThreadStopInfo(stop_packet) == eStateStopped;
+ return false;
+}
+
+ThreadSP ProcessGDBRemote::SetThreadStopInfo(
+ lldb::tid_t tid, ExpeditedRegisterMap &expedited_register_map,
+ uint8_t signo, const std::string &thread_name, const std::string &reason,
+ const std::string &description, uint32_t exc_type,
+ const std::vector<addr_t> &exc_data, addr_t thread_dispatch_qaddr,
+ bool queue_vars_valid, // Set to true if queue_name, queue_kind and
+ // queue_serial are valid
+ LazyBool associated_with_dispatch_queue, addr_t dispatch_queue_t,
+ std::string &queue_name, QueueKind queue_kind, uint64_t queue_serial) {
+ ThreadSP thread_sp;
+ if (tid != LLDB_INVALID_THREAD_ID) {
+ // Scope for "locker" below
+ {
+ // m_thread_list_real does have its own mutex, but we need to
+ // hold onto the mutex between the call to
+ // m_thread_list_real.FindThreadByID(...)
+ // and the m_thread_list_real.AddThread(...) so it doesn't change on us
+ std::lock_guard<std::recursive_mutex> guard(
+ m_thread_list_real.GetMutex());
+ thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false);
+
+ if (!thread_sp) {
+ // Create the thread if we need to
+ thread_sp.reset(new ThreadGDBRemote(*this, tid));
+ m_thread_list_real.AddThread(thread_sp);
+ }
+ }
+
+ if (thread_sp) {
+ ThreadGDBRemote *gdb_thread =
+ static_cast<ThreadGDBRemote *>(thread_sp.get());
+ gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true);
+
+ for (const auto &pair : expedited_register_map) {
+ StringExtractor reg_value_extractor;
+ reg_value_extractor.GetStringRef() = pair.second;
+ DataBufferSP buffer_sp(new DataBufferHeap(
+ reg_value_extractor.GetStringRef().size() / 2, 0));
+ reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc');
+ gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData());
+ }
+
+ thread_sp->SetName(thread_name.empty() ? NULL : thread_name.c_str());
+
+ gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr);
+ // Check if the GDB server was able to provide the queue name, kind and
+ // serial number
+ if (queue_vars_valid)
+ gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind,
+ queue_serial, dispatch_queue_t,
+ associated_with_dispatch_queue);
+ else
+ gdb_thread->ClearQueueInfo();
+
+ gdb_thread->SetAssociatedWithLibdispatchQueue(
+ associated_with_dispatch_queue);
+
+ if (dispatch_queue_t != LLDB_INVALID_ADDRESS)
+ gdb_thread->SetQueueLibdispatchQueueAddress(dispatch_queue_t);
+
+ // Make sure we update our thread stop reason just once
+ if (!thread_sp->StopInfoIsUpToDate()) {
+ thread_sp->SetStopInfo(StopInfoSP());
+ // If there's a memory thread backed by this thread, we need to use it
+ // to calcualte StopInfo.
+ ThreadSP memory_thread_sp =
+ m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID());
+ if (memory_thread_sp)
+ thread_sp = memory_thread_sp;
+
+ if (exc_type != 0) {
+ const size_t exc_data_size = exc_data.size();
+
+ thread_sp->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;
+ bool did_exec = false;
+ if (!reason.empty()) {
+ if (reason.compare("trace") == 0) {
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()
+ ->GetBreakpointSiteList()
+ .FindByAddress(pc);
+
+ // If the current pc is a breakpoint site then the StopInfo should
+ // be set to Breakpoint
+ // Otherwise, it will be set to Trace.
+ if (bp_site_sp &&
+ bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *thread_sp, bp_site_sp->GetID()));
+ } else
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonToTrace(*thread_sp));
+ handled = true;
+ } else if (reason.compare("breakpoint") == 0) {
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ lldb::BreakpointSiteSP bp_site_sp = thread_sp->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.
+ handled = true;
+ if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *thread_sp, bp_site_sp->GetID()));
+ } else {
+ StopInfoSP invalid_stop_info_sp;
+ thread_sp->SetStopInfo(invalid_stop_info_sp);
+ }
+ }
+ } else if (reason.compare("trap") == 0) {
+ // Let the trap just use the standard signal stop reason below...
+ } else if (reason.compare("watchpoint") == 0) {
+ StringExtractor desc_extractor(description.c_str());
+ addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
+ uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
+ addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
+ watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
+ if (wp_addr != LLDB_INVALID_ADDRESS) {
+ WatchpointSP wp_sp;
+ ArchSpec::Core core = GetTarget().GetArchitecture().GetCore();
+ if ((core >= ArchSpec::kCore_mips_first &&
+ core <= ArchSpec::kCore_mips_last) ||
+ (core >= ArchSpec::eCore_arm_generic &&
+ core <= ArchSpec::eCore_arm_aarch64))
+ wp_sp = GetTarget().GetWatchpointList().FindByAddress(
+ wp_hit_addr);
+ if (!wp_sp)
+ wp_sp =
+ GetTarget().GetWatchpointList().FindByAddress(wp_addr);
+ if (wp_sp) {
+ wp_sp->SetHardwareIndex(wp_index);
+ watch_id = wp_sp->GetID();
+ }
+ }
+ if (watch_id == LLDB_INVALID_WATCH_ID) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(
+ GDBR_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf("failed to find watchpoint");
+ }
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID(
+ *thread_sp, watch_id, wp_hit_addr));
+ handled = true;
+ } else if (reason.compare("exception") == 0) {
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException(
+ *thread_sp, description.c_str()));
+ handled = true;
+ } else if (reason.compare("exec") == 0) {
+ did_exec = true;
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonWithExec(*thread_sp));
+ handled = true;
+ }
+ } else if (!signo) {
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ lldb::BreakpointSiteSP bp_site_sp =
+ thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(
+ pc);
+
+ // If the current pc is a breakpoint site then the StopInfo should
+ // be set to Breakpoint
+ // even though the remote stub did not set it as such. This can
+ // happen when
+ // the thread is involuntarily interrupted (e.g. due to stops on
+ // other
+ // threads) just as it is about to execute the breakpoint
+ // instruction.
+ if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *thread_sp, bp_site_sp->GetID()));
+ handled = true;
+ }
+ }
+
+ if (!handled && signo && did_exec == false) {
+ if (signo == SIGTRAP) {
+ // Currently we are going to assume SIGTRAP means we are either
+ // hitting a breakpoint or hardware single stepping.
+ handled = true;
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC() +
+ m_breakpoint_pc_offset;
+ lldb::BreakpointSiteSP bp_site_sp = thread_sp->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(thread_sp.get())) {
+ if (m_breakpoint_pc_offset != 0)
+ thread_sp->GetRegisterContext()->SetPC(pc);
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *thread_sp, bp_site_sp->GetID()));
+ } else {
+ StopInfoSP invalid_stop_info_sp;
+ thread_sp->SetStopInfo(invalid_stop_info_sp);
+ }
+ } else {
+ // If we were stepping then assume the stop was the result of
+ // the trace. If we were
+ // not stepping then report the SIGTRAP.
+ // FIXME: We are still missing the case where we single step
+ // over a trap instruction.
+ if (thread_sp->GetTemporaryResumeState() == eStateStepping)
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonToTrace(*thread_sp));
+ else
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal(
+ *thread_sp, signo, description.c_str()));
+ }
+ }
+ if (!handled)
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal(
+ *thread_sp, signo, description.c_str()));
+ }
+
+ if (!description.empty()) {
+ lldb::StopInfoSP stop_info_sp(thread_sp->GetStopInfo());
+ if (stop_info_sp) {
+ const char *stop_info_desc = stop_info_sp->GetDescription();
+ if (!stop_info_desc || !stop_info_desc[0])
+ stop_info_sp->SetDescription(description.c_str());
+ } else {
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException(
+ *thread_sp, description.c_str()));
}
+ }
}
+ }
}
+ }
+ return thread_sp;
}
-//------------------------------------------------------------------
-// Process Memory
-//------------------------------------------------------------------
-size_t
-ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
-{
- GetMaxMemorySize ();
- 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];
- int packet_len;
- bool binary_memory_read = m_gdb_comm.GetxPacketSupported();
- packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64,
- binary_memory_read ? 'x' : 'm', (uint64_t)addr, (uint64_t)size);
- assert (packet_len + 1 < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true) == GDBRemoteCommunication::PacketResult::Success)
- {
- if (response.IsNormalResponse())
- {
- error.Clear();
- if (binary_memory_read)
- {
- // The lower level GDBRemoteCommunication packet receive layer has already de-quoted any
- // 0x7d character escaping that was present in the packet
-
- size_t data_received_size = response.GetBytesLeft();
- if (data_received_size > size)
- {
- // Don't write past the end of BUF if the remote debug server gave us too
- // much data for some reason.
- data_received_size = size;
+lldb::ThreadSP
+ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) {
+ static ConstString g_key_tid("tid");
+ static ConstString g_key_name("name");
+ static ConstString g_key_reason("reason");
+ static ConstString g_key_metype("metype");
+ static ConstString g_key_medata("medata");
+ static ConstString g_key_qaddr("qaddr");
+ static ConstString g_key_dispatch_queue_t("dispatch_queue_t");
+ static ConstString g_key_associated_with_dispatch_queue(
+ "associated_with_dispatch_queue");
+ static ConstString g_key_queue_name("qname");
+ static ConstString g_key_queue_kind("qkind");
+ static ConstString g_key_queue_serial_number("qserialnum");
+ static ConstString g_key_registers("registers");
+ static ConstString g_key_memory("memory");
+ static ConstString g_key_address("address");
+ static ConstString g_key_bytes("bytes");
+ static ConstString g_key_description("description");
+ static ConstString g_key_signal("signal");
+
+ // Stop with signal and thread info
+ lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+ uint8_t signo = 0;
+ std::string value;
+ std::string thread_name;
+ std::string reason;
+ std::string description;
+ uint32_t exc_type = 0;
+ std::vector<addr_t> exc_data;
+ addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
+ ExpeditedRegisterMap expedited_register_map;
+ bool queue_vars_valid = false;
+ addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
+ LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
+ std::string queue_name;
+ QueueKind queue_kind = eQueueKindUnknown;
+ uint64_t queue_serial_number = 0;
+ // Iterate through all of the thread dictionary key/value pairs from the
+ // structured data dictionary
+
+ thread_dict->ForEach([this, &tid, &expedited_register_map, &thread_name,
+ &signo, &reason, &description, &exc_type, &exc_data,
+ &thread_dispatch_qaddr, &queue_vars_valid,
+ &associated_with_dispatch_queue, &dispatch_queue_t,
+ &queue_name, &queue_kind, &queue_serial_number](
+ ConstString key,
+ StructuredData::Object *object) -> bool {
+ if (key == g_key_tid) {
+ // thread in big endian hex
+ tid = object->GetIntegerValue(LLDB_INVALID_THREAD_ID);
+ } else if (key == g_key_metype) {
+ // exception type in big endian hex
+ exc_type = object->GetIntegerValue(0);
+ } else if (key == g_key_medata) {
+ // exception data in big endian hex
+ StructuredData::Array *array = object->GetAsArray();
+ if (array) {
+ array->ForEach([&exc_data](StructuredData::Object *object) -> bool {
+ exc_data.push_back(object->GetIntegerValue());
+ return true; // Keep iterating through all array items
+ });
+ }
+ } else if (key == g_key_name) {
+ thread_name = object->GetStringValue();
+ } else if (key == g_key_qaddr) {
+ thread_dispatch_qaddr = object->GetIntegerValue(LLDB_INVALID_ADDRESS);
+ } else if (key == g_key_queue_name) {
+ queue_vars_valid = true;
+ queue_name = object->GetStringValue();
+ } else if (key == g_key_queue_kind) {
+ std::string queue_kind_str = object->GetStringValue();
+ if (queue_kind_str == "serial") {
+ queue_vars_valid = true;
+ queue_kind = eQueueKindSerial;
+ } else if (queue_kind_str == "concurrent") {
+ queue_vars_valid = true;
+ queue_kind = eQueueKindConcurrent;
+ }
+ } else if (key == g_key_queue_serial_number) {
+ queue_serial_number = object->GetIntegerValue(0);
+ if (queue_serial_number != 0)
+ queue_vars_valid = true;
+ } else if (key == g_key_dispatch_queue_t) {
+ dispatch_queue_t = object->GetIntegerValue(0);
+ if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS)
+ queue_vars_valid = true;
+ } else if (key == g_key_associated_with_dispatch_queue) {
+ queue_vars_valid = true;
+ bool associated = object->GetBooleanValue();
+ if (associated)
+ associated_with_dispatch_queue = eLazyBoolYes;
+ else
+ associated_with_dispatch_queue = eLazyBoolNo;
+ } else if (key == g_key_reason) {
+ reason = object->GetStringValue();
+ } else if (key == g_key_description) {
+ description = object->GetStringValue();
+ } else if (key == g_key_registers) {
+ StructuredData::Dictionary *registers_dict = object->GetAsDictionary();
+
+ if (registers_dict) {
+ registers_dict->ForEach(
+ [&expedited_register_map](ConstString key,
+ StructuredData::Object *object) -> bool {
+ const uint32_t reg =
+ StringConvert::ToUInt32(key.GetCString(), UINT32_MAX, 10);
+ if (reg != UINT32_MAX)
+ expedited_register_map[reg] = object->GetStringValue();
+ return true; // Keep iterating through all array items
+ });
+ }
+ } else if (key == g_key_memory) {
+ StructuredData::Array *array = object->GetAsArray();
+ if (array) {
+ array->ForEach([this](StructuredData::Object *object) -> bool {
+ StructuredData::Dictionary *mem_cache_dict =
+ object->GetAsDictionary();
+ if (mem_cache_dict) {
+ lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS;
+ if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>(
+ "address", mem_cache_addr)) {
+ if (mem_cache_addr != LLDB_INVALID_ADDRESS) {
+ StringExtractor bytes;
+ if (mem_cache_dict->GetValueForKeyAsString(
+ "bytes", bytes.GetStringRef())) {
+ bytes.SetFilePos(0);
+
+ const size_t byte_size = bytes.GetStringRef().size() / 2;
+ DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
+ const size_t bytes_copied =
+ bytes.GetHexBytes(data_buffer_sp->GetData(), 0);
+ if (bytes_copied == byte_size)
+ m_memory_cache.AddL1CacheData(mem_cache_addr,
+ data_buffer_sp);
}
- memcpy (buf, response.GetStringRef().data(), data_received_size);
- return data_received_size;
- }
- else
- {
- return response.GetHexBytes(llvm::MutableArrayRef<uint8_t>((uint8_t*)buf, size), '\xdd');
+ }
}
- }
- else if (response.IsErrorResponse())
- error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr);
- else if (response.IsUnsupportedResponse())
- error.SetErrorStringWithFormat("GDB server does not support reading memory");
- else
- error.SetErrorStringWithFormat("unexpected response to GDB server memory read packet '%s': '%s'", packet, response.GetStringRef().c_str());
- }
- else
- {
- error.SetErrorStringWithFormat("failed to send packet: '%s'", packet);
+ }
+ return true; // Keep iterating through all array items
+ });
+ }
+
+ } else if (key == g_key_signal)
+ signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER);
+ return true; // Keep iterating through all dictionary key/value pairs
+ });
+
+ return SetThreadStopInfo(tid, expedited_register_map, signo, thread_name,
+ reason, description, exc_type, exc_data,
+ thread_dispatch_qaddr, queue_vars_valid,
+ associated_with_dispatch_queue, dispatch_queue_t,
+ queue_name, queue_kind, queue_serial_number);
+}
+
+StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
+ stop_packet.SetFilePos(0);
+ const char stop_type = stop_packet.GetChar();
+ switch (stop_type) {
+ case 'T':
+ case 'S': {
+ // This is a bit of a hack, but is is required. If we did exec, we
+ // need to clear our thread lists and also know to rebuild our dynamic
+ // register info before we lookup and threads and populate the expedited
+ // register values so we need to know this right away so we can cleanup
+ // and update our registers.
+ const uint32_t stop_id = GetStopID();
+ if (stop_id == 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);
}
- return 0;
+ // Stop with signal and thread info
+ lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+ const uint8_t signo = stop_packet.GetHexU8();
+ llvm::StringRef key;
+ llvm::StringRef value;
+ std::string thread_name;
+ std::string reason;
+ std::string description;
+ uint32_t exc_type = 0;
+ std::vector<addr_t> exc_data;
+ addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
+ bool queue_vars_valid =
+ false; // says if locals below that start with "queue_" are valid
+ addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
+ LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
+ std::string queue_name;
+ QueueKind queue_kind = eQueueKindUnknown;
+ uint64_t queue_serial_number = 0;
+ ExpeditedRegisterMap expedited_register_map;
+ while (stop_packet.GetNameColonValue(key, value)) {
+ if (key.compare("metype") == 0) {
+ // exception type in big endian hex
+ value.getAsInteger(16, exc_type);
+ } else if (key.compare("medata") == 0) {
+ // exception data in big endian hex
+ uint64_t x;
+ value.getAsInteger(16, x);
+ exc_data.push_back(x);
+ } else if (key.compare("thread") == 0) {
+ // thread in big endian hex
+ if (value.getAsInteger(16, tid))
+ tid = LLDB_INVALID_THREAD_ID;
+ } else if (key.compare("threads") == 0) {
+ std::lock_guard<std::recursive_mutex> guard(
+ m_thread_list_real.GetMutex());
+
+ m_thread_ids.clear();
+ // A comma separated list of all threads in the current
+ // process that includes the thread for this stop reply
+ // packet
+ lldb::tid_t tid;
+ while (!value.empty()) {
+ llvm::StringRef tid_str;
+ std::tie(tid_str, value) = value.split(',');
+ if (tid_str.getAsInteger(16, tid))
+ tid = LLDB_INVALID_THREAD_ID;
+ m_thread_ids.push_back(tid);
+ }
+ } else if (key.compare("thread-pcs") == 0) {
+ m_thread_pcs.clear();
+ // A comma separated list of all threads in the current
+ // process that includes the thread for this stop reply
+ // packet
+ lldb::addr_t pc;
+ while (!value.empty()) {
+ llvm::StringRef pc_str;
+ std::tie(pc_str, value) = value.split(',');
+ if (pc_str.getAsInteger(16, pc))
+ pc = LLDB_INVALID_ADDRESS;
+ m_thread_pcs.push_back(pc);
+ }
+ } else if (key.compare("jstopinfo") == 0) {
+ StringExtractor json_extractor(value);
+ std::string json;
+ // Now convert the HEX bytes into a string value
+ json_extractor.GetHexByteString(json);
+
+ // This JSON contains thread IDs and thread stop info for all threads.
+ // It doesn't contain expedited registers, memory or queue info.
+ m_jstopinfo_sp = StructuredData::ParseJSON(json);
+ } else if (key.compare("hexname") == 0) {
+ StringExtractor name_extractor(value);
+ std::string name;
+ // Now convert the HEX bytes into a string value
+ name_extractor.GetHexByteString(thread_name);
+ } else if (key.compare("name") == 0) {
+ thread_name = value;
+ } else if (key.compare("qaddr") == 0) {
+ value.getAsInteger(16, thread_dispatch_qaddr);
+ } else if (key.compare("dispatch_queue_t") == 0) {
+ queue_vars_valid = true;
+ value.getAsInteger(16, dispatch_queue_t);
+ } else if (key.compare("qname") == 0) {
+ queue_vars_valid = true;
+ StringExtractor name_extractor(value);
+ // Now convert the HEX bytes into a string value
+ name_extractor.GetHexByteString(queue_name);
+ } else if (key.compare("qkind") == 0) {
+ queue_kind = llvm::StringSwitch<QueueKind>(value)
+ .Case("serial", eQueueKindSerial)
+ .Case("concurrent", eQueueKindConcurrent)
+ .Default(eQueueKindUnknown);
+ queue_vars_valid = queue_kind != eQueueKindUnknown;
+ } else if (key.compare("qserialnum") == 0) {
+ if (!value.getAsInteger(0, queue_serial_number))
+ queue_vars_valid = true;
+ } else if (key.compare("reason") == 0) {
+ reason = value;
+ } else if (key.compare("description") == 0) {
+ StringExtractor desc_extractor(value);
+ // Now convert the HEX bytes into a string value
+ desc_extractor.GetHexByteString(description);
+ } else if (key.compare("memory") == 0) {
+ // Expedited memory. GDB servers can choose to send back expedited
+ // memory
+ // that can populate the L1 memory cache in the process so that things
+ // like
+ // the frame pointer backchain can be expedited. This will help stack
+ // backtracing be more efficient by not having to send as many memory
+ // read
+ // requests down the remote GDB server.
+
+ // Key/value pair format: memory:<addr>=<bytes>;
+ // <addr> is a number whose base will be interpreted by the prefix:
+ // "0x[0-9a-fA-F]+" for hex
+ // "0[0-7]+" for octal
+ // "[1-9]+" for decimal
+ // <bytes> is native endian ASCII hex bytes just like the register
+ // values
+ llvm::StringRef addr_str, bytes_str;
+ std::tie(addr_str, bytes_str) = value.split('=');
+ if (!addr_str.empty() && !bytes_str.empty()) {
+ lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS;
+ if (!addr_str.getAsInteger(0, mem_cache_addr)) {
+ StringExtractor bytes(bytes_str);
+ const size_t byte_size = bytes.GetBytesLeft() / 2;
+ DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
+ const size_t bytes_copied =
+ bytes.GetHexBytes(data_buffer_sp->GetData(), 0);
+ if (bytes_copied == byte_size)
+ m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp);
+ }
+ }
+ } else if (key.compare("watch") == 0 || key.compare("rwatch") == 0 ||
+ key.compare("awatch") == 0) {
+ // Support standard GDB remote stop reply packet 'TAAwatch:addr'
+ lldb::addr_t wp_addr = LLDB_INVALID_ADDRESS;
+ value.getAsInteger(16, wp_addr);
+
+ WatchpointSP wp_sp =
+ GetTarget().GetWatchpointList().FindByAddress(wp_addr);
+ uint32_t wp_index = LLDB_INVALID_INDEX32;
+
+ if (wp_sp)
+ wp_index = wp_sp->GetHardwareIndex();
+
+ reason = "watchpoint";
+ StreamString ostr;
+ ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index);
+ description = ostr.GetString().c_str();
+ } else if (key.compare("library") == 0) {
+ LoadModules();
+ } else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) {
+ uint32_t reg = UINT32_MAX;
+ if (!key.getAsInteger(16, reg))
+ expedited_register_map[reg] = std::move(value);
+ }
+ }
+
+ if (tid == LLDB_INVALID_THREAD_ID) {
+ // A thread id may be invalid if the response is old style 'S' packet
+ // which does not provide the
+ // thread information. So update the thread list and choose the first one.
+ UpdateThreadIDList();
+
+ if (!m_thread_ids.empty()) {
+ tid = m_thread_ids.front();
+ }
+ }
+
+ ThreadSP thread_sp = SetThreadStopInfo(
+ tid, expedited_register_map, signo, thread_name, reason, description,
+ exc_type, exc_data, thread_dispatch_qaddr, queue_vars_valid,
+ associated_with_dispatch_queue, dispatch_queue_t, queue_name,
+ queue_kind, queue_serial_number);
+
+ return eStateStopped;
+ } break;
+
+ case 'W':
+ case 'X':
+ // process exited
+ return eStateExited;
+
+ default:
+ break;
+ }
+ return eStateInvalid;
+}
+
+void ProcessGDBRemote::RefreshStateAfterStop() {
+ std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
+
+ m_thread_ids.clear();
+ m_thread_pcs.clear();
+ // Set the thread stop info. It might have a "threads" key whose value is
+ // a list of all thread IDs in the current process, so m_thread_ids might
+ // get set.
+
+ // Scope for the lock
+ {
+ // Lock the thread stack while we access it
+ std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
+ // Get the number of stop packets on the stack
+ int nItems = m_stop_packet_stack.size();
+ // Iterate over them
+ for (int i = 0; i < nItems; i++) {
+ // Get the thread stop info
+ StringExtractorGDBRemote stop_info = m_stop_packet_stack[i];
+ // Process thread stop info
+ SetThreadStopInfo(stop_info);
+ }
+ // Clear the thread stop stack
+ m_stop_packet_stack.clear();
+ }
+
+ // Check to see if SetThreadStopInfo() filled in m_thread_ids?
+ if (m_thread_ids.empty()) {
+ // No, we need to fetch the thread list manually
+ UpdateThreadIDList();
+ }
+
+ // If we have queried for a default thread id
+ if (m_initial_tid != LLDB_INVALID_THREAD_ID) {
+ m_thread_list.SetSelectedThreadByID(m_initial_tid);
+ m_initial_tid = LLDB_INVALID_THREAD_ID;
+ }
+
+ // Let all threads recover from stopping and do any clean up based
+ // on the previous thread state (if any).
+ m_thread_list_real.RefreshStateAfterStop();
+}
+
+Error ProcessGDBRemote::DoHalt(bool &caused_stop) {
+ Error error;
+
+ if (m_public_state.GetValue() == eStateAttaching) {
+ // 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
+ caused_stop = m_gdb_comm.Interrupt();
+ return error;
}
-size_t
-ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
-{
- GetMaxMemorySize ();
- 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;
- }
+Error ProcessGDBRemote::DoDetach(bool keep_stopped) {
+ Error error;
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped);
- StreamString packet;
- packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
- packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), endian::InlHostByteOrder());
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true) == GDBRemoteCommunication::PacketResult::Success)
- {
- if (response.IsOKResponse())
- {
- error.Clear();
- return size;
- }
- else if (response.IsErrorResponse())
- error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64, addr);
- else if (response.IsUnsupportedResponse())
- error.SetErrorStringWithFormat("GDB server does not support writing memory");
- else
- error.SetErrorStringWithFormat("unexpected response to GDB server memory write packet '%s': '%s'", packet.GetString().c_str(), response.GetStringRef().c_str());
- }
+ error = m_gdb_comm.Detach(keep_stopped);
+ if (log) {
+ if (error.Success())
+ log->PutCString(
+ "ProcessGDBRemote::DoDetach() detach packet sent successfully");
else
- {
- error.SetErrorStringWithFormat("failed to send packet: '%s'", packet.GetString().c_str());
- }
- return 0;
-}
+ log->Printf("ProcessGDBRemote::DoDetach() detach packet send failed: %s",
+ error.AsCString() ? error.AsCString() : "<unknown error>");
+ }
-lldb::addr_t
-ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
-{
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_EXPRESSIONS));
- addr_t allocated_addr = LLDB_INVALID_ADDRESS;
+ if (!error.Success())
+ return error;
- if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo)
- {
- allocated_addr = m_gdb_comm.AllocateMemory (size, permissions);
- if (allocated_addr != LLDB_INVALID_ADDRESS || m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes)
- return allocated_addr;
- }
+ // Sleep for one second to let the process get all detached...
+ StopAsyncThread();
- if (m_gdb_comm.SupportsAllocDeallocMemory() == 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;
- if (log)
- log->Printf ("ProcessGDBRemote::%s no direct stub support for memory allocation, and InferiorCallMmap also failed - is stub missing register context save/restore capability?", __FUNCTION__);
- }
- }
+ SetPrivateState(eStateDetached);
+ ResumePrivateStateThread();
- if (allocated_addr == LLDB_INVALID_ADDRESS)
- error.SetErrorStringWithFormat("unable to allocate %" PRIu64 " bytes of memory with permissions %s", (uint64_t)size, GetPermissionsAsCString (permissions));
- else
- error.Clear();
- return allocated_addr;
+ // KillDebugserverProcess ();
+ return error;
}
-Error
-ProcessGDBRemote::GetMemoryRegionInfo (addr_t load_addr,
- MemoryRegionInfo ®ion_info)
-{
+Error ProcessGDBRemote::DoDestroy() {
+ Error error;
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::DoDestroy()");
+
+ // There is a bug in older iOS debugservers where they don't shut down the
+ // process
+ // they are debugging properly. If the process is sitting at a breakpoint or
+ // an exception,
+ // this can cause problems with restarting. So we check to see if any of our
+ // threads are stopped
+ // at a breakpoint, and if so we remove all the breakpoints, resume the
+ // process, and THEN
+ // destroy it again.
+ //
+ // Note, we don't have a good way to test the version of debugserver, but I
+ // happen to know that
+ // the set of all the iOS debugservers which don't support
+ // GetThreadSuffixSupported() and that of
+ // the debugservers with this bug are equal. There really should be a better
+ // way to test this!
+ //
+ // We also use m_destroy_tried_resuming to make sure we only do this once, if
+ // we resume and then halt and
+ // get called here to destroy again and we're still at a breakpoint or
+ // exception, then we should
+ // just do the straight-forward kill.
+ //
+ // And of course, if we weren't able to stop the process by the time we get
+ // here, it isn't
+ // necessary (or helpful) to do any of this.
+
+ if (!m_gdb_comm.GetThreadSuffixSupported() &&
+ m_public_state.GetValue() != eStateRunning) {
+ PlatformSP platform_sp = GetTarget().GetPlatform();
+
+ // FIXME: These should be ConstStrings so we aren't doing strcmp'ing.
+ if (platform_sp && platform_sp->GetName() &&
+ platform_sp->GetName() == PlatformRemoteiOS::GetPluginNameStatic()) {
+ if (m_destroy_tried_resuming) {
+ if (log)
+ log->PutCString("ProcessGDBRemote::DoDestroy() - Tried resuming to "
+ "destroy once already, not doing it again.");
+ } else {
+ // At present, the plans are discarded and the breakpoints disabled
+ // Process::Destroy,
+ // but we really need it to happen here and it doesn't matter if we do
+ // it twice.
+ m_thread_list.DiscardThreadPlans();
+ DisableAllBreakpointSites();
+
+ bool stop_looks_like_crash = false;
+ ThreadList &threads = GetThreadList();
+
+ {
+ std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+
+ size_t num_threads = threads.GetSize();
+ for (size_t i = 0; i < num_threads; i++) {
+ ThreadSP thread_sp = threads.GetThreadAtIndex(i);
+ StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
+ StopReason reason = eStopReasonInvalid;
+ if (stop_info_sp)
+ reason = stop_info_sp->GetStopReason();
+ if (reason == eStopReasonBreakpoint ||
+ reason == eStopReasonException) {
+ if (log)
+ log->Printf(
+ "ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64
+ " stopped with reason: %s.",
+ thread_sp->GetProtocolID(), stop_info_sp->GetDescription());
+ stop_looks_like_crash = true;
+ break;
+ }
+ }
+ }
+
+ if (stop_looks_like_crash) {
+ if (log)
+ log->PutCString("ProcessGDBRemote::DoDestroy() - Stopped at a "
+ "breakpoint, continue and then kill.");
+ m_destroy_tried_resuming = true;
+
+ // If we are going to run again before killing, it would be good to
+ // suspend all the threads
+ // before resuming so they won't get into more trouble. Sadly, for
+ // the threads stopped with
+ // the breakpoint or exception, the exception doesn't get cleared if
+ // it is suspended, so we do
+ // have to run the risk of letting those threads proceed a bit.
+
+ {
+ std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+
+ size_t num_threads = threads.GetSize();
+ for (size_t i = 0; i < num_threads; i++) {
+ ThreadSP thread_sp = threads.GetThreadAtIndex(i);
+ StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
+ StopReason reason = eStopReasonInvalid;
+ if (stop_info_sp)
+ reason = stop_info_sp->GetStopReason();
+ if (reason != eStopReasonBreakpoint &&
+ reason != eStopReasonException) {
+ if (log)
+ log->Printf("ProcessGDBRemote::DoDestroy() - Suspending "
+ "thread: 0x%4.4" PRIx64 " before running.",
+ thread_sp->GetProtocolID());
+ thread_sp->SetResumeState(eStateSuspended);
+ }
+ }
+ }
+ Resume();
+ return Destroy(false);
+ }
+ }
+ }
+ }
+
+ // Interrupt if our inferior is running...
+ int exit_status = SIGABRT;
+ std::string exit_string;
+
+ if (m_gdb_comm.IsConnected()) {
+ if (m_public_state.GetValue() != eStateAttaching) {
+ StringExtractorGDBRemote response;
+ bool send_async = true;
+ GDBRemoteCommunication::ScopedTimeout(m_gdb_comm, 3);
+
+ if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response,
+ send_async) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ char packet_cmd = response.GetChar(0);
- Error error (m_gdb_comm.GetMemoryRegionInfo (load_addr, region_info));
- return error;
-}
+ if (packet_cmd == 'W' || packet_cmd == 'X') {
+#if defined(__APPLE__)
+ // For Native processes on Mac OS X, we launch through the Host
+ // Platform, then hand the process off
+ // to debugserver, which becomes the parent process through
+ // "PT_ATTACH". Then when we go to kill
+ // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we
+ // call waitpid which returns
+ // with no error and the correct status. But amusingly enough that
+ // doesn't seem to actually reap
+ // the process, but instead it is left around as a Zombie. Probably
+ // the kernel is in the process of
+ // switching ownership back to lldb which was the original parent, and
+ // gets confused in the handoff.
+ // Anyway, so call waitpid here to finally reap it.
+ PlatformSP platform_sp(GetTarget().GetPlatform());
+ if (platform_sp && platform_sp->IsHost()) {
+ int status;
+ ::pid_t reap_pid;
+ reap_pid = waitpid(GetID(), &status, WNOHANG);
+ if (log)
+ log->Printf("Reaped pid: %d, status: %d.\n", reap_pid, status);
+ }
+#endif
+ SetLastStopPacket(response);
+ ClearThreadIDList();
+ exit_status = response.GetHexU8();
+ } else {
+ if (log)
+ log->Printf("ProcessGDBRemote::DoDestroy - got unexpected response "
+ "to k packet: %s",
+ response.GetStringRef().c_str());
+ exit_string.assign("got unexpected response to k packet: ");
+ exit_string.append(response.GetStringRef());
+ }
+ } else {
+ if (log)
+ log->Printf("ProcessGDBRemote::DoDestroy - failed to send k packet");
+ exit_string.assign("failed to send the k packet");
+ }
+ } else {
+ if (log)
+ log->Printf("ProcessGDBRemote::DoDestroy - killed or interrupted while "
+ "attaching");
+ exit_string.assign("killed or interrupted while attaching.");
+ }
+ } else {
+ // If we missed setting the exit status on the way out, do it here.
+ // NB set exit status can be called multiple times, the first one sets the
+ // status.
+ exit_string.assign("destroying when not connected to debugserver");
+ }
+
+ SetExitStatus(exit_status, exit_string.c_str());
+
+ StopAsyncThread();
+ KillDebugserverProcess();
+ return error;
+}
+
+void ProcessGDBRemote::SetLastStopPacket(
+ const StringExtractorGDBRemote &response) {
+ const bool did_exec =
+ response.GetStringRef().find(";reason:exec;") != std::string::npos;
+ if (did_exec) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::SetLastStopPacket () - detected exec");
-Error
-ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num)
-{
+ m_thread_list_real.Clear();
+ m_thread_list.Clear();
+ BuildDynamicRegisterInfo(true);
+ m_gdb_comm.ResetDiscoverableSettings(did_exec);
+ }
- Error error (m_gdb_comm.GetWatchpointSupportInfo (num));
- return error;
+ // Scope the lock
+ {
+ // Lock the thread stack while we access it
+ std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
+
+ // We are are not using non-stop mode, there can only be one last stop
+ // reply packet, so clear the list.
+ if (GetTarget().GetNonStopModeEnabled() == false)
+ m_stop_packet_stack.clear();
+
+ // Add this stop packet to the stop packet stack
+ // This stack will get popped and examined when we switch to the
+ // Stopped state
+ m_stop_packet_stack.push_back(response);
+ }
}
-Error
-ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num, bool& after)
-{
- Error error (m_gdb_comm.GetWatchpointSupportInfo (num, after, GetTarget().GetArchitecture()));
- return error;
+void ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) {
+ Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp));
}
-Error
-ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr)
-{
- Error error;
- 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;
+//------------------------------------------------------------------
+// Process Queries
+//------------------------------------------------------------------
- case eLazyBoolYes:
- if (!m_gdb_comm.DeallocateMemory (addr))
- error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
- break;
+bool ProcessGDBRemote::IsAlive() {
+ return m_gdb_comm.IsConnected() && Process::IsAlive();
+}
- case eLazyBoolNo:
- // Call munmap() to deallocate memory in the inferior..
- {
- 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%" PRIx64, addr);
- }
- break;
+addr_t ProcessGDBRemote::GetImageInfoAddress() {
+ // request the link map address via the $qShlibInfoAddr packet
+ lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr();
+
+ // the loaded module list can also provides a link map address
+ if (addr == LLDB_INVALID_ADDRESS) {
+ LoadedModuleInfoList list;
+ if (GetLoadedModuleList(list).Success())
+ addr = list.m_link_map;
+ }
+
+ return addr;
+}
+
+void ProcessGDBRemote::WillPublicStop() {
+ // See if the GDB remote client supports the JSON threads info.
+ // If so, we gather stop info for all threads, expedited registers,
+ // expedited memory, runtime queue information (iOS and MacOSX only),
+ // and more. Expediting memory will help stack backtracing be much
+ // faster. Expediting registers will make sure we don't have to read
+ // the thread registers for GPRs.
+ m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo();
+
+ if (m_jthreadsinfo_sp) {
+ // Now set the stop info for each thread and also expedite any registers
+ // and memory that was in the jThreadsInfo response.
+ StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
+ if (thread_infos) {
+ const size_t n = thread_infos->GetSize();
+ for (size_t i = 0; i < n; ++i) {
+ StructuredData::Dictionary *thread_dict =
+ thread_infos->GetItemAtIndex(i)->GetAsDictionary();
+ if (thread_dict)
+ SetThreadStopInfo(thread_dict);
+ }
}
-
- return error;
+ }
}
-
//------------------------------------------------------------------
-// Process STDIO
+// Process Memory
//------------------------------------------------------------------
-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);
- }
- else if (m_stdin_forward)
- {
- m_gdb_comm.SendStdinNotification(src, src_len);
+size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
+ Error &error) {
+ GetMaxMemorySize();
+ 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];
+ int packet_len;
+ bool binary_memory_read = m_gdb_comm.GetxPacketSupported();
+ packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64,
+ binary_memory_read ? 'x' : 'm', (uint64_t)addr,
+ (uint64_t)size);
+ assert(packet_len + 1 < (int)sizeof(packet));
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response,
+ true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsNormalResponse()) {
+ error.Clear();
+ if (binary_memory_read) {
+ // The lower level GDBRemoteCommunication packet receive layer has
+ // already de-quoted any
+ // 0x7d character escaping that was present in the packet
+
+ size_t data_received_size = response.GetBytesLeft();
+ if (data_received_size > size) {
+ // Don't write past the end of BUF if the remote debug server gave us
+ // too
+ // much data for some reason.
+ data_received_size = size;
+ }
+ memcpy(buf, response.GetStringRef().data(), data_received_size);
+ return data_received_size;
+ } else {
+ return response.GetHexBytes(
+ llvm::MutableArrayRef<uint8_t>((uint8_t *)buf, size), '\xdd');
+ }
+ } else if (response.IsErrorResponse())
+ error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr);
+ else if (response.IsUnsupportedResponse())
+ error.SetErrorStringWithFormat(
+ "GDB server does not support reading memory");
+ else
+ error.SetErrorStringWithFormat(
+ "unexpected response to GDB server memory read packet '%s': '%s'",
+ packet, response.GetStringRef().c_str());
+ } else {
+ error.SetErrorStringWithFormat("failed to send packet: '%s'", packet);
+ }
+ return 0;
+}
+
+size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf,
+ size_t size, Error &error) {
+ GetMaxMemorySize();
+ 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%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
+ packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(
+ packet.GetData(), packet.GetSize(), response, true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ error.Clear();
+ return size;
+ } else if (response.IsErrorResponse())
+ error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64,
+ addr);
+ else if (response.IsUnsupportedResponse())
+ error.SetErrorStringWithFormat(
+ "GDB server does not support writing memory");
+ else
+ error.SetErrorStringWithFormat(
+ "unexpected response to GDB server memory write packet '%s': '%s'",
+ packet.GetString().c_str(), response.GetStringRef().c_str());
+ } else {
+ error.SetErrorStringWithFormat("failed to send packet: '%s'",
+ packet.GetString().c_str());
+ }
+ return 0;
+}
+
+lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size,
+ uint32_t permissions,
+ Error &error) {
+ Log *log(
+ GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_EXPRESSIONS));
+ addr_t allocated_addr = LLDB_INVALID_ADDRESS;
+
+ if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo) {
+ allocated_addr = m_gdb_comm.AllocateMemory(size, permissions);
+ if (allocated_addr != LLDB_INVALID_ADDRESS ||
+ m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes)
+ return allocated_addr;
+ }
+
+ if (m_gdb_comm.SupportsAllocDeallocMemory() == 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;
+ if (log)
+ log->Printf("ProcessGDBRemote::%s no direct stub support for memory "
+ "allocation, and InferiorCallMmap also failed - is stub "
+ "missing register context save/restore capability?",
+ __FUNCTION__);
+ }
+ }
+
+ if (allocated_addr == LLDB_INVALID_ADDRESS)
+ error.SetErrorStringWithFormat(
+ "unable to allocate %" PRIu64 " bytes of memory with permissions %s",
+ (uint64_t)size, GetPermissionsAsCString(permissions));
+ else
+ error.Clear();
+ return allocated_addr;
+}
+
+Error ProcessGDBRemote::GetMemoryRegionInfo(addr_t load_addr,
+ MemoryRegionInfo ®ion_info) {
+
+ Error error(m_gdb_comm.GetMemoryRegionInfo(load_addr, region_info));
+ return error;
+}
+
+Error ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num) {
+
+ Error error(m_gdb_comm.GetWatchpointSupportInfo(num));
+ return error;
+}
+
+Error ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num, bool &after) {
+ Error error(m_gdb_comm.GetWatchpointSupportInfo(
+ num, after, GetTarget().GetArchitecture()));
+ return error;
+}
+
+Error ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) {
+ Error error;
+ 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%" PRIx64, addr);
+ break;
+
+ case eLazyBoolNo:
+ // Call munmap() to deallocate memory in the inferior..
+ {
+ 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%" PRIx64, addr);
}
- return 0;
-}
+ break;
+ }
-Error
-ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
-{
- Error error;
- assert(bp_site != NULL);
-
- // Get logging info
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
- user_id_t site_id = bp_site->GetID();
+ return error;
+}
- // Get the breakpoint address
- const addr_t addr = bp_site->GetLoadAddress();
+//------------------------------------------------------------------
+// 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);
+ } else if (m_stdin_forward) {
+ m_gdb_comm.SendStdinNotification(src, src_len);
+ }
+ return 0;
+}
+
+Error ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
+ Error error;
+ assert(bp_site != NULL);
+
+ // Get logging info
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
+ user_id_t site_id = bp_site->GetID();
+
+ // Get the breakpoint address
+ const addr_t addr = bp_site->GetLoadAddress();
+
+ // Log that a breakpoint was requested
+ if (log)
+ log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64
+ ") address = 0x%" PRIx64,
+ site_id, (uint64_t)addr);
- // Log that a breakpoint was requested
+ // Breakpoint already exists and is enabled
+ if (bp_site->IsEnabled()) {
if (log)
- log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64, site_id, (uint64_t)addr);
-
- // Breakpoint already exists and is enabled
- if (bp_site->IsEnabled())
- {
- if (log)
- log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", site_id, (uint64_t)addr);
- return error;
- }
-
- // Get the software breakpoint trap opcode size
- const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);
-
- // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this breakpoint type
- // is supported by the remote stub. These are set to true by default, and later set to false
- // only after we receive an unimplemented response when sending a breakpoint packet. This means
- // initially that unless we were specifically instructed to use a hardware breakpoint, LLDB will
- // attempt to set a software breakpoint. HardwareRequired() also queries a boolean variable which
- // indicates if the user specifically asked for hardware breakpoints. If true then we will
- // skip over software breakpoints.
- if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && (!bp_site->HardwareRequired()))
- {
- // Try to send off a software breakpoint packet ($Z0)
- uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size);
- if (error_no == 0)
- {
- // The breakpoint was placed successfully
- bp_site->SetEnabled(true);
- bp_site->SetType(BreakpointSite::eExternal);
- return error;
- }
-
- // SendGDBStoppointTypePacket() will return an error if it was unable to set this
- // breakpoint. We need to differentiate between a error specific to placing this breakpoint
- // or if we have learned that this breakpoint type is unsupported. To do this, we
- // must test the support boolean for this breakpoint type to see if it now indicates that
- // this breakpoint type is unsupported. If they are still supported then we should return
- // with the error code. If they are now unsupported, then we would like to fall through
- // and try another form of breakpoint.
- if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware))
- {
- if (error_no != UINT8_MAX)
- error.SetErrorStringWithFormat("error: %d sending the breakpoint request", errno);
- else
- error.SetErrorString("error sending the breakpoint request");
- return error;
- }
-
- // We reach here when software breakpoints have been found to be unsupported. For future
- // calls to set a breakpoint, we will not attempt to set a breakpoint with a type that is
- // known not to be supported.
- if (log)
- log->Printf("Software breakpoints are unsupported");
-
- // So we will fall through and try a hardware breakpoint
- }
-
- // The process of setting a hardware breakpoint is much the same as above. We check the
- // supported boolean for this breakpoint type, and if it is thought to be supported then we
- // will try to set this breakpoint with a hardware breakpoint.
- if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware))
- {
- // Try to send off a hardware breakpoint packet ($Z1)
- uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size);
- if (error_no == 0)
- {
- // The breakpoint was placed successfully
- bp_site->SetEnabled(true);
- bp_site->SetType(BreakpointSite::eHardware);
- return error;
- }
+ log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64
+ ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)",
+ site_id, (uint64_t)addr);
+ return error;
+ }
- // Check if the error was something other then an unsupported breakpoint type
- if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware))
- {
- // Unable to set this hardware breakpoint
- if (error_no != UINT8_MAX)
- error.SetErrorStringWithFormat("error: %d sending the hardware breakpoint request "
- "(hardware breakpoint resources might be exhausted or unavailable)",
- error_no);
- else
- error.SetErrorString("error sending the hardware breakpoint request (hardware breakpoint resources "
- "might be exhausted or unavailable)");
- return error;
- }
+ // Get the software breakpoint trap opcode size
+ const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);
- // We will reach here when the stub gives an unsupported response to a hardware breakpoint
- if (log)
- log->Printf("Hardware breakpoints are unsupported");
+ // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this
+ // breakpoint type
+ // is supported by the remote stub. These are set to true by default, and
+ // later set to false
+ // only after we receive an unimplemented response when sending a breakpoint
+ // packet. This means
+ // initially that unless we were specifically instructed to use a hardware
+ // breakpoint, LLDB will
+ // attempt to set a software breakpoint. HardwareRequired() also queries a
+ // boolean variable which
+ // indicates if the user specifically asked for hardware breakpoints. If true
+ // then we will
+ // skip over software breakpoints.
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) &&
+ (!bp_site->HardwareRequired())) {
+ // Try to send off a software breakpoint packet ($Z0)
+ uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
+ eBreakpointSoftware, true, addr, bp_op_size);
+ if (error_no == 0) {
+ // The breakpoint was placed successfully
+ bp_site->SetEnabled(true);
+ bp_site->SetType(BreakpointSite::eExternal);
+ return error;
+ }
+
+ // SendGDBStoppointTypePacket() will return an error if it was unable to set
+ // this
+ // breakpoint. We need to differentiate between a error specific to placing
+ // this breakpoint
+ // or if we have learned that this breakpoint type is unsupported. To do
+ // this, we
+ // must test the support boolean for this breakpoint type to see if it now
+ // indicates that
+ // this breakpoint type is unsupported. If they are still supported then we
+ // should return
+ // with the error code. If they are now unsupported, then we would like to
+ // fall through
+ // and try another form of breakpoint.
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) {
+ if (error_no != UINT8_MAX)
+ error.SetErrorStringWithFormat(
+ "error: %d sending the breakpoint request", errno);
+ else
+ error.SetErrorString("error sending the breakpoint request");
+ return error;
+ }
+
+ // We reach here when software breakpoints have been found to be
+ // unsupported. For future
+ // calls to set a breakpoint, we will not attempt to set a breakpoint with a
+ // type that is
+ // known not to be supported.
+ if (log)
+ log->Printf("Software breakpoints are unsupported");
- // Finally we will falling through to a #trap style breakpoint
- }
+ // So we will fall through and try a hardware breakpoint
+ }
- // Don't fall through when hardware breakpoints were specifically requested
- if (bp_site->HardwareRequired())
- {
- error.SetErrorString("hardware breakpoints are not supported");
- return error;
+ // The process of setting a hardware breakpoint is much the same as above. We
+ // check the
+ // supported boolean for this breakpoint type, and if it is thought to be
+ // supported then we
+ // will try to set this breakpoint with a hardware breakpoint.
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
+ // Try to send off a hardware breakpoint packet ($Z1)
+ uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
+ eBreakpointHardware, true, addr, bp_op_size);
+ if (error_no == 0) {
+ // The breakpoint was placed successfully
+ bp_site->SetEnabled(true);
+ bp_site->SetType(BreakpointSite::eHardware);
+ return error;
+ }
+
+ // Check if the error was something other then an unsupported breakpoint
+ // type
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
+ // Unable to set this hardware breakpoint
+ if (error_no != UINT8_MAX)
+ error.SetErrorStringWithFormat(
+ "error: %d sending the hardware breakpoint request "
+ "(hardware breakpoint resources might be exhausted or unavailable)",
+ error_no);
+ else
+ error.SetErrorString("error sending the hardware breakpoint request "
+ "(hardware breakpoint resources "
+ "might be exhausted or unavailable)");
+ return error;
}
- // As a last resort we want to place a manual breakpoint. An instruction
- // is placed into the process memory using memory write packets.
- return EnableSoftwareBreakpoint(bp_site);
-}
-
-Error
-ProcessGDBRemote::DisableBreakpointSite (BreakpointSite *bp_site)
-{
- Error error;
- assert (bp_site != NULL);
- addr_t addr = bp_site->GetLoadAddress();
- user_id_t site_id = bp_site->GetID();
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
+ // We will reach here when the stub gives an unsupported response to a
+ // hardware breakpoint
if (log)
- log->Printf ("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64, site_id, (uint64_t)addr);
+ log->Printf("Hardware breakpoints are unsupported");
- if (bp_site->IsEnabled())
- {
- const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
-
- BreakpointSite::Type bp_type = bp_site->GetType();
- switch (bp_type)
- {
- case BreakpointSite::eSoftware:
- error = DisableSoftwareBreakpoint (bp_site);
- break;
+ // Finally we will falling through to a #trap style breakpoint
+ }
- case BreakpointSite::eHardware:
- if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, addr, bp_op_size))
- error.SetErrorToGenericError();
- break;
+ // Don't fall through when hardware breakpoints were specifically requested
+ if (bp_site->HardwareRequired()) {
+ error.SetErrorString("hardware breakpoints are not supported");
+ return error;
+ }
- case BreakpointSite::eExternal:
- {
- GDBStoppointType stoppoint_type;
- if (bp_site->IsHardware())
- stoppoint_type = eBreakpointHardware;
- else
- stoppoint_type = eBreakpointSoftware;
+ // As a last resort we want to place a manual breakpoint. An instruction
+ // is placed into the process memory using memory write packets.
+ return EnableSoftwareBreakpoint(bp_site);
+}
+
+Error ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) {
+ Error error;
+ assert(bp_site != NULL);
+ addr_t addr = bp_site->GetLoadAddress();
+ user_id_t site_id = bp_site->GetID();
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64
+ ") addr = 0x%8.8" PRIx64,
+ site_id, (uint64_t)addr);
- if (m_gdb_comm.SendGDBStoppointTypePacket(stoppoint_type, false, addr, bp_op_size))
- error.SetErrorToGenericError();
- }
- break;
- }
- if (error.Success())
- bp_site->SetEnabled(false);
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", site_id, (uint64_t)addr);
- return error;
- }
+ if (bp_site->IsEnabled()) {
+ const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);
- if (error.Success())
+ BreakpointSite::Type bp_type = bp_site->GetType();
+ switch (bp_type) {
+ case BreakpointSite::eSoftware:
+ error = DisableSoftwareBreakpoint(bp_site);
+ break;
+
+ case BreakpointSite::eHardware:
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false,
+ addr, bp_op_size))
error.SetErrorToGenericError();
- return error;
-}
+ break;
-// 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, bool notify)
-{
- Error error;
- if (wp)
- {
- user_id_t watchID = wp->GetID();
- addr_t addr = wp->GetLoadAddress();
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", watchID);
- if (wp->IsEnabled())
- {
- if (log)
- log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", watchID, (uint64_t)addr);
- return error;
- }
+ case BreakpointSite::eExternal: {
+ GDBStoppointType stoppoint_type;
+ if (bp_site->IsHardware())
+ stoppoint_type = eBreakpointHardware;
+ else
+ stoppoint_type = eBreakpointSoftware;
- 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, notify);
- 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())
+ if (m_gdb_comm.SendGDBStoppointTypePacket(stoppoint_type, false, addr,
+ bp_op_size))
error.SetErrorToGenericError();
- return error;
-}
-
-Error
-ProcessGDBRemote::DisableWatchpoint (Watchpoint *wp, bool notify)
-{
- Error error;
- if (wp)
- {
- user_id_t watchID = wp->GetID();
-
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
-
- addr_t addr = wp->GetLoadAddress();
-
- if (log)
- log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64, watchID, (uint64_t)addr);
-
- if (!wp->IsEnabled())
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", watchID, (uint64_t)addr);
- // See also 'class WatchpointSentry' within StopInfo.cpp.
- // This disabling attempt might come from the user-supplied actions, we'll route it in order for
- // the watchpoint object to intelligently process this action.
- wp->SetEnabled(false, notify);
- 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, notify);
- 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.");
+ } break;
}
if (error.Success())
- error.SetErrorToGenericError();
+ bp_site->SetEnabled(false);
+ } else {
+ if (log)
+ log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)",
+ site_id, (uint64_t)addr);
return error;
-}
+ }
-void
-ProcessGDBRemote::Clear()
-{
- m_flags = 0;
- m_thread_list_real.Clear();
- m_thread_list.Clear();
+ if (error.Success())
+ error.SetErrorToGenericError();
+ return error;
}
-Error
-ProcessGDBRemote::DoSignal (int signo)
-{
- Error error;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+// 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, bool notify) {
+ Error error;
+ if (wp) {
+ user_id_t watchID = wp->GetID();
+ addr_t addr = wp->GetLoadAddress();
+ Log *log(
+ ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
if (log)
- log->Printf ("ProcessGDBRemote::DoSignal (signal = %d)", signo);
+ log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")",
+ watchID);
+ if (wp->IsEnabled()) {
+ if (log)
+ log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 ": 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, notify);
+ 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, bool notify) {
+ Error error;
+ if (wp) {
+ user_id_t watchID = wp->GetID();
- if (!m_gdb_comm.SendAsyncSignal (signo))
- error.SetErrorStringWithFormat("failed to send signal %i", signo);
- return error;
-}
+ Log *log(
+ ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
-Error
-ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info)
-{
- // Make sure we aren't already connected?
- if (m_gdb_comm.IsConnected())
- return Error();
-
- PlatformSP platform_sp (GetTarget ().GetPlatform ());
- if (platform_sp && !platform_sp->IsHost ())
- return Error("Lost debug server connection");
+ addr_t addr = wp->GetLoadAddress();
- auto error = LaunchAndConnectToDebugserver (process_info);
- if (error.Fail())
- {
- const char *error_string = error.AsCString();
- if (error_string == nullptr)
- error_string = "unable to launch " DEBUGSERVER_BASENAME;
+ if (log)
+ log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64,
+ watchID, (uint64_t)addr);
+
+ if (!wp->IsEnabled()) {
+ if (log)
+ log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)",
+ watchID, (uint64_t)addr);
+ // See also 'class WatchpointSentry' within StopInfo.cpp.
+ // This disabling attempt might come from the user-supplied actions, we'll
+ // route it in order for
+ // the watchpoint object to intelligently process this action.
+ wp->SetEnabled(false, notify);
+ 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, notify);
+ return error;
+ } else
+ error.SetErrorString("sending gdb watchpoint packet failed");
}
- return error;
+ // 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_real.Clear();
+ m_thread_list.Clear();
+}
+
+Error ProcessGDBRemote::DoSignal(int signo) {
+ Error error;
+ Log *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 ProcessGDBRemote::EstablishConnectionIfNeeded(
+ const ProcessInfo &process_info) {
+ // Make sure we aren't already connected?
+ if (m_gdb_comm.IsConnected())
+ return Error();
+
+ PlatformSP platform_sp(GetTarget().GetPlatform());
+ if (platform_sp && !platform_sp->IsHost())
+ return Error("Lost debug server connection");
+
+ auto error = LaunchAndConnectToDebugserver(process_info);
+ if (error.Fail()) {
+ const char *error_string = error.AsCString();
+ if (error_string == nullptr)
+ error_string = "unable to launch " DEBUGSERVER_BASENAME;
+ }
+ return error;
}
-#if defined (__APPLE__)
+#if defined(__APPLE__)
#define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1
#endif
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
-static bool SetCloexecFlag(int fd)
-{
-#if defined(FD_CLOEXEC)
- int flags = ::fcntl(fd, F_GETFD);
- if (flags == -1)
- return false;
- return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0);
-#else
+static bool SetCloexecFlag(int fd) {
+#if defined(FD_CLOEXEC)
+ int flags = ::fcntl(fd, F_GETFD);
+ if (flags == -1)
return false;
+ return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0);
+#else
+ return false;
#endif
}
#endif
-Error
-ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info)
-{
- using namespace std::placeholders; // For _1, _2, etc.
-
- 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;
-
- ProcessLaunchInfo debugserver_launch_info;
- // Make debugserver run in its own session so signals generated by
- // special terminal key sequences (^C) don't affect debugserver.
- debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);
+Error ProcessGDBRemote::LaunchAndConnectToDebugserver(
+ const ProcessInfo &process_info) {
+ using namespace std::placeholders; // For _1, _2, etc.
+
+ 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;
+
+ ProcessLaunchInfo debugserver_launch_info;
+ // Make debugserver run in its own session so signals generated by
+ // special terminal key sequences (^C) don't affect debugserver.
+ debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);
+
+ const std::weak_ptr<ProcessGDBRemote> this_wp =
+ std::static_pointer_cast<ProcessGDBRemote>(shared_from_this());
+ debugserver_launch_info.SetMonitorProcessCallback(
+ std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4), false);
+ debugserver_launch_info.SetUserID(process_info.GetUserID());
- const std::weak_ptr<ProcessGDBRemote> this_wp = std::static_pointer_cast<ProcessGDBRemote>(shared_from_this());
- debugserver_launch_info.SetMonitorProcessCallback(std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4),
- false);
- debugserver_launch_info.SetUserID(process_info.GetUserID());
-
-
- int communication_fd = -1;
+ int communication_fd = -1;
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
- // Auto close the sockets we might open up unless everything goes OK. This
- // helps us not leak file descriptors when things go wrong.
- lldb_utility::CleanUp <int, int> our_socket(-1, -1, close);
- lldb_utility::CleanUp <int, int> gdb_socket(-1, -1, close);
-
- // Use a socketpair on Apple for now until other platforms can verify it
- // works and is fast enough
- {
- int sockets[2]; /* the pair of socket descriptors */
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1)
- {
- error.SetErrorToErrno();
- return error;
- }
+ // Auto close the sockets we might open up unless everything goes OK. This
+ // helps us not leak file descriptors when things go wrong.
+ lldb_utility::CleanUp<int, int> our_socket(-1, -1, close);
+ lldb_utility::CleanUp<int, int> gdb_socket(-1, -1, close);
+
+ // Use a socketpair on Apple for now until other platforms can verify it
+ // works and is fast enough
+ {
+ int sockets[2]; /* the pair of socket descriptors */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
+ error.SetErrorToErrno();
+ return error;
+ }
- our_socket.set(sockets[0]);
- gdb_socket.set(sockets[1]);
- }
+ our_socket.set(sockets[0]);
+ gdb_socket.set(sockets[1]);
+ }
- // Don't let any child processes inherit our communication socket
- SetCloexecFlag(our_socket.get());
- communication_fd = gdb_socket.get();
+ // Don't let any child processes inherit our communication socket
+ SetCloexecFlag(our_socket.get());
+ communication_fd = gdb_socket.get();
#endif
- error = m_gdb_comm.StartDebugserverProcess(nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info, nullptr, nullptr, communication_fd);
+ error = m_gdb_comm.StartDebugserverProcess(
+ nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info,
+ nullptr, nullptr, communication_fd);
- if (error.Success ())
- m_debugserver_pid = debugserver_launch_info.GetProcessID();
- else
- m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ if (error.Success())
+ m_debugserver_pid = debugserver_launch_info.GetProcessID();
+ else
+ m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
- if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
- {
+ if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) {
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
- // Our process spawned correctly, we can now set our connection to use our
- // end of the socket pair
- m_gdb_comm.SetConnection(new ConnectionFileDescriptor(our_socket.release(), true));
+ // Our process spawned correctly, we can now set our connection to use our
+ // end of the socket pair
+ m_gdb_comm.SetConnection(
+ new ConnectionFileDescriptor(our_socket.release(), true));
#endif
- StartAsyncThread ();
- }
-
- if (error.Fail())
- {
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+ StartAsyncThread();
+ }
- if (log)
- log->Printf("failed to start debugserver process: %s", error.AsCString());
- return error;
- }
+ if (error.Fail()) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (m_gdb_comm.IsConnected())
- {
- // Finish the connection process by doing the handshake without connecting (send NULL URL)
- ConnectToDebugserver(NULL);
- }
- else
- {
- error.SetErrorString("connection failed");
- }
+ if (log)
+ log->Printf("failed to start debugserver process: %s",
+ error.AsCString());
+ return error;
+ }
+ if (m_gdb_comm.IsConnected()) {
+ // Finish the connection process by doing the handshake without connecting
+ // (send NULL URL)
+ ConnectToDebugserver(NULL);
+ } else {
+ error.SetErrorString("connection failed");
}
- return error;
+ }
+ return error;
}
-bool
-ProcessGDBRemote::MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp, 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
- )
-{
- // "debugserver_pid" argument passed in is the process ID for
- // debugserver that we are tracking...
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- const bool handled = true;
-
- if (log)
- log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 ", signo=%i (0x%x), exit_status=%i)", __FUNCTION__,
- debugserver_pid, signo, signo, exit_status);
-
- std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock();
- if (log)
- log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__, static_cast<void *>(process_sp.get()));
- if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid)
- return handled;
-
- // 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, then we are reaping it.
- const StateType state = process_sp->GetState();
-
- if (state != eStateInvalid && state != eStateUnloaded && state != eStateExited && state != eStateDetached)
- {
- char error_str[1024];
- if (signo)
- {
- const char *signal_cstr = process_sp->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);
- }
+bool ProcessGDBRemote::MonitorDebugserverProcess(
+ std::weak_ptr<ProcessGDBRemote> process_wp, 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
+ ) {
+ // "debugserver_pid" argument passed in is the process ID for
+ // debugserver that we are tracking...
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ const bool handled = true;
+
+ if (log)
+ log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64
+ ", signo=%i (0x%x), exit_status=%i)",
+ __FUNCTION__, debugserver_pid, signo, signo, exit_status);
+
+ std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock();
+ if (log)
+ log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__,
+ static_cast<void *>(process_sp.get()));
+ if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid)
+ return handled;
- process_sp->SetExitStatus(-1, error_str);
+ // 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, then we are reaping it.
+ const StateType state = process_sp->GetState();
+
+ if (state != eStateInvalid && state != eStateUnloaded &&
+ state != eStateExited && state != eStateDetached) {
+ char error_str[1024];
+ if (signo) {
+ const char *signal_cstr =
+ process_sp->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);
}
- // Debugserver has exited we need to let our ProcessGDBRemote
- // know that it no longer has a debugserver instance
- process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
- return handled;
+
+ process_sp->SetExitStatus(-1, error_str);
+ }
+ // Debugserver has exited we need to let our ProcessGDBRemote
+ // know that it no longer has a debugserver instance
+ process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ return handled;
}
-void
-ProcessGDBRemote::KillDebugserverProcess ()
-{
- m_gdb_comm.Disconnect();
- if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
- {
- Host::Kill (m_debugserver_pid, SIGINT);
- m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
- }
+void ProcessGDBRemote::KillDebugserverProcess() {
+ m_gdb_comm.Disconnect();
+ if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) {
+ Host::Kill(m_debugserver_pid, SIGINT);
+ m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ }
}
-void
-ProcessGDBRemote::Initialize()
-{
- static std::once_flag g_once_flag;
+void ProcessGDBRemote::Initialize() {
+ static std::once_flag g_once_flag;
- std::call_once(g_once_flag, []()
- {
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance,
- DebuggerInitialize);
- });
+ std::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ DebuggerInitialize);
+ });
}
-void
-ProcessGDBRemote::DebuggerInitialize (Debugger &debugger)
-{
- if (!PluginManager::GetSettingForProcessPlugin(debugger, PluginProperties::GetSettingName()))
- {
- const bool is_global_setting = true;
- PluginManager::CreateSettingForProcessPlugin (debugger,
- GetGlobalPluginProperties()->GetValueProperties(),
- ConstString ("Properties for the gdb-remote process plug-in."),
- is_global_setting);
- }
+void ProcessGDBRemote::DebuggerInitialize(Debugger &debugger) {
+ if (!PluginManager::GetSettingForProcessPlugin(
+ debugger, PluginProperties::GetSettingName())) {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForProcessPlugin(
+ debugger, GetGlobalPluginProperties()->GetValueProperties(),
+ ConstString("Properties for the gdb-remote process plug-in."),
+ is_global_setting);
+ }
}
-bool
-ProcessGDBRemote::StartAsyncThread ()
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+bool ProcessGDBRemote::StartAsyncThread() {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
+ if (log)
+ log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__);
- std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
- if (!m_async_thread.IsJoinable())
- {
- // Create a thread that watches our internal state and controls which
- // events make it to clients (into the DCProcess event queue).
+ std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
+ if (!m_async_thread.IsJoinable()) {
+ // Create a thread that watches our internal state and controls which
+ // events make it to clients (into the DCProcess event queue).
- m_async_thread = ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
- }
- else if (log)
- log->Printf("ProcessGDBRemote::%s () - Called when Async thread was already running.", __FUNCTION__);
+ m_async_thread =
+ ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>",
+ ProcessGDBRemote::AsyncThread, this, NULL);
+ } else if (log)
+ log->Printf("ProcessGDBRemote::%s () - Called when Async thread was "
+ "already running.",
+ __FUNCTION__);
- return m_async_thread.IsJoinable();
+ return m_async_thread.IsJoinable();
}
-void
-ProcessGDBRemote::StopAsyncThread ()
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+void ProcessGDBRemote::StopAsyncThread() {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
+ if (log)
+ log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__);
- std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
- if (m_async_thread.IsJoinable())
- {
- m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
+ std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
+ if (m_async_thread.IsJoinable()) {
+ m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit);
- // This will shut down the async thread.
- m_gdb_comm.Disconnect(); // Disconnect from the debug server.
+ // This will shut down the async thread.
+ m_gdb_comm.Disconnect(); // Disconnect from the debug server.
- // Stop the stdio thread
- m_async_thread.Join(nullptr);
- m_async_thread.Reset();
- }
- else if (log)
- log->Printf("ProcessGDBRemote::%s () - Called when Async thread was not running.", __FUNCTION__);
-}
-
-bool
-ProcessGDBRemote::HandleNotifyPacket (StringExtractorGDBRemote &packet)
-{
- // get the packet at a string
- const std::string &pkt = packet.GetStringRef();
- // skip %stop:
- StringExtractorGDBRemote stop_info(pkt.c_str() + 5);
-
- // pass as a thread stop info packet
- SetLastStopPacket(stop_info);
-
- // check for more stop reasons
- HandleStopReplySequence();
-
- // if the process is stopped then we need to fake a resume
- // so that we can stop properly with the new break. This
- // is possible due to SetPrivateState() broadcasting the
- // state change as a side effect.
- if (GetPrivateState() == lldb::StateType::eStateStopped)
- {
- SetPrivateState(lldb::StateType::eStateRunning);
- }
+ // Stop the stdio thread
+ m_async_thread.Join(nullptr);
+ m_async_thread.Reset();
+ } else if (log)
+ log->Printf(
+ "ProcessGDBRemote::%s () - Called when Async thread was not running.",
+ __FUNCTION__);
+}
- // since we have some stopped packets we can halt the process
- SetPrivateState(lldb::StateType::eStateStopped);
+bool ProcessGDBRemote::HandleNotifyPacket(StringExtractorGDBRemote &packet) {
+ // get the packet at a string
+ const std::string &pkt = packet.GetStringRef();
+ // skip %stop:
+ StringExtractorGDBRemote stop_info(pkt.c_str() + 5);
- return true;
+ // pass as a thread stop info packet
+ SetLastStopPacket(stop_info);
+
+ // check for more stop reasons
+ HandleStopReplySequence();
+
+ // if the process is stopped then we need to fake a resume
+ // so that we can stop properly with the new break. This
+ // is possible due to SetPrivateState() broadcasting the
+ // state change as a side effect.
+ if (GetPrivateState() == lldb::StateType::eStateStopped) {
+ SetPrivateState(lldb::StateType::eStateRunning);
+ }
+
+ // since we have some stopped packets we can halt the process
+ SetPrivateState(lldb::StateType::eStateStopped);
+
+ return true;
}
-thread_result_t
-ProcessGDBRemote::AsyncThread (void *arg)
-{
- ProcessGDBRemote *process = (ProcessGDBRemote*) arg;
+thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
+ ProcessGDBRemote *process = (ProcessGDBRemote *)arg;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, arg, process->GetID());
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") thread starting...",
+ __FUNCTION__, arg, process->GetID());
- EventSP event_sp;
- bool done = false;
- while (!done)
- {
+ EventSP event_sp;
+ bool done = false;
+ while (!done) {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") listener.WaitForEvent (NULL, event_sp)...",
+ __FUNCTION__, arg, process->GetID());
+ if (process->m_async_listener_sp->WaitForEvent(std::chrono::microseconds(0),
+ 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 = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
- if (process->m_async_listener_sp->WaitForEvent(std::chrono::microseconds(0), 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 = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") 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 = %" PRIu64
+ ") got eBroadcastBitAsyncContinue: %s",
+ __FUNCTION__, arg, process->GetID(), continue_cstr);
- 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 = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
-
- if (::strstr (continue_cstr, "vAttach") == NULL)
- process->SetPrivateState(eStateRunning);
- StringExtractorGDBRemote response;
-
- // If in Non-Stop-Mode
- if (process->GetTarget().GetNonStopModeEnabled())
- {
- // send the vCont packet
- if (!process->GetGDBRemote().SendvContPacket(
- llvm::StringRef(continue_cstr, continue_cstr_len), response))
- {
- // Something went wrong
- done = true;
- break;
- }
- }
- // If in All-Stop-Mode
- else
- {
- StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse(
- *process, *process->GetUnixSignals(),
- llvm::StringRef(continue_cstr, continue_cstr_len), response);
-
- // We need to immediately clear the thread ID list so we are sure to get a valid list of threads.
- // The thread ID list might be contained within the "response", or the stop reply packet that
- // caused the stop. So clear it now before we give the stop reply packet to the process
- // using the process->SetLastStopPacket()...
- process->ClearThreadIDList ();
-
- switch (stop_state)
- {
- case eStateStopped:
- case eStateCrashed:
- case eStateSuspended:
- process->SetLastStopPacket (response);
- process->SetPrivateState (stop_state);
- break;
-
- case eStateExited:
- {
- process->SetLastStopPacket (response);
- process->ClearThreadIDList();
- response.SetFilePos(1);
-
- int exit_status = response.GetHexU8();
- std::string desc_string;
- if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';')
- {
- llvm::StringRef desc_str;
- llvm::StringRef desc_token;
- while (response.GetNameColonValue(desc_token, desc_str))
- {
- if (desc_token != "description")
- continue;
- StringExtractor extractor(desc_str);
- extractor.GetHexByteString(desc_string);
- }
- }
- process->SetExitStatus(exit_status, desc_string.c_str());
- done = true;
- break;
- }
- case eStateInvalid:
- {
- // Check to see if we were trying to attach and if we got back
- // the "E87" error code from debugserver -- this indicates that
- // the process is not debuggable. Return a slightly more helpful
- // error message about why the attach failed.
- if (::strstr (continue_cstr, "vAttach") != NULL
- && response.GetError() == 0x87)
- {
- process->SetExitStatus(-1, "cannot attach to process due to System Integrity Protection");
- }
- // E01 code from vAttach means that the attach failed
- if (::strstr (continue_cstr, "vAttach") != NULL
- && response.GetError() == 0x1)
- {
- process->SetExitStatus(-1, "unable to attach");
- }
- else
- {
- process->SetExitStatus(-1, "lost connection");
- }
- break;
- }
-
- default:
- process->SetPrivateState (stop_state);
- break;
- } // switch(stop_state)
- } // else // if in All-stop-mode
- } // if (continue_packet)
- } // case eBroadcastBitAysncContinue
- break;
-
- case eBroadcastBitAsyncThreadShouldExit:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
- done = true;
- break;
-
- default:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
- done = true;
- break;
- }
+ if (::strstr(continue_cstr, "vAttach") == NULL)
+ process->SetPrivateState(eStateRunning);
+ StringExtractorGDBRemote response;
+
+ // If in Non-Stop-Mode
+ if (process->GetTarget().GetNonStopModeEnabled()) {
+ // send the vCont packet
+ if (!process->GetGDBRemote().SendvContPacket(
+ llvm::StringRef(continue_cstr, continue_cstr_len),
+ response)) {
+ // Something went wrong
+ done = true;
+ break;
+ }
}
- else if (event_sp->BroadcasterIs (&process->m_gdb_comm))
- {
- switch (event_type)
- {
- case Communication::eBroadcastBitReadThreadDidExit:
- process->SetExitStatus (-1, "lost connection");
- done = true;
- break;
-
- case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify:
- {
- lldb_private::Event *event = event_sp.get();
- const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event);
- StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes());
- // Hand this over to the process to handle
- process->HandleNotifyPacket(notify);
- break;
- }
-
- default:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
- done = true;
- break;
+ // If in All-Stop-Mode
+ else {
+ StateType stop_state =
+ process->GetGDBRemote().SendContinuePacketAndWaitForResponse(
+ *process, *process->GetUnixSignals(),
+ llvm::StringRef(continue_cstr, continue_cstr_len),
+ response);
+
+ // We need to immediately clear the thread ID list so we are sure
+ // to get a valid list of threads.
+ // The thread ID list might be contained within the "response", or
+ // the stop reply packet that
+ // caused the stop. So clear it now before we give the stop reply
+ // packet to the process
+ // using the process->SetLastStopPacket()...
+ process->ClearThreadIDList();
+
+ switch (stop_state) {
+ case eStateStopped:
+ case eStateCrashed:
+ case eStateSuspended:
+ process->SetLastStopPacket(response);
+ process->SetPrivateState(stop_state);
+ break;
+
+ case eStateExited: {
+ process->SetLastStopPacket(response);
+ process->ClearThreadIDList();
+ response.SetFilePos(1);
+
+ int exit_status = response.GetHexU8();
+ std::string desc_string;
+ if (response.GetBytesLeft() > 0 &&
+ response.GetChar('-') == ';') {
+ llvm::StringRef desc_str;
+ llvm::StringRef desc_token;
+ while (response.GetNameColonValue(desc_token, desc_str)) {
+ if (desc_token != "description")
+ continue;
+ StringExtractor extractor(desc_str);
+ extractor.GetHexByteString(desc_string);
+ }
}
- }
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
- done = true;
+ process->SetExitStatus(exit_status, desc_string.c_str());
+ done = true;
+ break;
+ }
+ case eStateInvalid: {
+ // Check to see if we were trying to attach and if we got back
+ // the "E87" error code from debugserver -- this indicates that
+ // the process is not debuggable. Return a slightly more
+ // helpful
+ // error message about why the attach failed.
+ if (::strstr(continue_cstr, "vAttach") != NULL &&
+ response.GetError() == 0x87) {
+ process->SetExitStatus(-1, "cannot attach to process due to "
+ "System Integrity Protection");
+ }
+ // E01 code from vAttach means that the attach failed
+ if (::strstr(continue_cstr, "vAttach") != NULL &&
+ response.GetError() == 0x1) {
+ process->SetExitStatus(-1, "unable to attach");
+ } else {
+ process->SetExitStatus(-1, "lost connection");
+ }
+ break;
+ }
+
+ default:
+ process->SetPrivateState(stop_state);
+ break;
+ } // switch(stop_state)
+ } // else // if in All-stop-mode
+ } // if (continue_packet)
+ } // case eBroadcastBitAysncContinue
+ break;
+
+ case eBroadcastBitAsyncThreadShouldExit:
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") got eBroadcastBitAsyncThreadShouldExit...",
+ __FUNCTION__, arg, process->GetID());
+ done = true;
+ break;
+
+ default:
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") got unknown event 0x%8.8x",
+ __FUNCTION__, arg, process->GetID(), event_type);
+ done = true;
+ break;
+ }
+ } else if (event_sp->BroadcasterIs(&process->m_gdb_comm)) {
+ switch (event_type) {
+ case Communication::eBroadcastBitReadThreadDidExit:
+ process->SetExitStatus(-1, "lost connection");
+ done = true;
+ break;
+
+ case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify: {
+ lldb_private::Event *event = event_sp.get();
+ const EventDataBytes *continue_packet =
+ EventDataBytes::GetEventDataFromEvent(event);
+ StringExtractorGDBRemote notify(
+ (const char *)continue_packet->GetBytes());
+ // Hand this over to the process to handle
+ process->HandleNotifyPacket(notify);
+ break;
+ }
+
+ default:
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") got unknown event 0x%8.8x",
+ __FUNCTION__, arg, process->GetID(), event_type);
+ done = true;
+ break;
}
+ }
+ } else {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") listener.WaitForEvent (NULL, event_sp) => false",
+ __FUNCTION__, arg, process->GetID());
+ done = true;
}
+ }
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", __FUNCTION__, arg, process->GetID());
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") thread exiting...",
+ __FUNCTION__, arg, process->GetID());
- return NULL;
+ return NULL;
}
-//uint32_t
-//ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
+// 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 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);
@@ -4059,270 +3727,239 @@ ProcessGDBRemote::AsyncThread (void *arg
//
//}
//
-bool
-ProcessGDBRemote::NewThreadNotifyBreakpointHit (void *baton,
- 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.
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- if (log)
- log->Printf("Hit New Thread Notification breakpoint.");
- return false;
+bool ProcessGDBRemote::NewThreadNotifyBreakpointHit(
+ void *baton, 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.
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (log)
+ log->Printf("Hit New Thread Notification breakpoint.");
+ return false;
}
-
-bool
-ProcessGDBRemote::StartNoticingNewThreads()
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- if (m_thread_create_bp_sp)
- {
+bool ProcessGDBRemote::StartNoticingNewThreads() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (m_thread_create_bp_sp) {
+ if (log && log->GetVerbose())
+ log->Printf("Enabled noticing new thread breakpoint.");
+ m_thread_create_bp_sp->SetEnabled(true);
+ } else {
+ PlatformSP platform_sp(GetTarget().GetPlatform());
+ if (platform_sp) {
+ m_thread_create_bp_sp =
+ platform_sp->SetThreadCreationBreakpoint(GetTarget());
+ if (m_thread_create_bp_sp) {
if (log && log->GetVerbose())
- log->Printf("Enabled noticing new thread breakpoint.");
- m_thread_create_bp_sp->SetEnabled(true);
- }
- else
- {
- PlatformSP platform_sp (GetTarget().GetPlatform());
- if (platform_sp)
- {
- m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(GetTarget());
- if (m_thread_create_bp_sp)
- {
- if (log && log->GetVerbose())
- log->Printf("Successfully created new thread notification breakpoint %i", m_thread_create_bp_sp->GetID());
- m_thread_create_bp_sp->SetCallback (ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true);
- }
- else
- {
- if (log)
- log->Printf("Failed to create new thread notification breakpoint.");
- }
- }
+ log->Printf(
+ "Successfully created new thread notification breakpoint %i",
+ m_thread_create_bp_sp->GetID());
+ m_thread_create_bp_sp->SetCallback(
+ ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true);
+ } else {
+ if (log)
+ log->Printf("Failed to create new thread notification breakpoint.");
+ }
}
- return m_thread_create_bp_sp.get() != NULL;
+ }
+ return m_thread_create_bp_sp.get() != NULL;
}
-bool
-ProcessGDBRemote::StopNoticingNewThreads()
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- if (log && log->GetVerbose())
- log->Printf ("Disabling new thread notification breakpoint.");
+bool ProcessGDBRemote::StopNoticingNewThreads() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (log && log->GetVerbose())
+ log->Printf("Disabling new thread notification breakpoint.");
- if (m_thread_create_bp_sp)
- m_thread_create_bp_sp->SetEnabled(false);
+ if (m_thread_create_bp_sp)
+ m_thread_create_bp_sp->SetEnabled(false);
- return true;
+ return true;
}
-DynamicLoader *
-ProcessGDBRemote::GetDynamicLoader ()
-{
- if (m_dyld_ap.get() == NULL)
- m_dyld_ap.reset (DynamicLoader::FindPlugin(this, NULL));
- return m_dyld_ap.get();
-}
-
-Error
-ProcessGDBRemote::SendEventData(const char *data)
-{
- int return_value;
- bool was_supported;
+DynamicLoader *ProcessGDBRemote::GetDynamicLoader() {
+ if (m_dyld_ap.get() == NULL)
+ m_dyld_ap.reset(DynamicLoader::FindPlugin(this, NULL));
+ return m_dyld_ap.get();
+}
- Error error;
+Error ProcessGDBRemote::SendEventData(const char *data) {
+ int return_value;
+ bool was_supported;
- return_value = m_gdb_comm.SendLaunchEventDataPacket (data, &was_supported);
- if (return_value != 0)
- {
- if (!was_supported)
- error.SetErrorString("Sending events is not supported for this process.");
- else
- error.SetErrorStringWithFormat("Error sending event data: %d.", return_value);
- }
- return error;
-}
+ Error error;
-const DataBufferSP
-ProcessGDBRemote::GetAuxvData()
-{
- DataBufferSP buf;
- if (m_gdb_comm.GetQXferAuxvReadSupported())
- {
- std::string response_string;
- if (m_gdb_comm.SendPacketsAndConcatenateResponses("qXfer:auxv:read::", response_string) == GDBRemoteCommunication::PacketResult::Success)
- buf.reset(new DataBufferHeap(response_string.c_str(), response_string.length()));
- }
- return buf;
+ return_value = m_gdb_comm.SendLaunchEventDataPacket(data, &was_supported);
+ if (return_value != 0) {
+ if (!was_supported)
+ error.SetErrorString("Sending events is not supported for this process.");
+ else
+ error.SetErrorStringWithFormat("Error sending event data: %d.",
+ return_value);
+ }
+ return error;
+}
+
+const DataBufferSP ProcessGDBRemote::GetAuxvData() {
+ DataBufferSP buf;
+ if (m_gdb_comm.GetQXferAuxvReadSupported()) {
+ std::string response_string;
+ if (m_gdb_comm.SendPacketsAndConcatenateResponses("qXfer:auxv:read::",
+ response_string) ==
+ GDBRemoteCommunication::PacketResult::Success)
+ buf.reset(new DataBufferHeap(response_string.c_str(),
+ response_string.length()));
+ }
+ return buf;
}
StructuredData::ObjectSP
-ProcessGDBRemote::GetExtendedInfoForThread (lldb::tid_t tid)
-{
- StructuredData::ObjectSP object_sp;
+ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) {
+ StructuredData::ObjectSP object_sp;
- if (m_gdb_comm.GetThreadExtendedInfoSupported())
- {
- StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
- SystemRuntime *runtime = GetSystemRuntime();
- if (runtime)
- {
- runtime->AddThreadExtendedInfoPacketHints (args_dict);
- }
- args_dict->GetAsDictionary()->AddIntegerItem ("thread", tid);
+ if (m_gdb_comm.GetThreadExtendedInfoSupported()) {
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+ SystemRuntime *runtime = GetSystemRuntime();
+ if (runtime) {
+ runtime->AddThreadExtendedInfoPacketHints(args_dict);
+ }
+ args_dict->GetAsDictionary()->AddIntegerItem("thread", tid);
- StreamString packet;
- packet << "jThreadExtendedInfo:";
- args_dict->Dump (packet, false);
-
- // FIXME the final character of a JSON dictionary, '}', is the escape
- // character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
- packet << (char) (0x7d ^ 0x20);
+ StreamString packet;
+ packet << "jThreadExtendedInfo:";
+ args_dict->Dump(packet, false);
- StringExtractorGDBRemote response;
- response.SetResponseValidatorToJSON();
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success)
- {
- StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType();
- if (response_type == StringExtractorGDBRemote::eResponse)
- {
- if (!response.Empty())
- {
- object_sp = StructuredData::ParseJSON (response.GetStringRef());
- }
- }
+ // FIXME the final character of a JSON dictionary, '}', is the escape
+ // character in gdb-remote binary mode. lldb currently doesn't escape
+ // these characters in its packet output -- so we add the quoted version
+ // of the } character here manually in case we talk to a debugserver which
+ // un-escapes the characters at packet read time.
+ packet << (char)(0x7d ^ 0x20);
+
+ StringExtractorGDBRemote response;
+ response.SetResponseValidatorToJSON();
+ if (m_gdb_comm.SendPacketAndWaitForResponse(
+ packet.GetData(), packet.GetSize(), response, false) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ StringExtractorGDBRemote::ResponseType response_type =
+ response.GetResponseType();
+ if (response_type == StringExtractorGDBRemote::eResponse) {
+ if (!response.Empty()) {
+ object_sp = StructuredData::ParseJSON(response.GetStringRef());
}
+ }
}
- return object_sp;
+ }
+ return object_sp;
}
-StructuredData::ObjectSP
-ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count)
-{
+StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos(
+ lldb::addr_t image_list_address, lldb::addr_t image_count) {
- StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
- args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address);
- args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count);
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+ args_dict->GetAsDictionary()->AddIntegerItem("image_list_address",
+ image_list_address);
+ args_dict->GetAsDictionary()->AddIntegerItem("image_count", image_count);
- return GetLoadedDynamicLibrariesInfos_sender (args_dict);
+ return GetLoadedDynamicLibrariesInfos_sender(args_dict);
}
-StructuredData::ObjectSP
-ProcessGDBRemote::GetLoadedDynamicLibrariesInfos ()
-{
- StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos() {
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
- args_dict->GetAsDictionary()->AddBooleanItem ("fetch_all_solibs", true);
+ args_dict->GetAsDictionary()->AddBooleanItem("fetch_all_solibs", true);
- return GetLoadedDynamicLibrariesInfos_sender (args_dict);
+ return GetLoadedDynamicLibrariesInfos_sender(args_dict);
}
-StructuredData::ObjectSP
-ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (const std::vector<lldb::addr_t> &load_addresses)
-{
- StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
- StructuredData::ArraySP addresses(new StructuredData::Array);
+StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos(
+ const std::vector<lldb::addr_t> &load_addresses) {
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+ StructuredData::ArraySP addresses(new StructuredData::Array);
- for (auto addr : load_addresses)
- {
- StructuredData::ObjectSP addr_sp (new StructuredData::Integer (addr));
- addresses->AddItem (addr_sp);
- }
+ for (auto addr : load_addresses) {
+ StructuredData::ObjectSP addr_sp(new StructuredData::Integer(addr));
+ addresses->AddItem(addr_sp);
+ }
- args_dict->GetAsDictionary()->AddItem ("solib_addresses", addresses);
+ args_dict->GetAsDictionary()->AddItem("solib_addresses", addresses);
- return GetLoadedDynamicLibrariesInfos_sender (args_dict);
+ return GetLoadedDynamicLibrariesInfos_sender(args_dict);
}
StructuredData::ObjectSP
-ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender (StructuredData::ObjectSP args_dict)
-{
- StructuredData::ObjectSP object_sp;
-
- if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported())
- {
- // Scope for the scoped timeout object
- GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10);
-
- StreamString packet;
- packet << "jGetLoadedDynamicLibrariesInfos:";
- args_dict->Dump (packet, false);
-
- // FIXME the final character of a JSON dictionary, '}', is the escape
- // character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
- packet << (char) (0x7d ^ 0x20);
-
- StringExtractorGDBRemote response;
- response.SetResponseValidatorToJSON();
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success)
- {
- StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType();
- if (response_type == StringExtractorGDBRemote::eResponse)
- {
- if (!response.Empty())
- {
- object_sp = StructuredData::ParseJSON (response.GetStringRef());
- }
- }
- }
- }
- return object_sp;
-}
-
+ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender(
+ StructuredData::ObjectSP args_dict) {
+ StructuredData::ObjectSP object_sp;
+
+ if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported()) {
+ // Scope for the scoped timeout object
+ GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, 10);
+ StreamString packet;
+ packet << "jGetLoadedDynamicLibrariesInfos:";
+ args_dict->Dump(packet, false);
+ // FIXME the final character of a JSON dictionary, '}', is the escape
+ // character in gdb-remote binary mode. lldb currently doesn't escape
+ // these characters in its packet output -- so we add the quoted version
+ // of the } character here manually in case we talk to a debugserver which
+ // un-escapes the characters at packet read time.
+ packet << (char)(0x7d ^ 0x20);
-StructuredData::ObjectSP
-ProcessGDBRemote::GetSharedCacheInfo ()
-{
- StructuredData::ObjectSP object_sp;
- StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+ StringExtractorGDBRemote response;
+ response.SetResponseValidatorToJSON();
+ if (m_gdb_comm.SendPacketAndWaitForResponse(
+ packet.GetData(), packet.GetSize(), response, false) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ StringExtractorGDBRemote::ResponseType response_type =
+ response.GetResponseType();
+ if (response_type == StringExtractorGDBRemote::eResponse) {
+ if (!response.Empty()) {
+ object_sp = StructuredData::ParseJSON(response.GetStringRef());
+ }
+ }
+ }
+ }
+ return object_sp;
+}
+
+StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() {
+ StructuredData::ObjectSP object_sp;
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
- if (m_gdb_comm.GetSharedCacheInfoSupported())
- {
- StreamString packet;
- packet << "jGetSharedCacheInfo:";
- args_dict->Dump (packet, false);
-
- // FIXME the final character of a JSON dictionary, '}', is the escape
- // character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
- packet << (char) (0x7d ^ 0x20);
+ if (m_gdb_comm.GetSharedCacheInfoSupported()) {
+ StreamString packet;
+ packet << "jGetSharedCacheInfo:";
+ args_dict->Dump(packet, false);
- StringExtractorGDBRemote response;
- response.SetResponseValidatorToJSON();
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success)
- {
- StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType();
- if (response_type == StringExtractorGDBRemote::eResponse)
- {
- if (!response.Empty())
- {
- object_sp = StructuredData::ParseJSON (response.GetStringRef());
- }
- }
- }
- }
- return object_sp;
-}
+ // FIXME the final character of a JSON dictionary, '}', is the escape
+ // character in gdb-remote binary mode. lldb currently doesn't escape
+ // these characters in its packet output -- so we add the quoted version
+ // of the } character here manually in case we talk to a debugserver which
+ // un-escapes the characters at packet read time.
+ packet << (char)(0x7d ^ 0x20);
-Error
-ProcessGDBRemote::ConfigureStructuredData(const ConstString &type_name,
- const StructuredData::ObjectSP
- &config_sp)
-{
- return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp);
+ StringExtractorGDBRemote response;
+ response.SetResponseValidatorToJSON();
+ if (m_gdb_comm.SendPacketAndWaitForResponse(
+ packet.GetData(), packet.GetSize(), response, false) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ StringExtractorGDBRemote::ResponseType response_type =
+ response.GetResponseType();
+ if (response_type == StringExtractorGDBRemote::eResponse) {
+ if (!response.Empty()) {
+ object_sp = StructuredData::ParseJSON(response.GetStringRef());
+ }
+ }
+ }
+ }
+ return object_sp;
+}
+
+Error ProcessGDBRemote::ConfigureStructuredData(
+ const ConstString &type_name, const StructuredData::ObjectSP &config_sp) {
+ return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp);
}
// Establish the largest memory read/write payloads we should use.
@@ -4334,100 +3971,82 @@ ProcessGDBRemote::ConfigureStructuredDat
// If the remote stub doesn't advertise a max packet size, use a
// conservative default.
-void
-ProcessGDBRemote::GetMaxMemorySize()
-{
- const uint64_t reasonable_largeish_default = 128 * 1024;
- const uint64_t conservative_default = 512;
-
- if (m_max_memory_size == 0)
- {
- uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize();
- if (stub_max_size != UINT64_MAX && stub_max_size != 0)
- {
- // Save the stub's claimed maximum packet size
- m_remote_stub_max_memory_size = stub_max_size;
-
- // Even if the stub says it can support ginormous packets,
- // don't exceed our reasonable largeish default packet size.
- if (stub_max_size > reasonable_largeish_default)
- {
- stub_max_size = reasonable_largeish_default;
- }
+void ProcessGDBRemote::GetMaxMemorySize() {
+ const uint64_t reasonable_largeish_default = 128 * 1024;
+ const uint64_t conservative_default = 512;
+
+ if (m_max_memory_size == 0) {
+ uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize();
+ if (stub_max_size != UINT64_MAX && stub_max_size != 0) {
+ // Save the stub's claimed maximum packet size
+ m_remote_stub_max_memory_size = stub_max_size;
+
+ // Even if the stub says it can support ginormous packets,
+ // don't exceed our reasonable largeish default packet size.
+ if (stub_max_size > reasonable_largeish_default) {
+ stub_max_size = reasonable_largeish_default;
+ }
- m_max_memory_size = stub_max_size;
- }
- else
- {
- m_max_memory_size = conservative_default;
- }
+ m_max_memory_size = stub_max_size;
+ } else {
+ m_max_memory_size = conservative_default;
}
+ }
}
-void
-ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max)
-{
- if (user_specified_max != 0)
- {
- GetMaxMemorySize ();
-
- if (m_remote_stub_max_memory_size != 0)
- {
- if (m_remote_stub_max_memory_size < user_specified_max)
- {
- m_max_memory_size = m_remote_stub_max_memory_size; // user specified a packet size too big, go as big
- // as the remote stub says we can go.
- }
- else
- {
- m_max_memory_size = user_specified_max; // user's packet size is good
- }
- }
- else
- {
- m_max_memory_size = user_specified_max; // user's packet size is probably fine
- }
+void ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize(
+ uint64_t user_specified_max) {
+ if (user_specified_max != 0) {
+ GetMaxMemorySize();
+
+ if (m_remote_stub_max_memory_size != 0) {
+ if (m_remote_stub_max_memory_size < user_specified_max) {
+ m_max_memory_size = m_remote_stub_max_memory_size; // user specified a
+ // packet size too
+ // big, go as big
+ // as the remote stub says we can go.
+ } else {
+ m_max_memory_size = user_specified_max; // user's packet size is good
+ }
+ } else {
+ m_max_memory_size =
+ user_specified_max; // user's packet size is probably fine
}
+ }
}
-bool
-ProcessGDBRemote::GetModuleSpec(const FileSpec& module_file_spec,
- const ArchSpec& arch,
- ModuleSpec &module_spec)
-{
- Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM);
-
- if (!m_gdb_comm.GetModuleInfo (module_file_spec, arch, module_spec))
- {
- if (log)
- log->Printf ("ProcessGDBRemote::%s - failed to get module info for %s:%s",
- __FUNCTION__, module_file_spec.GetPath ().c_str (),
- arch.GetTriple ().getTriple ().c_str ());
- return false;
- }
+bool ProcessGDBRemote::GetModuleSpec(const FileSpec &module_file_spec,
+ const ArchSpec &arch,
+ ModuleSpec &module_spec) {
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ if (!m_gdb_comm.GetModuleInfo(module_file_spec, arch, module_spec)) {
if (log)
- {
- StreamString stream;
- module_spec.Dump (stream);
- log->Printf ("ProcessGDBRemote::%s - got module info for (%s:%s) : %s",
- __FUNCTION__, module_file_spec.GetPath ().c_str (),
- arch.GetTriple ().getTriple ().c_str (), stream.GetString ().c_str ());
- }
+ log->Printf("ProcessGDBRemote::%s - failed to get module info for %s:%s",
+ __FUNCTION__, module_file_spec.GetPath().c_str(),
+ arch.GetTriple().getTriple().c_str());
+ return false;
+ }
+ if (log) {
+ StreamString stream;
+ module_spec.Dump(stream);
+ log->Printf("ProcessGDBRemote::%s - got module info for (%s:%s) : %s",
+ __FUNCTION__, module_file_spec.GetPath().c_str(),
+ arch.GetTriple().getTriple().c_str(),
+ stream.GetString().c_str());
+ }
+
+ return true;
+}
+
+bool ProcessGDBRemote::GetHostOSVersion(uint32_t &major, uint32_t &minor,
+ uint32_t &update) {
+ if (m_gdb_comm.GetOSVersion(major, minor, update))
return true;
-}
-
-bool
-ProcessGDBRemote::GetHostOSVersion(uint32_t &major,
- uint32_t &minor,
- uint32_t &update)
-{
- if (m_gdb_comm.GetOSVersion(major, minor, update))
- return true;
- // We failed to get the host OS version, defer to the base
- // implementation to correctly invalidate the arguments.
- return Process::GetHostOSVersion(major, minor, update);
+ // We failed to get the host OS version, defer to the base
+ // implementation to correctly invalidate the arguments.
+ return Process::GetHostOSVersion(major, minor, update);
}
namespace {
@@ -4435,29 +4054,29 @@ namespace {
typedef std::vector<std::string> stringVec;
typedef std::vector<struct GdbServerRegisterInfo> GDBServerRegisterVec;
-struct RegisterSetInfo
-{
- ConstString name;
+struct RegisterSetInfo {
+ ConstString name;
};
typedef std::map<uint32_t, RegisterSetInfo> RegisterSetMap;
-struct GdbServerTargetInfo
-{
- std::string arch;
- std::string osabi;
- stringVec includes;
- RegisterSetMap reg_set_map;
- XMLNode feature_node;
+struct GdbServerTargetInfo {
+ std::string arch;
+ std::string osabi;
+ stringVec includes;
+ RegisterSetMap reg_set_map;
+ XMLNode feature_node;
};
-bool
-ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp, uint32_t &cur_reg_num, uint32_t ®_offset)
-{
- if (!feature_node)
- return false;
+bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
+ GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp,
+ uint32_t &cur_reg_num, uint32_t ®_offset) {
+ if (!feature_node)
+ return false;
- feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, &abi_sp](const XMLNode ®_node) -> bool {
+ feature_node.ForEachChildElementWithName(
+ "reg", [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset,
+ &abi_sp](const XMLNode ®_node) -> bool {
std::string gdb_group;
std::string gdb_type;
ConstString reg_name;
@@ -4468,1076 +4087,1001 @@ ParseRegisters (XMLNode feature_node, Gd
std::vector<uint8_t> dwarf_opcode_bytes;
bool encoding_set = false;
bool format_set = false;
- RegisterInfo reg_info = { NULL, // Name
- NULL, // Alt name
- 0, // byte size
- reg_offset, // offset
- eEncodingUint, // encoding
- eFormatHex, // format
+ RegisterInfo reg_info = {
+ NULL, // Name
+ NULL, // Alt name
+ 0, // byte size
+ reg_offset, // offset
+ eEncodingUint, // encoding
+ eFormatHex, // format
{
LLDB_INVALID_REGNUM, // eh_frame reg num
LLDB_INVALID_REGNUM, // DWARF reg num
LLDB_INVALID_REGNUM, // generic reg num
- cur_reg_num, // process plugin reg num
- cur_reg_num // native register number
+ cur_reg_num, // process plugin reg num
+ cur_reg_num // native register number
},
NULL,
NULL,
- NULL, // Dwarf Expression opcode bytes pointer
- 0 // Dwarf Expression opcode bytes length
- };
-
- reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, &cur_reg_num, ®_offset, &dwarf_opcode_bytes](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
- if (name == "name")
- {
- reg_name.SetString(value);
- }
- else if (name == "bitsize")
- {
- reg_info.byte_size = StringConvert::ToUInt32(value.data(), 0, 0) / CHAR_BIT;
- }
- else if (name == "type")
- {
- gdb_type = value.str();
- }
- else if (name == "group")
- {
- gdb_group = value.str();
- }
- else if (name == "regnum")
- {
- const uint32_t regnum = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
- if (regnum != LLDB_INVALID_REGNUM)
- {
- reg_info.kinds[eRegisterKindProcessPlugin] = regnum;
- }
- }
- else if (name == "offset")
- {
- reg_offset = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
- }
- else if (name == "altname")
- {
- alt_name.SetString(value);
- }
- else if (name == "encoding")
- {
- encoding_set = true;
- reg_info.encoding = Args::StringToEncoding (value.data(), eEncodingUint);
- }
- else if (name == "format")
- {
- format_set = true;
- Format format = eFormatInvalid;
- if (Args::StringToFormat (value.data(), format, NULL).Success())
- reg_info.format = format;
- else if (value == "vector-sint8")
- reg_info.format = eFormatVectorOfSInt8;
- else if (value == "vector-uint8")
- reg_info.format = eFormatVectorOfUInt8;
- else if (value == "vector-sint16")
- reg_info.format = eFormatVectorOfSInt16;
- else if (value == "vector-uint16")
- reg_info.format = eFormatVectorOfUInt16;
- else if (value == "vector-sint32")
- reg_info.format = eFormatVectorOfSInt32;
- else if (value == "vector-uint32")
- reg_info.format = eFormatVectorOfUInt32;
- else if (value == "vector-float32")
- reg_info.format = eFormatVectorOfFloat32;
- else if (value == "vector-uint128")
- reg_info.format = eFormatVectorOfUInt128;
- }
- else if (name == "group_id")
- {
- const uint32_t set_id = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
- RegisterSetMap::const_iterator pos = target_info.reg_set_map.find(set_id);
- if (pos != target_info.reg_set_map.end())
- set_name = pos->second.name;
- }
- else if (name == "gcc_regnum" || name == "ehframe_regnum")
- {
- reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
- }
- else if (name == "dwarf_regnum")
- {
- reg_info.kinds[eRegisterKindDWARF] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
- }
- else if (name == "generic")
- {
- reg_info.kinds[eRegisterKindGeneric] = Args::StringToGenericRegister(value.data());
- }
- else if (name == "value_regnums")
- {
- SplitCommaSeparatedRegisterNumberString(value, value_regs, 0);
- }
- else if (name == "invalidate_regnums")
- {
- SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0);
- }
- else if (name == "dynamic_size_dwarf_expr_bytes")
- {
- StringExtractor opcode_extractor;
- std::string opcode_string = value.str ();
- size_t dwarf_opcode_len = opcode_string.length () / 2;
- assert (dwarf_opcode_len > 0);
-
- dwarf_opcode_bytes.resize (dwarf_opcode_len);
- reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;
- opcode_extractor.GetStringRef ().swap (opcode_string);
- uint32_t ret_val = opcode_extractor.GetHexBytesAvail (dwarf_opcode_bytes);
- assert (dwarf_opcode_len == ret_val);
-
- reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data ();
- }
- else
- {
- printf("unhandled attribute %s = %s\n", name.data(), value.data());
- }
- return true; // Keep iterating through all attributes
- });
-
- if (!gdb_type.empty() && !(encoding_set || format_set))
- {
- if (gdb_type.find("int") == 0)
- {
- reg_info.format = eFormatHex;
- reg_info.encoding = eEncodingUint;
- }
- else if (gdb_type == "data_ptr" || gdb_type == "code_ptr")
- {
- reg_info.format = eFormatAddressInfo;
- reg_info.encoding = eEncodingUint;
- }
- else if (gdb_type == "i387_ext" || gdb_type == "float")
- {
- reg_info.format = eFormatFloat;
- reg_info.encoding = eEncodingIEEE754;
- }
+ NULL, // Dwarf Expression opcode bytes pointer
+ 0 // Dwarf Expression opcode bytes length
+ };
+
+ reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type,
+ ®_name, &alt_name, &set_name, &value_regs,
+ &invalidate_regs, &encoding_set, &format_set,
+ ®_info, &cur_reg_num, ®_offset,
+ &dwarf_opcode_bytes](
+ const llvm::StringRef &name,
+ const llvm::StringRef &value) -> bool {
+ if (name == "name") {
+ reg_name.SetString(value);
+ } else if (name == "bitsize") {
+ reg_info.byte_size =
+ StringConvert::ToUInt32(value.data(), 0, 0) / CHAR_BIT;
+ } else if (name == "type") {
+ gdb_type = value.str();
+ } else if (name == "group") {
+ gdb_group = value.str();
+ } else if (name == "regnum") {
+ const uint32_t regnum =
+ StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
+ if (regnum != LLDB_INVALID_REGNUM) {
+ reg_info.kinds[eRegisterKindProcessPlugin] = regnum;
+ }
+ } else if (name == "offset") {
+ reg_offset = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
+ } else if (name == "altname") {
+ alt_name.SetString(value);
+ } else if (name == "encoding") {
+ encoding_set = true;
+ reg_info.encoding =
+ Args::StringToEncoding(value.data(), eEncodingUint);
+ } else if (name == "format") {
+ format_set = true;
+ Format format = eFormatInvalid;
+ if (Args::StringToFormat(value.data(), format, NULL).Success())
+ reg_info.format = format;
+ else if (value == "vector-sint8")
+ reg_info.format = eFormatVectorOfSInt8;
+ else if (value == "vector-uint8")
+ reg_info.format = eFormatVectorOfUInt8;
+ else if (value == "vector-sint16")
+ reg_info.format = eFormatVectorOfSInt16;
+ else if (value == "vector-uint16")
+ reg_info.format = eFormatVectorOfUInt16;
+ else if (value == "vector-sint32")
+ reg_info.format = eFormatVectorOfSInt32;
+ else if (value == "vector-uint32")
+ reg_info.format = eFormatVectorOfUInt32;
+ else if (value == "vector-float32")
+ reg_info.format = eFormatVectorOfFloat32;
+ else if (value == "vector-uint128")
+ reg_info.format = eFormatVectorOfUInt128;
+ } else if (name == "group_id") {
+ const uint32_t set_id =
+ StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
+ RegisterSetMap::const_iterator pos =
+ target_info.reg_set_map.find(set_id);
+ if (pos != target_info.reg_set_map.end())
+ set_name = pos->second.name;
+ } else if (name == "gcc_regnum" || name == "ehframe_regnum") {
+ reg_info.kinds[eRegisterKindEHFrame] =
+ StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
+ } else if (name == "dwarf_regnum") {
+ reg_info.kinds[eRegisterKindDWARF] =
+ StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
+ } else if (name == "generic") {
+ reg_info.kinds[eRegisterKindGeneric] =
+ Args::StringToGenericRegister(value.data());
+ } else if (name == "value_regnums") {
+ SplitCommaSeparatedRegisterNumberString(value, value_regs, 0);
+ } else if (name == "invalidate_regnums") {
+ SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0);
+ } else if (name == "dynamic_size_dwarf_expr_bytes") {
+ StringExtractor opcode_extractor;
+ std::string opcode_string = value.str();
+ size_t dwarf_opcode_len = opcode_string.length() / 2;
+ assert(dwarf_opcode_len > 0);
+
+ dwarf_opcode_bytes.resize(dwarf_opcode_len);
+ reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;
+ opcode_extractor.GetStringRef().swap(opcode_string);
+ uint32_t ret_val =
+ opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes);
+ assert(dwarf_opcode_len == ret_val);
+
+ reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data();
+ } else {
+ printf("unhandled attribute %s = %s\n", name.data(), value.data());
+ }
+ return true; // Keep iterating through all attributes
+ });
+
+ if (!gdb_type.empty() && !(encoding_set || format_set)) {
+ if (gdb_type.find("int") == 0) {
+ reg_info.format = eFormatHex;
+ reg_info.encoding = eEncodingUint;
+ } else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") {
+ reg_info.format = eFormatAddressInfo;
+ reg_info.encoding = eEncodingUint;
+ } else if (gdb_type == "i387_ext" || gdb_type == "float") {
+ reg_info.format = eFormatFloat;
+ reg_info.encoding = eEncodingIEEE754;
+ }
}
- // Only update the register set name if we didn't get a "reg_set" attribute.
+ // Only update the register set name if we didn't get a "reg_set"
+ // attribute.
// "set_name" will be empty if we didn't have a "reg_set" attribute.
if (!set_name && !gdb_group.empty())
- set_name.SetCString(gdb_group.c_str());
+ set_name.SetCString(gdb_group.c_str());
reg_info.byte_offset = reg_offset;
- assert (reg_info.byte_size != 0);
+ assert(reg_info.byte_size != 0);
reg_offset += reg_info.byte_size;
- if (!value_regs.empty())
- {
- value_regs.push_back(LLDB_INVALID_REGNUM);
- reg_info.value_regs = value_regs.data();
- }
- if (!invalidate_regs.empty())
- {
- invalidate_regs.push_back(LLDB_INVALID_REGNUM);
- reg_info.invalidate_regs = invalidate_regs.data();
+ if (!value_regs.empty()) {
+ value_regs.push_back(LLDB_INVALID_REGNUM);
+ reg_info.value_regs = value_regs.data();
+ }
+ if (!invalidate_regs.empty()) {
+ invalidate_regs.push_back(LLDB_INVALID_REGNUM);
+ reg_info.invalidate_regs = invalidate_regs.data();
}
++cur_reg_num;
- AugmentRegisterInfoViaABI (reg_info, reg_name, abi_sp);
+ AugmentRegisterInfoViaABI(reg_info, reg_name, abi_sp);
dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);
return true; // Keep iterating through all "reg" elements
- });
- return true;
+ });
+ return true;
}
} // namespace {}
-
// query the target of gdb-remote for extended target information
// return: 'true' on success
// 'false' on failure
-bool
-ProcessGDBRemote::GetGDBServerRegisterInfo (ArchSpec &arch_to_use)
-{
- // Make sure LLDB has an XML parser it can use first
- if (!XMLDocument::XMLEnabled())
- return false;
-
- // redirect libxml2's error handler since the default prints to stdout
-
- GDBRemoteCommunicationClient & comm = m_gdb_comm;
-
- // check that we have extended feature read support
- if ( !comm.GetQXferFeaturesReadSupported( ) )
- return false;
-
- // request the target xml file
- std::string raw;
- lldb_private::Error lldberr;
- if (!comm.ReadExtFeature(ConstString("features"),
- ConstString("target.xml"),
- raw,
- lldberr))
- {
- return false;
- }
-
-
- XMLDocument xml_document;
+bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
+ // Make sure LLDB has an XML parser it can use first
+ if (!XMLDocument::XMLEnabled())
+ return false;
- if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml"))
- {
- GdbServerTargetInfo target_info;
+ // redirect libxml2's error handler since the default prints to stdout
- XMLNode target_node = xml_document.GetRootElement("target");
- if (target_node)
- {
- XMLNode feature_node;
- target_node.ForEachChildElement([&target_info, this, &feature_node](const XMLNode &node) -> bool
- {
- llvm::StringRef name = node.GetName();
- if (name == "architecture")
- {
- node.GetElementText(target_info.arch);
- }
- else if (name == "osabi")
- {
- node.GetElementText(target_info.osabi);
- }
- else if (name == "xi:include" || name == "include")
- {
- llvm::StringRef href = node.GetAttributeValue("href");
- if (!href.empty())
- target_info.includes.push_back(href.str());
- }
- else if (name == "feature")
- {
- feature_node = node;
- }
- else if (name == "groups")
- {
- node.ForEachChildElementWithName("group", [&target_info](const XMLNode &node) -> bool {
- uint32_t set_id = UINT32_MAX;
- RegisterSetInfo set_info;
-
- node.ForEachAttribute([&set_id, &set_info](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
- if (name == "id")
- set_id = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
- if (name == "name")
- set_info.name = ConstString(value);
- return true; // Keep iterating through all attributes
- });
-
- if (set_id != UINT32_MAX)
- target_info.reg_set_map[set_id] = set_info;
- return true; // Keep iterating through all "group" elements
- });
- }
- return true; // Keep iterating through all children of the target_node
- });
+ GDBRemoteCommunicationClient &comm = m_gdb_comm;
- // Initialize these outside of ParseRegisters, since they should not be reset inside each include feature
- uint32_t cur_reg_num = 0;
- uint32_t reg_offset = 0;
-
- // Don't use Process::GetABI, this code gets called from DidAttach, and in that context we haven't
- // set the Target's architecture yet, so the ABI is also potentially incorrect.
- ABISP abi_to_use_sp = ABI::FindPlugin(arch_to_use);
- if (feature_node)
- {
- ParseRegisters(feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset);
- }
+ // check that we have extended feature read support
+ if (!comm.GetQXferFeaturesReadSupported())
+ return false;
- for (const auto &include : target_info.includes)
- {
- // request register file
- std::string xml_data;
- if (!comm.ReadExtFeature(ConstString("features"),
- ConstString(include),
- xml_data,
- lldberr))
- continue;
-
- XMLDocument include_xml_document;
- include_xml_document.ParseMemory(xml_data.data(), xml_data.size(), include.c_str());
- XMLNode include_feature_node = include_xml_document.GetRootElement("feature");
- if (include_feature_node)
- {
- ParseRegisters(include_feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset);
- }
- }
- this->m_register_info.Finalize(arch_to_use);
- }
- }
+ // request the target xml file
+ std::string raw;
+ lldb_private::Error lldberr;
+ if (!comm.ReadExtFeature(ConstString("features"), ConstString("target.xml"),
+ raw, lldberr)) {
+ return false;
+ }
- return m_register_info.GetNumRegisters() > 0;
-}
+ XMLDocument xml_document;
-Error
-ProcessGDBRemote::GetLoadedModuleList (LoadedModuleInfoList & list)
-{
- // Make sure LLDB has an XML parser it can use first
- if (!XMLDocument::XMLEnabled())
- return Error (0, ErrorType::eErrorTypeGeneric);
+ if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml")) {
+ GdbServerTargetInfo target_info;
- Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS);
- if (log)
- log->Printf ("ProcessGDBRemote::%s", __FUNCTION__);
+ XMLNode target_node = xml_document.GetRootElement("target");
+ if (target_node) {
+ XMLNode feature_node;
+ target_node.ForEachChildElement([&target_info, this, &feature_node](
+ const XMLNode &node) -> bool {
+ llvm::StringRef name = node.GetName();
+ if (name == "architecture") {
+ node.GetElementText(target_info.arch);
+ } else if (name == "osabi") {
+ node.GetElementText(target_info.osabi);
+ } else if (name == "xi:include" || name == "include") {
+ llvm::StringRef href = node.GetAttributeValue("href");
+ if (!href.empty())
+ target_info.includes.push_back(href.str());
+ } else if (name == "feature") {
+ feature_node = node;
+ } else if (name == "groups") {
+ node.ForEachChildElementWithName(
+ "group", [&target_info](const XMLNode &node) -> bool {
+ uint32_t set_id = UINT32_MAX;
+ RegisterSetInfo set_info;
+
+ node.ForEachAttribute(
+ [&set_id, &set_info](const llvm::StringRef &name,
+ const llvm::StringRef &value) -> bool {
+ if (name == "id")
+ set_id = StringConvert::ToUInt32(value.data(),
+ UINT32_MAX, 0);
+ if (name == "name")
+ set_info.name = ConstString(value);
+ return true; // Keep iterating through all attributes
+ });
- GDBRemoteCommunicationClient & comm = m_gdb_comm;
+ if (set_id != UINT32_MAX)
+ target_info.reg_set_map[set_id] = set_info;
+ return true; // Keep iterating through all "group" elements
+ });
+ }
+ return true; // Keep iterating through all children of the target_node
+ });
+
+ // Initialize these outside of ParseRegisters, since they should not be
+ // reset inside each include feature
+ uint32_t cur_reg_num = 0;
+ uint32_t reg_offset = 0;
+
+ // Don't use Process::GetABI, this code gets called from DidAttach, and in
+ // that context we haven't
+ // set the Target's architecture yet, so the ABI is also potentially
+ // incorrect.
+ ABISP abi_to_use_sp = ABI::FindPlugin(arch_to_use);
+ if (feature_node) {
+ ParseRegisters(feature_node, target_info, this->m_register_info,
+ abi_to_use_sp, cur_reg_num, reg_offset);
+ }
+
+ for (const auto &include : target_info.includes) {
+ // request register file
+ std::string xml_data;
+ if (!comm.ReadExtFeature(ConstString("features"), ConstString(include),
+ xml_data, lldberr))
+ continue;
+
+ XMLDocument include_xml_document;
+ include_xml_document.ParseMemory(xml_data.data(), xml_data.size(),
+ include.c_str());
+ XMLNode include_feature_node =
+ include_xml_document.GetRootElement("feature");
+ if (include_feature_node) {
+ ParseRegisters(include_feature_node, target_info,
+ this->m_register_info, abi_to_use_sp, cur_reg_num,
+ reg_offset);
+ }
+ }
+ this->m_register_info.Finalize(arch_to_use);
+ }
+ }
+
+ return m_register_info.GetNumRegisters() > 0;
+}
+
+Error ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) {
+ // Make sure LLDB has an XML parser it can use first
+ if (!XMLDocument::XMLEnabled())
+ return Error(0, ErrorType::eErrorTypeGeneric);
+
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS);
+ if (log)
+ log->Printf("ProcessGDBRemote::%s", __FUNCTION__);
+
+ GDBRemoteCommunicationClient &comm = m_gdb_comm;
+
+ // check that we have extended feature read support
+ if (comm.GetQXferLibrariesSVR4ReadSupported()) {
+ list.clear();
- // check that we have extended feature read support
- if (comm.GetQXferLibrariesSVR4ReadSupported ()) {
- list.clear ();
+ // request the loaded library list
+ std::string raw;
+ lldb_private::Error lldberr;
- // request the loaded library list
- std::string raw;
- lldb_private::Error lldberr;
+ if (!comm.ReadExtFeature(ConstString("libraries-svr4"), ConstString(""),
+ raw, lldberr))
+ return Error(0, ErrorType::eErrorTypeGeneric);
- if (!comm.ReadExtFeature (ConstString ("libraries-svr4"), ConstString (""), raw, lldberr))
- return Error (0, ErrorType::eErrorTypeGeneric);
+ // parse the xml file in memory
+ if (log)
+ log->Printf("parsing: %s", raw.c_str());
+ XMLDocument doc;
- // parse the xml file in memory
- if (log)
- log->Printf ("parsing: %s", raw.c_str());
- XMLDocument doc;
+ if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
+ return Error(0, ErrorType::eErrorTypeGeneric);
- if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
- return Error (0, ErrorType::eErrorTypeGeneric);
+ XMLNode root_element = doc.GetRootElement("library-list-svr4");
+ if (!root_element)
+ return Error();
- XMLNode root_element = doc.GetRootElement("library-list-svr4");
- if (!root_element)
- return Error();
-
- // main link map structure
- llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm");
- if (!main_lm.empty())
- {
- list.m_link_map = StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0);
- }
+ // main link map structure
+ llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm");
+ if (!main_lm.empty()) {
+ list.m_link_map =
+ StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0);
+ }
- root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
+ root_element.ForEachChildElementWithName(
+ "library", [log, &list](const XMLNode &library) -> bool {
- LoadedModuleInfoList::LoadedModuleInfo module;
+ LoadedModuleInfoList::LoadedModuleInfo module;
- library.ForEachAttribute([log, &module](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
+ library.ForEachAttribute(
+ [log, &module](const llvm::StringRef &name,
+ const llvm::StringRef &value) -> bool {
if (name == "name")
- module.set_name (value.str());
- else if (name == "lm")
- {
- // the address of the link_map struct.
- module.set_link_map(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
- }
- else if (name == "l_addr")
- {
- // the displacement as read from the field 'l_addr' of the link_map struct.
- module.set_base(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
- // base address is always a displacement, not an absolute value.
- module.set_base_is_offset(true);
- }
- else if (name == "l_ld")
- {
- // the memory address of the libraries PT_DYAMIC section.
- module.set_dynamic(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
+ module.set_name(value.str());
+ else if (name == "lm") {
+ // the address of the link_map struct.
+ module.set_link_map(StringConvert::ToUInt64(
+ value.data(), LLDB_INVALID_ADDRESS, 0));
+ } else if (name == "l_addr") {
+ // the displacement as read from the field 'l_addr' of the
+ // link_map struct.
+ module.set_base(StringConvert::ToUInt64(
+ value.data(), LLDB_INVALID_ADDRESS, 0));
+ // base address is always a displacement, not an absolute
+ // value.
+ module.set_base_is_offset(true);
+ } else if (name == "l_ld") {
+ // the memory address of the libraries PT_DYAMIC section.
+ module.set_dynamic(StringConvert::ToUInt64(
+ value.data(), LLDB_INVALID_ADDRESS, 0));
}
return true; // Keep iterating over all properties of "library"
- });
-
- if (log)
- {
- std::string name;
- lldb::addr_t lm=0, base=0, ld=0;
- bool base_is_offset;
-
- module.get_name (name);
- module.get_link_map (lm);
- module.get_base (base);
- module.get_base_is_offset (base_is_offset);
- module.get_dynamic (ld);
-
- log->Printf ("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 "[%s], ld:0x%08" PRIx64 ", name:'%s')", lm, base, (base_is_offset ? "offset" : "absolute"), ld, name.c_str());
- }
+ });
- list.add (module);
- return true; // Keep iterating over all "library" elements in the root node
+ if (log) {
+ std::string name;
+ lldb::addr_t lm = 0, base = 0, ld = 0;
+ bool base_is_offset;
+
+ module.get_name(name);
+ module.get_link_map(lm);
+ module.get_base(base);
+ module.get_base_is_offset(base_is_offset);
+ module.get_dynamic(ld);
+
+ log->Printf("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64
+ "[%s], ld:0x%08" PRIx64 ", name:'%s')",
+ lm, base, (base_is_offset ? "offset" : "absolute"), ld,
+ name.c_str());
+ }
+
+ list.add(module);
+ return true; // Keep iterating over all "library" elements in the root
+ // node
});
- if (log)
- log->Printf ("found %" PRId32 " modules in total", (int) list.m_list.size());
- } else if (comm.GetQXferLibrariesReadSupported ()) {
- list.clear ();
-
- // request the loaded library list
- std::string raw;
- lldb_private::Error lldberr;
-
- if (!comm.ReadExtFeature (ConstString ("libraries"), ConstString (""), raw, lldberr))
- return Error (0, ErrorType::eErrorTypeGeneric);
-
- if (log)
- log->Printf ("parsing: %s", raw.c_str());
- XMLDocument doc;
+ if (log)
+ log->Printf("found %" PRId32 " modules in total",
+ (int)list.m_list.size());
+ } else if (comm.GetQXferLibrariesReadSupported()) {
+ list.clear();
- if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
- return Error (0, ErrorType::eErrorTypeGeneric);
+ // request the loaded library list
+ std::string raw;
+ lldb_private::Error lldberr;
- XMLNode root_element = doc.GetRootElement("library-list");
- if (!root_element)
- return Error();
-
- root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
- LoadedModuleInfoList::LoadedModuleInfo module;
-
- llvm::StringRef name = library.GetAttributeValue("name");
- module.set_name(name.str());
-
- // The base address of a given library will be the address of its
- // first section. Most remotes send only one section for Windows
- // targets for example.
- const XMLNode §ion = library.FindFirstChildElementWithName("section");
- llvm::StringRef address = section.GetAttributeValue("address");
- module.set_base(StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0));
- // These addresses are absolute values.
- module.set_base_is_offset(false);
+ if (!comm.ReadExtFeature(ConstString("libraries"), ConstString(""), raw,
+ lldberr))
+ return Error(0, ErrorType::eErrorTypeGeneric);
- if (log)
- {
- std::string name;
- lldb::addr_t base = 0;
- bool base_is_offset;
- module.get_name (name);
- module.get_base (base);
- module.get_base_is_offset (base_is_offset);
+ if (log)
+ log->Printf("parsing: %s", raw.c_str());
+ XMLDocument doc;
- log->Printf ("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, (base_is_offset ? "offset" : "absolute"), name.c_str());
- }
+ if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
+ return Error(0, ErrorType::eErrorTypeGeneric);
- list.add (module);
- return true; // Keep iterating over all "library" elements in the root node
+ XMLNode root_element = doc.GetRootElement("library-list");
+ if (!root_element)
+ return Error();
+
+ root_element.ForEachChildElementWithName(
+ "library", [log, &list](const XMLNode &library) -> bool {
+ LoadedModuleInfoList::LoadedModuleInfo module;
+
+ llvm::StringRef name = library.GetAttributeValue("name");
+ module.set_name(name.str());
+
+ // The base address of a given library will be the address of its
+ // first section. Most remotes send only one section for Windows
+ // targets for example.
+ const XMLNode §ion =
+ library.FindFirstChildElementWithName("section");
+ llvm::StringRef address = section.GetAttributeValue("address");
+ module.set_base(
+ StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0));
+ // These addresses are absolute values.
+ module.set_base_is_offset(false);
+
+ if (log) {
+ std::string name;
+ lldb::addr_t base = 0;
+ bool base_is_offset;
+ module.get_name(name);
+ module.get_base(base);
+ module.get_base_is_offset(base_is_offset);
+
+ log->Printf("found (base:0x%08" PRIx64 "[%s], name:'%s')", base,
+ (base_is_offset ? "offset" : "absolute"), name.c_str());
+ }
+
+ list.add(module);
+ return true; // Keep iterating over all "library" elements in the root
+ // node
});
- if (log)
- log->Printf ("found %" PRId32 " modules in total", (int) list.m_list.size());
- } else {
- return Error (0, ErrorType::eErrorTypeGeneric);
- }
+ if (log)
+ log->Printf("found %" PRId32 " modules in total",
+ (int)list.m_list.size());
+ } else {
+ return Error(0, ErrorType::eErrorTypeGeneric);
+ }
- return Error();
+ return Error();
}
-lldb::ModuleSP
-ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t link_map,
- lldb::addr_t base_addr, bool value_is_offset)
-{
- DynamicLoader *loader = GetDynamicLoader();
- if (!loader)
- return nullptr;
+lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file,
+ lldb::addr_t link_map,
+ lldb::addr_t base_addr,
+ bool value_is_offset) {
+ DynamicLoader *loader = GetDynamicLoader();
+ if (!loader)
+ return nullptr;
- return loader->LoadModuleAtAddress(file, link_map, base_addr, value_is_offset);
+ return loader->LoadModuleAtAddress(file, link_map, base_addr,
+ value_is_offset);
}
-size_t
-ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list)
-{
- using lldb_private::process_gdb_remote::ProcessGDBRemote;
-
- // request a list of loaded libraries from GDBServer
- if (GetLoadedModuleList (module_list).Fail())
- return 0;
-
- // get a list of all the modules
- ModuleList new_modules;
-
- for (LoadedModuleInfoList::LoadedModuleInfo & modInfo : module_list.m_list)
- {
- std::string mod_name;
- lldb::addr_t mod_base;
- lldb::addr_t link_map;
- bool mod_base_is_offset;
-
- bool valid = true;
- valid &= modInfo.get_name (mod_name);
- valid &= modInfo.get_base (mod_base);
- valid &= modInfo.get_base_is_offset (mod_base_is_offset);
- if (!valid)
- continue;
-
- if (!modInfo.get_link_map (link_map))
- link_map = LLDB_INVALID_ADDRESS;
-
- FileSpec file (mod_name.c_str(), true);
- lldb::ModuleSP module_sp = LoadModuleAtAddress (file, link_map, mod_base,
- mod_base_is_offset);
-
- if (module_sp.get())
- new_modules.Append (module_sp);
- }
-
- if (new_modules.GetSize() > 0)
- {
- ModuleList removed_modules;
- Target &target = GetTarget();
- ModuleList &loaded_modules = m_process->GetTarget().GetImages();
+size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) {
+ using lldb_private::process_gdb_remote::ProcessGDBRemote;
- for (size_t i = 0; i < loaded_modules.GetSize(); ++i)
- {
- const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i);
+ // request a list of loaded libraries from GDBServer
+ if (GetLoadedModuleList(module_list).Fail())
+ return 0;
- bool found = false;
- for (size_t j = 0; j < new_modules.GetSize(); ++j)
- {
- if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get())
- found = true;
- }
+ // get a list of all the modules
+ ModuleList new_modules;
- // The main executable will never be included in libraries-svr4, don't remove it
- if (!found && loaded_module.get() != target.GetExecutableModulePointer())
- {
- removed_modules.Append (loaded_module);
- }
- }
+ for (LoadedModuleInfoList::LoadedModuleInfo &modInfo : module_list.m_list) {
+ std::string mod_name;
+ lldb::addr_t mod_base;
+ lldb::addr_t link_map;
+ bool mod_base_is_offset;
+
+ bool valid = true;
+ valid &= modInfo.get_name(mod_name);
+ valid &= modInfo.get_base(mod_base);
+ valid &= modInfo.get_base_is_offset(mod_base_is_offset);
+ if (!valid)
+ continue;
+
+ if (!modInfo.get_link_map(link_map))
+ link_map = LLDB_INVALID_ADDRESS;
+
+ FileSpec file(mod_name.c_str(), true);
+ lldb::ModuleSP module_sp =
+ LoadModuleAtAddress(file, link_map, mod_base, mod_base_is_offset);
+
+ if (module_sp.get())
+ new_modules.Append(module_sp);
+ }
+
+ if (new_modules.GetSize() > 0) {
+ ModuleList removed_modules;
+ Target &target = GetTarget();
+ ModuleList &loaded_modules = m_process->GetTarget().GetImages();
+
+ for (size_t i = 0; i < loaded_modules.GetSize(); ++i) {
+ const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i);
+
+ bool found = false;
+ for (size_t j = 0; j < new_modules.GetSize(); ++j) {
+ if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get())
+ found = true;
+ }
+
+ // The main executable will never be included in libraries-svr4, don't
+ // remove it
+ if (!found &&
+ loaded_module.get() != target.GetExecutableModulePointer()) {
+ removed_modules.Append(loaded_module);
+ }
+ }
+
+ loaded_modules.Remove(removed_modules);
+ m_process->GetTarget().ModulesDidUnload(removed_modules, false);
+
+ new_modules.ForEach([&target](const lldb::ModuleSP module_sp) -> bool {
+ lldb_private::ObjectFile *obj = module_sp->GetObjectFile();
+ if (!obj)
+ return true;
- loaded_modules.Remove (removed_modules);
- m_process->GetTarget().ModulesDidUnload (removed_modules, false);
+ if (obj->GetType() != ObjectFile::Type::eTypeExecutable)
+ return true;
- new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) -> bool
- {
- lldb_private::ObjectFile * obj = module_sp->GetObjectFile ();
- if (!obj)
- return true;
-
- if (obj->GetType () != ObjectFile::Type::eTypeExecutable)
- return true;
-
- lldb::ModuleSP module_copy_sp = module_sp;
- target.SetExecutableModule (module_copy_sp, false);
- return false;
- });
+ lldb::ModuleSP module_copy_sp = module_sp;
+ target.SetExecutableModule(module_copy_sp, false);
+ return false;
+ });
- loaded_modules.AppendIfNeeded (new_modules);
- m_process->GetTarget().ModulesDidLoad (new_modules);
- }
+ loaded_modules.AppendIfNeeded(new_modules);
+ m_process->GetTarget().ModulesDidLoad(new_modules);
+ }
- return new_modules.GetSize();
+ return new_modules.GetSize();
}
-size_t
-ProcessGDBRemote::LoadModules ()
-{
- LoadedModuleInfoList module_list;
- return LoadModules (module_list);
+size_t ProcessGDBRemote::LoadModules() {
+ LoadedModuleInfoList module_list;
+ return LoadModules(module_list);
}
-Error
-ProcessGDBRemote::GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr)
-{
- is_loaded = false;
- load_addr = LLDB_INVALID_ADDRESS;
-
- std::string file_path = file.GetPath(false);
- if (file_path.empty ())
- return Error("Empty file name specified");
+Error ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file,
+ bool &is_loaded,
+ lldb::addr_t &load_addr) {
+ is_loaded = false;
+ load_addr = LLDB_INVALID_ADDRESS;
- StreamString packet;
- packet.PutCString("qFileLoadAddress:");
- packet.PutCStringAsRawHex8(file_path.c_str());
+ std::string file_path = file.GetPath(false);
+ if (file_path.empty())
+ return Error("Empty file name specified");
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(), response, false) != GDBRemoteCommunication::PacketResult::Success)
- return Error("Sending qFileLoadAddress packet failed");
+ StreamString packet;
+ packet.PutCString("qFileLoadAddress:");
+ packet.PutCStringAsRawHex8(file_path.c_str());
- if (response.IsErrorResponse())
- {
- if (response.GetError() == 1)
- {
- // The file is not loaded into the inferior
- is_loaded = false;
- load_addr = LLDB_INVALID_ADDRESS;
- return Error();
- }
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
+ response, false) !=
+ GDBRemoteCommunication::PacketResult::Success)
+ return Error("Sending qFileLoadAddress packet failed");
- return Error("Fetching file load address from remote server returned an error");
+ if (response.IsErrorResponse()) {
+ if (response.GetError() == 1) {
+ // The file is not loaded into the inferior
+ is_loaded = false;
+ load_addr = LLDB_INVALID_ADDRESS;
+ return Error();
}
- if (response.IsNormalResponse())
- {
- is_loaded = true;
- load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
- return Error();
- }
+ return Error(
+ "Fetching file load address from remote server returned an error");
+ }
- return Error("Unknown error happened during sending the load address packet");
-}
+ if (response.IsNormalResponse()) {
+ is_loaded = true;
+ load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
+ return Error();
+ }
+ return Error("Unknown error happened during sending the load address packet");
+}
-void
-ProcessGDBRemote::ModulesDidLoad (ModuleList &module_list)
-{
- // We must call the lldb_private::Process::ModulesDidLoad () first before we do anything
- Process::ModulesDidLoad (module_list);
+void ProcessGDBRemote::ModulesDidLoad(ModuleList &module_list) {
+ // We must call the lldb_private::Process::ModulesDidLoad () first before we
+ // do anything
+ Process::ModulesDidLoad(module_list);
- // After loading shared libraries, we can ask our remote GDB server if
- // it needs any symbols.
- m_gdb_comm.ServeSymbolLookups(this);
+ // After loading shared libraries, we can ask our remote GDB server if
+ // it needs any symbols.
+ m_gdb_comm.ServeSymbolLookups(this);
}
-void
-ProcessGDBRemote::HandleAsyncStdout(llvm::StringRef out)
-{
- AppendSTDOUT(out.data(), out.size());
+void ProcessGDBRemote::HandleAsyncStdout(llvm::StringRef out) {
+ AppendSTDOUT(out.data(), out.size());
}
static const char *end_delimiter = "--end--;";
static const int end_delimiter_len = 8;
-void
-ProcessGDBRemote::HandleAsyncMisc(llvm::StringRef data)
-{
- std::string input = data.str(); // '1' to move beyond 'A'
- if (m_partial_profile_data.length() > 0)
- {
- m_partial_profile_data.append(input);
- input = m_partial_profile_data;
- m_partial_profile_data.clear();
- }
-
- size_t found, pos = 0, len = input.length();
- while ((found = input.find(end_delimiter, pos)) != std::string::npos)
- {
- StringExtractorGDBRemote profileDataExtractor(input.substr(pos, found).c_str());
- std::string profile_data = HarmonizeThreadIdsForProfileData(profileDataExtractor);
- BroadcastAsyncProfileData(profile_data);
-
- pos = found + end_delimiter_len;
- }
-
- if (pos < len)
- {
- // Last incomplete chunk.
- m_partial_profile_data = input.substr(pos);
- }
-}
-
-std::string
-ProcessGDBRemote::HarmonizeThreadIdsForProfileData(StringExtractorGDBRemote &profileDataExtractor)
-{
- std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map;
- std::string output;
- llvm::raw_string_ostream output_stream(output);
- llvm::StringRef name, value;
-
- // Going to assuming thread_used_usec comes first, else bail out.
- while (profileDataExtractor.GetNameColonValue(name, value))
- {
- if (name.compare("thread_used_id") == 0)
- {
- StringExtractor threadIDHexExtractor(value);
- uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0);
-
- bool has_used_usec = false;
- uint32_t curr_used_usec = 0;
- llvm::StringRef usec_name, usec_value;
- uint32_t input_file_pos = profileDataExtractor.GetFilePos();
- if (profileDataExtractor.GetNameColonValue(usec_name, usec_value))
- {
- if (usec_name.equals("thread_used_usec"))
- {
- has_used_usec = true;
- usec_value.getAsInteger(0, curr_used_usec);
- }
- else
- {
- // We didn't find what we want, it is probably
- // an older version. Bail out.
- profileDataExtractor.SetFilePos(input_file_pos);
- }
- }
-
- if (has_used_usec)
- {
- uint32_t prev_used_usec = 0;
- std::map<uint64_t, uint32_t>::iterator iterator = m_thread_id_to_used_usec_map.find(thread_id);
- if (iterator != m_thread_id_to_used_usec_map.end())
- {
- prev_used_usec = m_thread_id_to_used_usec_map[thread_id];
- }
-
- uint32_t real_used_usec = curr_used_usec - prev_used_usec;
- // A good first time record is one that runs for at least 0.25 sec
- bool good_first_time = (prev_used_usec == 0) && (real_used_usec > 250000);
- bool good_subsequent_time =
- (prev_used_usec > 0) && ((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id)));
-
- if (good_first_time || good_subsequent_time)
- {
- // We try to avoid doing too many index id reservation,
- // resulting in fast increase of index ids.
-
- output_stream << name << ":";
- int32_t index_id = AssignIndexIDToThread(thread_id);
- output_stream << index_id << ";";
-
- output_stream << usec_name << ":" << usec_value << ";";
- }
- else
- {
- // Skip past 'thread_used_name'.
- llvm::StringRef local_name, local_value;
- profileDataExtractor.GetNameColonValue(local_name, local_value);
- }
-
- // Store current time as previous time so that they can be compared later.
- new_thread_id_to_used_usec_map[thread_id] = curr_used_usec;
- }
- else
- {
- // Bail out and use old string.
- output_stream << name << ":" << value << ";";
- }
- }
- else
- {
- output_stream << name << ":" << value << ";";
- }
+void ProcessGDBRemote::HandleAsyncMisc(llvm::StringRef data) {
+ std::string input = data.str(); // '1' to move beyond 'A'
+ if (m_partial_profile_data.length() > 0) {
+ m_partial_profile_data.append(input);
+ input = m_partial_profile_data;
+ m_partial_profile_data.clear();
+ }
+
+ size_t found, pos = 0, len = input.length();
+ while ((found = input.find(end_delimiter, pos)) != std::string::npos) {
+ StringExtractorGDBRemote profileDataExtractor(
+ input.substr(pos, found).c_str());
+ std::string profile_data =
+ HarmonizeThreadIdsForProfileData(profileDataExtractor);
+ BroadcastAsyncProfileData(profile_data);
+
+ pos = found + end_delimiter_len;
+ }
+
+ if (pos < len) {
+ // Last incomplete chunk.
+ m_partial_profile_data = input.substr(pos);
+ }
+}
+
+std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData(
+ StringExtractorGDBRemote &profileDataExtractor) {
+ std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map;
+ std::string output;
+ llvm::raw_string_ostream output_stream(output);
+ llvm::StringRef name, value;
+
+ // Going to assuming thread_used_usec comes first, else bail out.
+ while (profileDataExtractor.GetNameColonValue(name, value)) {
+ if (name.compare("thread_used_id") == 0) {
+ StringExtractor threadIDHexExtractor(value);
+ uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0);
+
+ bool has_used_usec = false;
+ uint32_t curr_used_usec = 0;
+ llvm::StringRef usec_name, usec_value;
+ uint32_t input_file_pos = profileDataExtractor.GetFilePos();
+ if (profileDataExtractor.GetNameColonValue(usec_name, usec_value)) {
+ if (usec_name.equals("thread_used_usec")) {
+ has_used_usec = true;
+ usec_value.getAsInteger(0, curr_used_usec);
+ } else {
+ // We didn't find what we want, it is probably
+ // an older version. Bail out.
+ profileDataExtractor.SetFilePos(input_file_pos);
+ }
+ }
+
+ if (has_used_usec) {
+ uint32_t prev_used_usec = 0;
+ std::map<uint64_t, uint32_t>::iterator iterator =
+ m_thread_id_to_used_usec_map.find(thread_id);
+ if (iterator != m_thread_id_to_used_usec_map.end()) {
+ prev_used_usec = m_thread_id_to_used_usec_map[thread_id];
+ }
+
+ uint32_t real_used_usec = curr_used_usec - prev_used_usec;
+ // A good first time record is one that runs for at least 0.25 sec
+ bool good_first_time =
+ (prev_used_usec == 0) && (real_used_usec > 250000);
+ bool good_subsequent_time =
+ (prev_used_usec > 0) &&
+ ((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id)));
+
+ if (good_first_time || good_subsequent_time) {
+ // We try to avoid doing too many index id reservation,
+ // resulting in fast increase of index ids.
+
+ output_stream << name << ":";
+ int32_t index_id = AssignIndexIDToThread(thread_id);
+ output_stream << index_id << ";";
+
+ output_stream << usec_name << ":" << usec_value << ";";
+ } else {
+ // Skip past 'thread_used_name'.
+ llvm::StringRef local_name, local_value;
+ profileDataExtractor.GetNameColonValue(local_name, local_value);
+ }
+
+ // Store current time as previous time so that they can be compared
+ // later.
+ new_thread_id_to_used_usec_map[thread_id] = curr_used_usec;
+ } else {
+ // Bail out and use old string.
+ output_stream << name << ":" << value << ";";
+ }
+ } else {
+ output_stream << name << ":" << value << ";";
}
- output_stream << end_delimiter;
- m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map;
+ }
+ output_stream << end_delimiter;
+ m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map;
- return output_stream.str();
+ return output_stream.str();
}
-void
-ProcessGDBRemote::HandleStopReply()
-{
- if (GetStopID() != 0)
- return;
+void ProcessGDBRemote::HandleStopReply() {
+ if (GetStopID() != 0)
+ return;
- if (GetID() == LLDB_INVALID_PROCESS_ID)
- {
- lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
- if (pid != LLDB_INVALID_PROCESS_ID)
- SetID(pid);
- }
- BuildDynamicRegisterInfo(true);
+ if (GetID() == LLDB_INVALID_PROCESS_ID) {
+ lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ SetID(pid);
+ }
+ BuildDynamicRegisterInfo(true);
}
-bool
-ProcessGDBRemote::HandleAsyncStructuredData(const StructuredData::ObjectSP
- &object_sp)
-{
- return RouteAsyncStructuredData(object_sp);
+bool ProcessGDBRemote::HandleAsyncStructuredData(
+ const StructuredData::ObjectSP &object_sp) {
+ return RouteAsyncStructuredData(object_sp);
}
-class CommandObjectProcessGDBRemoteSpeedTest: public CommandObjectParsed
-{
+class CommandObjectProcessGDBRemoteSpeedTest : public CommandObjectParsed {
public:
- CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "process plugin packet speed-test",
- "Tests packet speeds of various sizes to determine the performance characteristics of the GDB remote connection. ",
- NULL),
- m_option_group (),
- m_num_packets (LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount, "The number of packets to send of each varying size (default is 1000).", 1000),
- m_max_send (LLDB_OPT_SET_1, false, "max-send", 's', 0, eArgTypeCount, "The maximum number of bytes to send in a packet. Sizes increase in powers of 2 while the size is less than or equal to this option value. (default 1024).", 1024),
- m_max_recv (LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount, "The maximum number of bytes to receive in a packet. Sizes increase in powers of 2 while the size is less than or equal to this option value. (default 1024).", 1024),
- m_json (LLDB_OPT_SET_1, false, "json", 'j', "Print the output as JSON data for easy parsing.", false, true)
- {
- m_option_group.Append (&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
- m_option_group.Append (&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
- m_option_group.Append (&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
- m_option_group.Append (&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
- m_option_group.Finalize();
- }
-
- ~CommandObjectProcessGDBRemoteSpeedTest ()
- {
- }
-
-
- Options *
- GetOptions () override
- {
- return &m_option_group;
- }
-
- bool
- DoExecute (Args& command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc == 0)
- {
- ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process)
- {
- StreamSP output_stream_sp (m_interpreter.GetDebugger().GetAsyncOutputStream());
- result.SetImmediateOutputStream (output_stream_sp);
-
- const uint32_t num_packets = (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue();
- const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue();
- const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue();
- const bool json = m_json.GetOptionValue().GetCurrentValue();
- if (output_stream_sp)
- process->GetGDBRemote().TestPacketSpeed (num_packets, max_send, max_recv, json, *output_stream_sp);
- else
- {
- process->GetGDBRemote().TestPacketSpeed (num_packets, max_send, max_recv, json, result.GetOutputStream());
- }
- result.SetStatus (eReturnStatusSuccessFinishResult);
- return true;
- }
- }
- else
- {
- result.AppendErrorWithFormat ("'%s' takes no arguments", m_cmd_name.c_str());
+ CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process plugin packet speed-test",
+ "Tests packet speeds of various sizes to determine "
+ "the performance characteristics of the GDB remote "
+ "connection. ",
+ NULL),
+ m_option_group(),
+ m_num_packets(LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount,
+ "The number of packets to send of each varying size "
+ "(default is 1000).",
+ 1000),
+ m_max_send(LLDB_OPT_SET_1, false, "max-send", 's', 0, eArgTypeCount,
+ "The maximum number of bytes to send in a packet. Sizes "
+ "increase in powers of 2 while the size is less than or "
+ "equal to this option value. (default 1024).",
+ 1024),
+ m_max_recv(LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount,
+ "The maximum number of bytes to receive in a packet. Sizes "
+ "increase in powers of 2 while the size is less than or "
+ "equal to this option value. (default 1024).",
+ 1024),
+ m_json(LLDB_OPT_SET_1, false, "json", 'j',
+ "Print the output as JSON data for easy parsing.", false, true) {
+ m_option_group.Append(&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Append(&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Append(&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Append(&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Finalize();
+ }
+
+ ~CommandObjectProcessGDBRemoteSpeedTest() {}
+
+ Options *GetOptions() override { return &m_option_group; }
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0) {
+ ProcessGDBRemote *process =
+ (ProcessGDBRemote *)m_interpreter.GetExecutionContext()
+ .GetProcessPtr();
+ if (process) {
+ StreamSP output_stream_sp(
+ m_interpreter.GetDebugger().GetAsyncOutputStream());
+ result.SetImmediateOutputStream(output_stream_sp);
+
+ const uint32_t num_packets =
+ (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue();
+ const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue();
+ const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue();
+ const bool json = m_json.GetOptionValue().GetCurrentValue();
+ if (output_stream_sp)
+ process->GetGDBRemote().TestPacketSpeed(
+ num_packets, max_send, max_recv, json, *output_stream_sp);
+ else {
+ process->GetGDBRemote().TestPacketSpeed(
+ num_packets, max_send, max_recv, json, result.GetOutputStream());
}
- result.SetStatus (eReturnStatusFailed);
- return false;
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ } else {
+ result.AppendErrorWithFormat("'%s' takes no arguments",
+ m_cmd_name.c_str());
}
-protected:
- OptionGroupOptions m_option_group;
- OptionGroupUInt64 m_num_packets;
- OptionGroupUInt64 m_max_send;
- OptionGroupUInt64 m_max_recv;
- OptionGroupBoolean m_json;
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+protected:
+ OptionGroupOptions m_option_group;
+ OptionGroupUInt64 m_num_packets;
+ OptionGroupUInt64 m_max_send;
+ OptionGroupUInt64 m_max_recv;
+ OptionGroupBoolean m_json;
};
-class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed
-{
+class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed {
private:
-
public:
- CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "process plugin packet history",
- "Dumps the packet history buffer. ",
- NULL)
- {
- }
-
- ~CommandObjectProcessGDBRemotePacketHistory ()
- {
- }
-
- bool
- DoExecute (Args& command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc == 0)
- {
- ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process)
- {
- process->GetGDBRemote().DumpHistory(result.GetOutputStream());
- result.SetStatus (eReturnStatusSuccessFinishResult);
- return true;
- }
- }
- else
- {
- result.AppendErrorWithFormat ("'%s' takes no arguments", m_cmd_name.c_str());
- }
- result.SetStatus (eReturnStatusFailed);
- return false;
+ CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process plugin packet history",
+ "Dumps the packet history buffer. ", NULL) {}
+
+ ~CommandObjectProcessGDBRemotePacketHistory() {}
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0) {
+ ProcessGDBRemote *process =
+ (ProcessGDBRemote *)m_interpreter.GetExecutionContext()
+ .GetProcessPtr();
+ if (process) {
+ process->GetGDBRemote().DumpHistory(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ } else {
+ result.AppendErrorWithFormat("'%s' takes no arguments",
+ m_cmd_name.c_str());
}
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
};
-class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed
-{
+class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed {
private:
-
public:
- CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "process plugin packet xfer-size",
- "Maximum size that lldb will try to read/write one one chunk.",
- NULL)
- {
- }
-
- ~CommandObjectProcessGDBRemotePacketXferSize ()
- {
- }
-
- bool
- DoExecute (Args& command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc == 0)
- {
- result.AppendErrorWithFormat ("'%s' takes an argument to specify the max amount to be transferred when reading/writing", m_cmd_name.c_str());
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process)
- {
- const char *packet_size = command.GetArgumentAtIndex(0);
- errno = 0;
- uint64_t user_specified_max = strtoul (packet_size, NULL, 10);
- if (errno == 0 && user_specified_max != 0)
- {
- process->SetUserSpecifiedMaxMemoryTransferSize (user_specified_max);
- result.SetStatus (eReturnStatusSuccessFinishResult);
- return true;
- }
- }
- result.SetStatus (eReturnStatusFailed);
- return false;
+ CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "process plugin packet xfer-size",
+ "Maximum size that lldb will try to read/write one one chunk.",
+ NULL) {}
+
+ ~CommandObjectProcessGDBRemotePacketXferSize() {}
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0) {
+ result.AppendErrorWithFormat("'%s' takes an argument to specify the max "
+ "amount to be transferred when "
+ "reading/writing",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ ProcessGDBRemote *process =
+ (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
+ if (process) {
+ const char *packet_size = command.GetArgumentAtIndex(0);
+ errno = 0;
+ uint64_t user_specified_max = strtoul(packet_size, NULL, 10);
+ if (errno == 0 && user_specified_max != 0) {
+ process->SetUserSpecifiedMaxMemoryTransferSize(user_specified_max);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
}
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
};
-
-class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed
-{
+class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed {
private:
-
public:
- CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "process plugin packet send",
- "Send a custom packet through the GDB remote protocol and print the answer. "
- "The packet header and footer will automatically be added to the packet prior to sending and stripped from the result.",
- NULL)
- {
- }
-
- ~CommandObjectProcessGDBRemotePacketSend ()
- {
- }
+ CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process plugin packet send",
+ "Send a custom packet through the GDB remote "
+ "protocol and print the answer. "
+ "The packet header and footer will automatically "
+ "be added to the packet prior to sending and "
+ "stripped from the result.",
+ NULL) {}
+
+ ~CommandObjectProcessGDBRemotePacketSend() {}
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0) {
+ result.AppendErrorWithFormat(
+ "'%s' takes a one or more packet content arguments",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ ProcessGDBRemote *process =
+ (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
+ if (process) {
+ for (size_t i = 0; i < argc; ++i) {
+ const char *packet_cstr = command.GetArgumentAtIndex(0);
+ bool send_async = true;
+ StringExtractorGDBRemote response;
+ process->GetGDBRemote().SendPacketAndWaitForResponse(
+ packet_cstr, response, send_async);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ Stream &output_strm = result.GetOutputStream();
+ output_strm.Printf(" packet: %s\n", packet_cstr);
+ std::string &response_str = response.GetStringRef();
- bool
- DoExecute (Args& command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc == 0)
- {
- result.AppendErrorWithFormat ("'%s' takes a one or more packet content arguments", m_cmd_name.c_str());
- result.SetStatus (eReturnStatusFailed);
- return false;
+ if (strstr(packet_cstr, "qGetProfileData") != NULL) {
+ response_str = process->HarmonizeThreadIdsForProfileData(response);
}
- ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process)
- {
- for (size_t i=0; i<argc; ++ i)
- {
- const char *packet_cstr = command.GetArgumentAtIndex(0);
- bool send_async = true;
- StringExtractorGDBRemote response;
- process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async);
- result.SetStatus (eReturnStatusSuccessFinishResult);
- Stream &output_strm = result.GetOutputStream();
- output_strm.Printf (" packet: %s\n", packet_cstr);
- std::string &response_str = response.GetStringRef();
-
- if (strstr(packet_cstr, "qGetProfileData") != NULL)
- {
- response_str = process->HarmonizeThreadIdsForProfileData(response);
- }
-
- if (response_str.empty())
- output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n");
- else
- output_strm.Printf ("response: %s\n", response.GetStringRef().c_str());
- }
- }
- return true;
+ if (response_str.empty())
+ output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n");
+ else
+ output_strm.Printf("response: %s\n", response.GetStringRef().c_str());
+ }
}
+ return true;
+ }
};
-class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw
-{
+class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw {
private:
-
public:
- CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter) :
- CommandObjectRaw (interpreter,
- "process plugin packet monitor",
- "Send a qRcmd packet through the GDB remote protocol and print the response."
- "The argument passed to this command will be hex encoded into a valid 'qRcmd' packet, sent and the response will be printed.",
- NULL)
- {
- }
-
- ~CommandObjectProcessGDBRemotePacketMonitor ()
- {
- }
-
- bool
- DoExecute (const char *command, CommandReturnObject &result) override
- {
- if (command == NULL || command[0] == '\0')
- {
- result.AppendErrorWithFormat ("'%s' takes a command string argument", m_cmd_name.c_str());
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process)
- {
- StreamString packet;
- packet.PutCString("qRcmd,");
- packet.PutBytesAsRawHex8(command, strlen(command));
- const char *packet_cstr = packet.GetString().c_str();
-
- bool send_async = true;
- StringExtractorGDBRemote response;
- process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async);
- result.SetStatus (eReturnStatusSuccessFinishResult);
- Stream &output_strm = result.GetOutputStream();
- output_strm.Printf (" packet: %s\n", packet_cstr);
- const std::string &response_str = response.GetStringRef();
-
- if (response_str.empty())
- output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n");
- else
- output_strm.Printf ("response: %s\n", response.GetStringRef().c_str());
- }
- return true;
+ CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter)
+ : CommandObjectRaw(interpreter, "process plugin packet monitor",
+ "Send a qRcmd packet through the GDB remote protocol "
+ "and print the response."
+ "The argument passed to this command will be hex "
+ "encoded into a valid 'qRcmd' packet, sent and the "
+ "response will be printed.",
+ NULL) {}
+
+ ~CommandObjectProcessGDBRemotePacketMonitor() {}
+
+ bool DoExecute(const char *command, CommandReturnObject &result) override {
+ if (command == NULL || command[0] == '\0') {
+ result.AppendErrorWithFormat("'%s' takes a command string argument",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ ProcessGDBRemote *process =
+ (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
+ if (process) {
+ StreamString packet;
+ packet.PutCString("qRcmd,");
+ packet.PutBytesAsRawHex8(command, strlen(command));
+ const char *packet_cstr = packet.GetString().c_str();
+
+ bool send_async = true;
+ StringExtractorGDBRemote response;
+ process->GetGDBRemote().SendPacketAndWaitForResponse(
+ packet_cstr, response, send_async);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ Stream &output_strm = result.GetOutputStream();
+ output_strm.Printf(" packet: %s\n", packet_cstr);
+ const std::string &response_str = response.GetStringRef();
+
+ if (response_str.empty())
+ output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n");
+ else
+ output_strm.Printf("response: %s\n", response.GetStringRef().c_str());
}
+ return true;
+ }
};
-class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword
-{
+class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword {
private:
-
public:
- CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) :
- CommandObjectMultiword (interpreter,
- "process plugin packet",
- "Commands that deal with GDB remote packets.",
- NULL)
- {
- LoadSubCommand ("history", CommandObjectSP (new CommandObjectProcessGDBRemotePacketHistory (interpreter)));
- LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessGDBRemotePacketSend (interpreter)));
- LoadSubCommand ("monitor", CommandObjectSP (new CommandObjectProcessGDBRemotePacketMonitor (interpreter)));
- LoadSubCommand ("xfer-size", CommandObjectSP (new CommandObjectProcessGDBRemotePacketXferSize (interpreter)));
- LoadSubCommand ("speed-test", CommandObjectSP (new CommandObjectProcessGDBRemoteSpeedTest (interpreter)));
- }
+ CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "process plugin packet",
+ "Commands that deal with GDB remote packets.",
+ NULL) {
+ LoadSubCommand(
+ "history",
+ CommandObjectSP(
+ new CommandObjectProcessGDBRemotePacketHistory(interpreter)));
+ LoadSubCommand(
+ "send", CommandObjectSP(
+ new CommandObjectProcessGDBRemotePacketSend(interpreter)));
+ LoadSubCommand(
+ "monitor",
+ CommandObjectSP(
+ new CommandObjectProcessGDBRemotePacketMonitor(interpreter)));
+ LoadSubCommand(
+ "xfer-size",
+ CommandObjectSP(
+ new CommandObjectProcessGDBRemotePacketXferSize(interpreter)));
+ LoadSubCommand("speed-test",
+ CommandObjectSP(new CommandObjectProcessGDBRemoteSpeedTest(
+ interpreter)));
+ }
- ~CommandObjectProcessGDBRemotePacket ()
- {
- }
+ ~CommandObjectProcessGDBRemotePacket() {}
};
-class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword
-{
+class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword {
public:
- CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "process plugin", "Commands for operating on a ProcessGDBRemote process.",
- "process plugin <subcommand> [<subcommand-options>]")
- {
- LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessGDBRemotePacket (interpreter)));
- }
+ CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "process plugin",
+ "Commands for operating on a ProcessGDBRemote process.",
+ "process plugin <subcommand> [<subcommand-options>]") {
+ LoadSubCommand(
+ "packet",
+ CommandObjectSP(new CommandObjectProcessGDBRemotePacket(interpreter)));
+ }
- ~CommandObjectMultiwordProcessGDBRemote ()
- {
- }
+ ~CommandObjectMultiwordProcessGDBRemote() {}
};
-CommandObject *
-ProcessGDBRemote::GetPluginCommandObject()
-{
- if (!m_command_sp)
- m_command_sp.reset (new CommandObjectMultiwordProcessGDBRemote (GetTarget().GetDebugger().GetCommandInterpreter()));
- return m_command_sp.get();
+CommandObject *ProcessGDBRemote::GetPluginCommandObject() {
+ if (!m_command_sp)
+ m_command_sp.reset(new CommandObjectMultiwordProcessGDBRemote(
+ GetTarget().GetDebugger().GetCommandInterpreter()));
+ return m_command_sp.get();
}
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Tue Sep 6 15:57:50 2016
@@ -24,16 +24,16 @@
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
+#include "lldb/Core/LoadedModuleInfoList.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/StringList.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/ThreadSafeValue.h"
-#include "lldb/Core/LoadedModuleInfoList.h"
#include "lldb/Host/HostThread.h"
-#include "lldb/lldb-private-forward.h"
-#include "lldb/Utility/StringExtractor.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/StringExtractor.h"
+#include "lldb/lldb-private-forward.h"
#include "GDBRemoteCommunicationClient.h"
#include "GDBRemoteRegisterContext.h"
@@ -43,478 +43,376 @@ namespace process_gdb_remote {
class ThreadGDBRemote;
-class ProcessGDBRemote : public Process, private GDBRemoteClientBase::ContinueDelegate
-{
+class ProcessGDBRemote : public Process,
+ private GDBRemoteClientBase::ContinueDelegate {
public:
- ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
+ ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
+
+ ~ProcessGDBRemote() override;
+
+ static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *crash_file_path);
+
+ static void Initialize();
+
+ static void DebuggerInitialize(Debugger &debugger);
+
+ static void Terminate();
+
+ static ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ //------------------------------------------------------------------
+ // Check if a given Process
+ //------------------------------------------------------------------
+ bool CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) override;
+
+ CommandObject *GetPluginCommandObject() override;
+
+ //------------------------------------------------------------------
+ // Creating a new process, or attaching to an existing one
+ //------------------------------------------------------------------
+ Error WillLaunch(Module *module) override;
+
+ Error DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override;
+
+ void DidLaunch() override;
+
+ Error WillAttachToProcessWithID(lldb::pid_t pid) override;
+
+ Error WillAttachToProcessWithName(const char *process_name,
+ bool wait_for_launch) override;
+
+ Error DoConnectRemote(Stream *strm, const char *remote_url) override;
+
+ Error WillLaunchOrAttach();
+
+ Error DoAttachToProcessWithID(lldb::pid_t pid,
+ const ProcessAttachInfo &attach_info) override;
+
+ Error
+ DoAttachToProcessWithName(const char *process_name,
+ const ProcessAttachInfo &attach_info) override;
+
+ void DidAttach(ArchSpec &process_arch) override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ //------------------------------------------------------------------
+ // Process Control
+ //------------------------------------------------------------------
+ Error WillResume() override;
+
+ Error DoResume() override;
+
+ Error DoHalt(bool &caused_stop) override;
+
+ Error DoDetach(bool keep_stopped) override;
+
+ bool DetachRequiresHalt() override { return true; }
+
+ Error DoSignal(int signal) override;
+
+ Error DoDestroy() override;
+
+ void RefreshStateAfterStop() override;
+
+ void SetUnixSignals(const lldb::UnixSignalsSP &signals_sp);
+
+ //------------------------------------------------------------------
+ // Process Queries
+ //------------------------------------------------------------------
+ bool IsAlive() override;
+
+ lldb::addr_t GetImageInfoAddress() override;
+
+ void WillPublicStop() override;
+
+ //------------------------------------------------------------------
+ // Process Memory
+ //------------------------------------------------------------------
+ size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Error &error) override;
+
+ size_t DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size,
+ Error &error) override;
+
+ lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions,
+ Error &error) override;
+
+ Error GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo ®ion_info) override;
+
+ Error DoDeallocateMemory(lldb::addr_t ptr) override;
+
+ //------------------------------------------------------------------
+ // Process STDIO
+ //------------------------------------------------------------------
+ size_t PutSTDIN(const char *buf, size_t buf_size, Error &error) override;
+
+ //----------------------------------------------------------------------
+ // Process Breakpoints
+ //----------------------------------------------------------------------
+ Error EnableBreakpointSite(BreakpointSite *bp_site) override;
+
+ Error DisableBreakpointSite(BreakpointSite *bp_site) override;
+
+ //----------------------------------------------------------------------
+ // Process Watchpoints
+ //----------------------------------------------------------------------
+ Error EnableWatchpoint(Watchpoint *wp, bool notify = true) override;
+
+ Error DisableWatchpoint(Watchpoint *wp, bool notify = true) override;
+
+ Error GetWatchpointSupportInfo(uint32_t &num) override;
+
+ Error GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
+
+ bool StartNoticingNewThreads() override;
+
+ bool StopNoticingNewThreads() override;
+
+ GDBRemoteCommunicationClient &GetGDBRemote() { return m_gdb_comm; }
- ~ProcessGDBRemote() override;
+ Error SendEventData(const char *data) override;
- static lldb::ProcessSP
- CreateInstance (lldb::TargetSP target_sp,
- lldb::ListenerSP listener_sp,
- const FileSpec *crash_file_path);
-
- static void
- Initialize();
-
- static void
- DebuggerInitialize (Debugger &debugger);
-
- static void
- Terminate();
-
- static ConstString
- GetPluginNameStatic();
-
- static const char *
- GetPluginDescriptionStatic();
-
- //------------------------------------------------------------------
- // Check if a given Process
- //------------------------------------------------------------------
- bool
- CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name) override;
-
- CommandObject *
- GetPluginCommandObject() override;
-
- //------------------------------------------------------------------
- // Creating a new process, or attaching to an existing one
- //------------------------------------------------------------------
- Error
- WillLaunch (Module* module) override;
-
- Error
- DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) override;
-
- void
- DidLaunch () override;
-
- Error
- WillAttachToProcessWithID (lldb::pid_t pid) override;
-
- Error
- WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) override;
-
- Error
- DoConnectRemote (Stream *strm, const char *remote_url) override;
-
- Error
- WillLaunchOrAttach ();
-
- Error
- DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info) override;
-
- Error
- DoAttachToProcessWithName (const char *process_name,
- const ProcessAttachInfo &attach_info) override;
-
- void
- DidAttach (ArchSpec &process_arch) override;
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- ConstString
- GetPluginName() override;
-
- uint32_t
- GetPluginVersion() override;
-
- //------------------------------------------------------------------
- // Process Control
- //------------------------------------------------------------------
- Error
- WillResume () override;
-
- Error
- DoResume () override;
-
- Error
- DoHalt (bool &caused_stop) override;
-
- Error
- DoDetach (bool keep_stopped) override;
-
- bool
- DetachRequiresHalt() override { return true; }
-
- Error
- DoSignal (int signal) override;
-
- Error
- DoDestroy () override;
-
- void
- RefreshStateAfterStop() override;
-
- void
- SetUnixSignals(const lldb::UnixSignalsSP &signals_sp);
-
- //------------------------------------------------------------------
- // Process Queries
- //------------------------------------------------------------------
- bool
- IsAlive () override;
-
- lldb::addr_t
- GetImageInfoAddress() override;
-
- void
- WillPublicStop () override;
-
- //------------------------------------------------------------------
- // Process Memory
- //------------------------------------------------------------------
- size_t
- DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error) override;
-
- size_t
- DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, Error &error) override;
-
- lldb::addr_t
- DoAllocateMemory (size_t size, uint32_t permissions, Error &error) override;
-
- Error
- GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo ®ion_info) override;
-
- Error
- DoDeallocateMemory (lldb::addr_t ptr) override;
-
- //------------------------------------------------------------------
- // Process STDIO
- //------------------------------------------------------------------
- size_t
- PutSTDIN (const char *buf, size_t buf_size, Error &error) override;
-
- //----------------------------------------------------------------------
- // Process Breakpoints
- //----------------------------------------------------------------------
- Error
- EnableBreakpointSite (BreakpointSite *bp_site) override;
-
- Error
- DisableBreakpointSite (BreakpointSite *bp_site) override;
-
- //----------------------------------------------------------------------
- // Process Watchpoints
- //----------------------------------------------------------------------
- Error
- EnableWatchpoint (Watchpoint *wp, bool notify = true) override;
-
- Error
- DisableWatchpoint (Watchpoint *wp, bool notify = true) override;
-
- Error
- GetWatchpointSupportInfo (uint32_t &num) override;
-
- Error
- GetWatchpointSupportInfo (uint32_t &num, bool& after) override;
-
- bool
- StartNoticingNewThreads() override;
-
- bool
- StopNoticingNewThreads() override;
-
- GDBRemoteCommunicationClient &
- GetGDBRemote()
- {
- return m_gdb_comm;
- }
-
- Error
- SendEventData(const char *data) override;
-
- //----------------------------------------------------------------------
- // Override DidExit so we can disconnect from the remote GDB server
- //----------------------------------------------------------------------
- void
- DidExit () override;
-
- void
- SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max);
-
- bool
- GetModuleSpec(const FileSpec& module_file_spec,
- const ArchSpec& arch,
- ModuleSpec &module_spec) override;
-
- bool
- GetHostOSVersion(uint32_t &major,
- uint32_t &minor,
- uint32_t &update) override;
-
- size_t
- LoadModules(LoadedModuleInfoList &module_list) override;
-
- size_t
- LoadModules() override;
-
- Error
- GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr) override;
-
- void
- ModulesDidLoad (ModuleList &module_list) override;
-
- StructuredData::ObjectSP
- GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count) override;
-
- Error
- ConfigureStructuredData(const ConstString &type_name,
- const StructuredData::ObjectSP &config_sp) override;
-
- StructuredData::ObjectSP
- GetLoadedDynamicLibrariesInfos () override;
-
- StructuredData::ObjectSP
- GetLoadedDynamicLibrariesInfos (const std::vector<lldb::addr_t> &load_addresses) override;
+ //----------------------------------------------------------------------
+ // Override DidExit so we can disconnect from the remote GDB server
+ //----------------------------------------------------------------------
+ void DidExit() override;
- StructuredData::ObjectSP
- GetLoadedDynamicLibrariesInfos_sender (StructuredData::ObjectSP args);
+ void SetUserSpecifiedMaxMemoryTransferSize(uint64_t user_specified_max);
- StructuredData::ObjectSP
- GetSharedCacheInfo () override;
+ bool GetModuleSpec(const FileSpec &module_file_spec, const ArchSpec &arch,
+ ModuleSpec &module_spec) override;
- std::string
- HarmonizeThreadIdsForProfileData(StringExtractorGDBRemote &inputStringExtractor);
+ bool GetHostOSVersion(uint32_t &major, uint32_t &minor,
+ uint32_t &update) override;
+
+ size_t LoadModules(LoadedModuleInfoList &module_list) override;
+
+ size_t LoadModules() override;
+
+ Error GetFileLoadAddress(const FileSpec &file, bool &is_loaded,
+ lldb::addr_t &load_addr) override;
+
+ void ModulesDidLoad(ModuleList &module_list) override;
+
+ StructuredData::ObjectSP
+ GetLoadedDynamicLibrariesInfos(lldb::addr_t image_list_address,
+ lldb::addr_t image_count) override;
+
+ Error
+ ConfigureStructuredData(const ConstString &type_name,
+ const StructuredData::ObjectSP &config_sp) override;
+
+ StructuredData::ObjectSP GetLoadedDynamicLibrariesInfos() override;
+
+ StructuredData::ObjectSP GetLoadedDynamicLibrariesInfos(
+ const std::vector<lldb::addr_t> &load_addresses) override;
+
+ StructuredData::ObjectSP
+ GetLoadedDynamicLibrariesInfos_sender(StructuredData::ObjectSP args);
+
+ StructuredData::ObjectSP GetSharedCacheInfo() override;
+
+ std::string HarmonizeThreadIdsForProfileData(
+ StringExtractorGDBRemote &inputStringExtractor);
protected:
- friend class ThreadGDBRemote;
- friend class GDBRemoteCommunicationClient;
- friend class GDBRemoteRegisterContext;
-
- //------------------------------------------------------------------
- /// Broadcaster event bits definitions.
- //------------------------------------------------------------------
- enum
- {
- eBroadcastBitAsyncContinue = (1 << 0),
- eBroadcastBitAsyncThreadShouldExit = (1 << 1),
- eBroadcastBitAsyncThreadDidExit = (1 << 2)
- };
-
- Flags m_flags; // Process specific flags (see eFlags enums)
- GDBRemoteCommunicationClient m_gdb_comm;
- std::atomic<lldb::pid_t> m_debugserver_pid;
- std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet stack replaces the last stop packet variable
- std::recursive_mutex m_last_stop_packet_mutex;
- GDBRemoteDynamicRegisterInfo m_register_info;
- Broadcaster m_async_broadcaster;
- lldb::ListenerSP m_async_listener_sp;
- HostThread m_async_thread;
- std::recursive_mutex m_async_thread_state_mutex;
- typedef std::vector<lldb::tid_t> tid_collection;
- typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
- typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
- typedef std::map<uint32_t, std::string> ExpeditedRegisterMap;
- tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping
- std::vector<lldb::addr_t> m_thread_pcs; // PC values for all the threads.
- StructuredData::ObjectSP m_jstopinfo_sp; // Stop info only for any threads that have valid stop infos
- StructuredData::ObjectSP m_jthreadsinfo_sp; // Full stop info, expedited registers and memory for all threads if "jThreadsInfo" packet is supported
- tid_collection m_continue_c_tids; // 'c' for continue
- tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
- tid_collection m_continue_s_tids; // 's' for step
- tid_sig_collection m_continue_S_tids; // 'S' for step with signal
- uint64_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
- uint64_t m_remote_stub_max_memory_size; // The maximum memory size the remote gdb stub can handle
- MMapMap m_addr_to_mmap_size;
- lldb::BreakpointSP m_thread_create_bp_sp;
- bool m_waiting_for_attach;
- bool m_destroy_tried_resuming;
- lldb::CommandObjectSP m_command_sp;
- int64_t m_breakpoint_pc_offset;
- lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
-
- //----------------------------------------------------------------------
- // Accessors
- //----------------------------------------------------------------------
- bool
- IsRunning ( lldb::StateType state )
- {
- return state == lldb::eStateRunning || IsStepping(state);
- }
-
- bool
- IsStepping ( lldb::StateType state)
- {
- return state == lldb::eStateStepping;
- }
-
- bool
- CanResume ( lldb::StateType state)
- {
- return state == lldb::eStateStopped;
- }
-
- bool
- HasExited (lldb::StateType state)
- {
- return state == lldb::eStateExited;
- }
-
- bool
- ProcessIDIsValid ( ) const;
-
- void
- Clear ( );
-
- Flags &
- GetFlags ()
- {
- return m_flags;
- }
-
- const Flags &
- GetFlags () const
- {
- return m_flags;
- }
-
- bool
- UpdateThreadList (ThreadList &old_thread_list,
- ThreadList &new_thread_list) override;
-
- Error
- EstablishConnectionIfNeeded (const ProcessInfo &process_info);
-
- Error
- LaunchAndConnectToDebugserver (const ProcessInfo &process_info);
-
- void
- KillDebugserverProcess ();
-
- void
- BuildDynamicRegisterInfo (bool force);
-
- void
- SetLastStopPacket (const StringExtractorGDBRemote &response);
-
- bool
- ParsePythonTargetDefinition(const FileSpec &target_definition_fspec);
-
- const lldb::DataBufferSP
- GetAuxvData() override;
-
- StructuredData::ObjectSP
- GetExtendedInfoForThread (lldb::tid_t tid);
-
- void
- GetMaxMemorySize();
-
- bool
- CalculateThreadStopInfo (ThreadGDBRemote *thread);
-
- size_t
- UpdateThreadPCsFromStopReplyThreadsValue (std::string &value);
-
- size_t
- UpdateThreadIDsFromStopReplyThreadsValue (std::string &value);
-
- bool
- HandleNotifyPacket(StringExtractorGDBRemote &packet);
-
- bool
- StartAsyncThread ();
-
- void
- StopAsyncThread ();
-
- static lldb::thread_result_t
- AsyncThread (void *arg);
-
- static bool
- MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t pid, bool exited, int signo,
- int exit_status);
-
- lldb::StateType
- SetThreadStopInfo (StringExtractor& stop_packet);
-
- bool
- GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp);
-
- lldb::ThreadSP
- SetThreadStopInfo (StructuredData::Dictionary *thread_dict);
-
- lldb::ThreadSP
- SetThreadStopInfo (lldb::tid_t tid,
- ExpeditedRegisterMap &expedited_register_map,
- uint8_t signo,
- const std::string &thread_name,
- const std::string &reason,
- const std::string &description,
- uint32_t exc_type,
- const std::vector<lldb::addr_t> &exc_data,
- lldb::addr_t thread_dispatch_qaddr,
- bool queue_vars_valid,
- lldb_private::LazyBool associated_with_libdispatch_queue,
- lldb::addr_t dispatch_queue_t,
- std::string &queue_name,
- lldb::QueueKind queue_kind,
- uint64_t queue_serial);
-
- void
- HandleStopReplySequence ();
-
- void
- ClearThreadIDList ();
-
- bool
- UpdateThreadIDList ();
-
- void
- DidLaunchOrAttach (ArchSpec& process_arch);
-
- Error
- ConnectToDebugserver (const char *host_port);
-
- const char *
- GetDispatchQueueNameForThread (lldb::addr_t thread_dispatch_qaddr,
- std::string &dispatch_queue_name);
-
- DynamicLoader *
- GetDynamicLoader () override;
-
- // Query remote GDBServer for register information
- bool
- GetGDBServerRegisterInfo (ArchSpec &arch);
-
- // Query remote GDBServer for a detailed loaded library list
- Error
- GetLoadedModuleList (LoadedModuleInfoList &);
-
- lldb::ModuleSP
- LoadModuleAtAddress (const FileSpec &file, lldb::addr_t link_map, lldb::addr_t base_addr,
- bool value_is_offset);
+ friend class ThreadGDBRemote;
+ friend class GDBRemoteCommunicationClient;
+ friend class GDBRemoteRegisterContext;
+
+ //------------------------------------------------------------------
+ /// Broadcaster event bits definitions.
+ //------------------------------------------------------------------
+ enum {
+ eBroadcastBitAsyncContinue = (1 << 0),
+ eBroadcastBitAsyncThreadShouldExit = (1 << 1),
+ eBroadcastBitAsyncThreadDidExit = (1 << 2)
+ };
+
+ Flags m_flags; // Process specific flags (see eFlags enums)
+ GDBRemoteCommunicationClient m_gdb_comm;
+ std::atomic<lldb::pid_t> m_debugserver_pid;
+ std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet
+ // stack replaces
+ // the last stop
+ // packet variable
+ std::recursive_mutex m_last_stop_packet_mutex;
+ GDBRemoteDynamicRegisterInfo m_register_info;
+ Broadcaster m_async_broadcaster;
+ lldb::ListenerSP m_async_listener_sp;
+ HostThread m_async_thread;
+ std::recursive_mutex m_async_thread_state_mutex;
+ typedef std::vector<lldb::tid_t> tid_collection;
+ typedef std::vector<std::pair<lldb::tid_t, int>> tid_sig_collection;
+ typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
+ typedef std::map<uint32_t, std::string> ExpeditedRegisterMap;
+ tid_collection m_thread_ids; // Thread IDs for all threads. This list gets
+ // updated after stopping
+ std::vector<lldb::addr_t> m_thread_pcs; // PC values for all the threads.
+ StructuredData::ObjectSP m_jstopinfo_sp; // Stop info only for any threads
+ // that have valid stop infos
+ StructuredData::ObjectSP m_jthreadsinfo_sp; // Full stop info, expedited
+ // registers and memory for all
+ // threads if "jThreadsInfo"
+ // packet is supported
+ tid_collection m_continue_c_tids; // 'c' for continue
+ tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
+ tid_collection m_continue_s_tids; // 's' for step
+ tid_sig_collection m_continue_S_tids; // 'S' for step with signal
+ uint64_t m_max_memory_size; // The maximum number of bytes to read/write when
+ // reading and writing memory
+ uint64_t m_remote_stub_max_memory_size; // The maximum memory size the remote
+ // gdb stub can handle
+ MMapMap m_addr_to_mmap_size;
+ lldb::BreakpointSP m_thread_create_bp_sp;
+ bool m_waiting_for_attach;
+ bool m_destroy_tried_resuming;
+ lldb::CommandObjectSP m_command_sp;
+ int64_t m_breakpoint_pc_offset;
+ lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+ bool IsRunning(lldb::StateType state) {
+ return state == lldb::eStateRunning || IsStepping(state);
+ }
+
+ bool IsStepping(lldb::StateType state) {
+ return state == lldb::eStateStepping;
+ }
+
+ bool CanResume(lldb::StateType state) { return state == lldb::eStateStopped; }
+
+ bool HasExited(lldb::StateType state) { return state == lldb::eStateExited; }
+
+ bool ProcessIDIsValid() const;
+
+ void Clear();
+
+ Flags &GetFlags() { return m_flags; }
+
+ const Flags &GetFlags() const { return m_flags; }
+
+ bool UpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) override;
+
+ Error EstablishConnectionIfNeeded(const ProcessInfo &process_info);
+
+ Error LaunchAndConnectToDebugserver(const ProcessInfo &process_info);
+
+ void KillDebugserverProcess();
+
+ void BuildDynamicRegisterInfo(bool force);
+
+ void SetLastStopPacket(const StringExtractorGDBRemote &response);
+
+ bool ParsePythonTargetDefinition(const FileSpec &target_definition_fspec);
+
+ const lldb::DataBufferSP GetAuxvData() override;
+
+ StructuredData::ObjectSP GetExtendedInfoForThread(lldb::tid_t tid);
+
+ void GetMaxMemorySize();
+
+ bool CalculateThreadStopInfo(ThreadGDBRemote *thread);
+
+ size_t UpdateThreadPCsFromStopReplyThreadsValue(std::string &value);
+
+ size_t UpdateThreadIDsFromStopReplyThreadsValue(std::string &value);
+
+ bool HandleNotifyPacket(StringExtractorGDBRemote &packet);
+
+ bool StartAsyncThread();
+
+ void StopAsyncThread();
+
+ static lldb::thread_result_t AsyncThread(void *arg);
+
+ static bool
+ MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp,
+ lldb::pid_t pid, bool exited, int signo,
+ int exit_status);
+
+ lldb::StateType SetThreadStopInfo(StringExtractor &stop_packet);
+
+ bool
+ GetThreadStopInfoFromJSON(ThreadGDBRemote *thread,
+ const StructuredData::ObjectSP &thread_infos_sp);
+
+ lldb::ThreadSP SetThreadStopInfo(StructuredData::Dictionary *thread_dict);
+
+ lldb::ThreadSP
+ SetThreadStopInfo(lldb::tid_t tid,
+ ExpeditedRegisterMap &expedited_register_map, uint8_t signo,
+ const std::string &thread_name, const std::string &reason,
+ const std::string &description, uint32_t exc_type,
+ const std::vector<lldb::addr_t> &exc_data,
+ lldb::addr_t thread_dispatch_qaddr, bool queue_vars_valid,
+ lldb_private::LazyBool associated_with_libdispatch_queue,
+ lldb::addr_t dispatch_queue_t, std::string &queue_name,
+ lldb::QueueKind queue_kind, uint64_t queue_serial);
+
+ void HandleStopReplySequence();
+
+ void ClearThreadIDList();
+
+ bool UpdateThreadIDList();
+
+ void DidLaunchOrAttach(ArchSpec &process_arch);
+
+ Error ConnectToDebugserver(const char *host_port);
+
+ const char *GetDispatchQueueNameForThread(lldb::addr_t thread_dispatch_qaddr,
+ std::string &dispatch_queue_name);
+
+ DynamicLoader *GetDynamicLoader() override;
+
+ // Query remote GDBServer for register information
+ bool GetGDBServerRegisterInfo(ArchSpec &arch);
+
+ // Query remote GDBServer for a detailed loaded library list
+ Error GetLoadedModuleList(LoadedModuleInfoList &);
+
+ lldb::ModuleSP LoadModuleAtAddress(const FileSpec &file,
+ lldb::addr_t link_map,
+ lldb::addr_t base_addr,
+ bool value_is_offset);
private:
- //------------------------------------------------------------------
- // For ProcessGDBRemote only
- //------------------------------------------------------------------
- std::string m_partial_profile_data;
- std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map;
-
- static bool
- NewThreadNotifyBreakpointHit (void *baton,
- StoppointCallbackContext *context,
- lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id);
-
- //------------------------------------------------------------------
- // ContinueDelegate interface
- //------------------------------------------------------------------
- void
- HandleAsyncStdout(llvm::StringRef out) override;
- void
- HandleAsyncMisc(llvm::StringRef data) override;
- void
- HandleStopReply() override;
- bool
- HandleAsyncStructuredData(const StructuredData::ObjectSP
- &object_sp) override;
+ //------------------------------------------------------------------
+ // For ProcessGDBRemote only
+ //------------------------------------------------------------------
+ std::string m_partial_profile_data;
+ std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map;
+
+ static bool NewThreadNotifyBreakpointHit(void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ //------------------------------------------------------------------
+ // ContinueDelegate interface
+ //------------------------------------------------------------------
+ void HandleAsyncStdout(llvm::StringRef out) override;
+ void HandleAsyncMisc(llvm::StringRef data) override;
+ void HandleStopReply() override;
+ bool
+ HandleAsyncStructuredData(const StructuredData::ObjectSP &object_sp) override;
- DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote);
+ DISALLOW_COPY_AND_ASSIGN(ProcessGDBRemote);
};
} // namespace process_gdb_remote
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp Tue Sep 6 15:57:50 2016
@@ -11,8 +11,8 @@
#include <mutex>
-#include "lldb/Interpreter/Args.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Interpreter/Args.h"
#include "ProcessGDBRemote.h"
@@ -20,196 +20,198 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
-
// We want to avoid global constructors where code needs to be run so here we
// control access to our static g_log_sp by hiding it in a singleton function
-// that will construct the static g_lob_sp the first time this function is
+// that will construct the static g_lob_sp the first time this function is
// called.
static bool g_log_enabled = false;
-static Log * g_log = NULL;
-static Log *
-GetLog ()
-{
- if (!g_log_enabled)
- return NULL;
- return g_log;
-}
-
-void
-ProcessGDBRemoteLog::Initialize()
-{
- static ConstString g_name("gdb-remote");
- static std::once_flag g_once_flag;
-
- std::call_once(g_once_flag, [](){
- Log::Callbacks log_callbacks = {
- DisableLog,
- EnableLog,
- ListLogCategories
- };
-
- Log::RegisterLogChannel (g_name, log_callbacks);
- });
-}
-
-Log *
-ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (uint32_t mask)
-{
- Log *log(GetLog ());
- if (log && mask)
- {
- uint32_t log_mask = log->GetMask().Get();
- if ((log_mask & mask) != mask)
- return NULL;
- }
- return log;
+static Log *g_log = NULL;
+static Log *GetLog() {
+ if (!g_log_enabled)
+ return NULL;
+ return g_log;
}
-Log *
-ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (uint32_t mask)
-{
- Log *log(GetLog ());
- if (log && log->GetMask().Get() & mask)
- return log;
- return NULL;
+void ProcessGDBRemoteLog::Initialize() {
+ static ConstString g_name("gdb-remote");
+ static std::once_flag g_once_flag;
+
+ std::call_once(g_once_flag, []() {
+ Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories};
+
+ Log::RegisterLogChannel(g_name, log_callbacks);
+ });
}
-void
-ProcessGDBRemoteLog::DisableLog (const char **categories, Stream *feedback_strm)
-{
- Log *log (GetLog ());
- if (log)
- {
- uint32_t flag_bits = 0;
-
- if (categories[0] != NULL)
- {
- flag_bits = log->GetMask().Get();
- for (size_t i = 0; categories[i] != NULL; ++i)
- {
- const char *arg = categories[i];
-
-
- if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~GDBR_LOG_ALL;
- else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~GDBR_LOG_ASYNC;
- else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~GDBR_LOG_BREAKPOINTS;
- else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~GDBR_LOG_COMM;
- else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~GDBR_LOG_DEFAULT;
- else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~GDBR_LOG_PACKETS;
- else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~GDBR_LOG_MEMORY;
- else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~GDBR_LOG_MEMORY_DATA_SHORT;
- else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~GDBR_LOG_MEMORY_DATA_LONG;
- else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~GDBR_LOG_PROCESS;
- else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~GDBR_LOG_STEP;
- else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~GDBR_LOG_THREAD;
- else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~GDBR_LOG_VERBOSE;
- else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~GDBR_LOG_WATCHPOINTS;
- else
- {
- feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
- ListLogCategories (feedback_strm);
- }
-
- }
- }
-
- if (flag_bits == 0)
- g_log_enabled = false;
- else
- log->GetMask().Reset (flag_bits);
- }
-
- return;
+Log *ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(uint32_t mask) {
+ Log *log(GetLog());
+ if (log && mask) {
+ uint32_t log_mask = log->GetMask().Get();
+ if ((log_mask & mask) != mask)
+ return NULL;
+ }
+ return log;
}
-Log *
-ProcessGDBRemoteLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm)
-{
- // Try see if there already is a log - that way we can reuse its settings.
- // We could reuse the log in toto, but we don't know that the stream is the same.
- uint32_t flag_bits = 0;
- if (g_log)
- flag_bits = g_log->GetMask().Get();
+Log *ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(uint32_t mask) {
+ Log *log(GetLog());
+ if (log && log->GetMask().Get() & mask)
+ return log;
+ return NULL;
+}
- // Now make a new log with this stream if one was provided
- if (log_stream_sp)
- {
- if (g_log)
- g_log->SetStream(log_stream_sp);
- else
- g_log = new Log(log_stream_sp);
- }
+void ProcessGDBRemoteLog::DisableLog(const char **categories,
+ Stream *feedback_strm) {
+ Log *log(GetLog());
+ if (log) {
+ uint32_t flag_bits = 0;
- if (g_log)
- {
- bool got_unknown_category = false;
- for (size_t i=0; categories[i] != NULL; ++i)
- {
- const char *arg = categories[i];
-
- if (::strcasecmp (arg, "all") == 0 ) flag_bits |= GDBR_LOG_ALL;
- else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= GDBR_LOG_ASYNC;
- else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= GDBR_LOG_BREAKPOINTS;
- else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= GDBR_LOG_COMM;
- else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= GDBR_LOG_DEFAULT;
- else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= GDBR_LOG_PACKETS;
- else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= GDBR_LOG_MEMORY;
- else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT;
- else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= GDBR_LOG_MEMORY_DATA_LONG;
- else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= GDBR_LOG_PROCESS;
- else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= GDBR_LOG_STEP;
- else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= GDBR_LOG_THREAD;
- else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= GDBR_LOG_VERBOSE;
- else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= GDBR_LOG_WATCHPOINTS;
- else
- {
- feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
- if (got_unknown_category == false)
- {
- got_unknown_category = true;
- ListLogCategories (feedback_strm);
- }
- }
+ if (categories[0] != NULL) {
+ flag_bits = log->GetMask().Get();
+ for (size_t i = 0; categories[i] != NULL; ++i) {
+ const char *arg = categories[i];
+
+ if (::strcasecmp(arg, "all") == 0)
+ flag_bits &= ~GDBR_LOG_ALL;
+ else if (::strcasecmp(arg, "async") == 0)
+ flag_bits &= ~GDBR_LOG_ASYNC;
+ else if (::strncasecmp(arg, "break", 5) == 0)
+ flag_bits &= ~GDBR_LOG_BREAKPOINTS;
+ else if (::strncasecmp(arg, "comm", 4) == 0)
+ flag_bits &= ~GDBR_LOG_COMM;
+ else if (::strcasecmp(arg, "default") == 0)
+ flag_bits &= ~GDBR_LOG_DEFAULT;
+ else if (::strcasecmp(arg, "packets") == 0)
+ flag_bits &= ~GDBR_LOG_PACKETS;
+ else if (::strcasecmp(arg, "memory") == 0)
+ flag_bits &= ~GDBR_LOG_MEMORY;
+ else if (::strcasecmp(arg, "data-short") == 0)
+ flag_bits &= ~GDBR_LOG_MEMORY_DATA_SHORT;
+ else if (::strcasecmp(arg, "data-long") == 0)
+ flag_bits &= ~GDBR_LOG_MEMORY_DATA_LONG;
+ else if (::strcasecmp(arg, "process") == 0)
+ flag_bits &= ~GDBR_LOG_PROCESS;
+ else if (::strcasecmp(arg, "step") == 0)
+ flag_bits &= ~GDBR_LOG_STEP;
+ else if (::strcasecmp(arg, "thread") == 0)
+ flag_bits &= ~GDBR_LOG_THREAD;
+ else if (::strcasecmp(arg, "verbose") == 0)
+ flag_bits &= ~GDBR_LOG_VERBOSE;
+ else if (::strncasecmp(arg, "watch", 5) == 0)
+ flag_bits &= ~GDBR_LOG_WATCHPOINTS;
+ else {
+ feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+ ListLogCategories(feedback_strm);
}
- if (flag_bits == 0)
- flag_bits = GDBR_LOG_DEFAULT;
- g_log->GetMask().Reset(flag_bits);
- g_log->GetOptions().Reset(log_options);
+ }
}
- g_log_enabled = true;
- return g_log;
-}
-
-void
-ProcessGDBRemoteLog::ListLogCategories (Stream *strm)
-{
- strm->Printf ("Logging categories for '%s':\n"
- " all - turn on all available logging categories\n"
- " async - log asynchronous activity\n"
- " break - log breakpoints\n"
- " communication - log communication activity\n"
- " default - enable the default set of logging categories for liblldb\n"
- " packets - log gdb remote packets\n"
- " memory - log memory reads and writes\n"
- " data-short - log memory bytes for memory reads and writes for short transactions only\n"
- " data-long - log memory bytes for memory reads and writes for all transactions\n"
- " process - log process events and activities\n"
- " thread - log thread events and activities\n"
- " step - log step related activities\n"
- " verbose - enable verbose logging\n"
- " watch - log watchpoint related activities\n", ProcessGDBRemote::GetPluginNameStatic().GetCString());
-}
+ if (flag_bits == 0)
+ g_log_enabled = false;
+ else
+ log->GetMask().Reset(flag_bits);
+ }
+
+ return;
+}
+
+Log *ProcessGDBRemoteLog::EnableLog(StreamSP &log_stream_sp,
+ uint32_t log_options,
+ const char **categories,
+ Stream *feedback_strm) {
+ // Try see if there already is a log - that way we can reuse its settings.
+ // We could reuse the log in toto, but we don't know that the stream is the
+ // same.
+ uint32_t flag_bits = 0;
+ if (g_log)
+ flag_bits = g_log->GetMask().Get();
-void
-ProcessGDBRemoteLog::LogIf (uint32_t mask, const char *format, ...)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (mask));
- if (log)
- {
- va_list args;
- va_start (args, format);
- log->VAPrintf (format, args);
- va_end (args);
+ // Now make a new log with this stream if one was provided
+ if (log_stream_sp) {
+ if (g_log)
+ g_log->SetStream(log_stream_sp);
+ else
+ g_log = new Log(log_stream_sp);
+ }
+
+ if (g_log) {
+ bool got_unknown_category = false;
+ for (size_t i = 0; categories[i] != NULL; ++i) {
+ const char *arg = categories[i];
+
+ if (::strcasecmp(arg, "all") == 0)
+ flag_bits |= GDBR_LOG_ALL;
+ else if (::strcasecmp(arg, "async") == 0)
+ flag_bits |= GDBR_LOG_ASYNC;
+ else if (::strncasecmp(arg, "break", 5) == 0)
+ flag_bits |= GDBR_LOG_BREAKPOINTS;
+ else if (::strncasecmp(arg, "comm", 4) == 0)
+ flag_bits |= GDBR_LOG_COMM;
+ else if (::strcasecmp(arg, "default") == 0)
+ flag_bits |= GDBR_LOG_DEFAULT;
+ else if (::strcasecmp(arg, "packets") == 0)
+ flag_bits |= GDBR_LOG_PACKETS;
+ else if (::strcasecmp(arg, "memory") == 0)
+ flag_bits |= GDBR_LOG_MEMORY;
+ else if (::strcasecmp(arg, "data-short") == 0)
+ flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT;
+ else if (::strcasecmp(arg, "data-long") == 0)
+ flag_bits |= GDBR_LOG_MEMORY_DATA_LONG;
+ else if (::strcasecmp(arg, "process") == 0)
+ flag_bits |= GDBR_LOG_PROCESS;
+ else if (::strcasecmp(arg, "step") == 0)
+ flag_bits |= GDBR_LOG_STEP;
+ else if (::strcasecmp(arg, "thread") == 0)
+ flag_bits |= GDBR_LOG_THREAD;
+ else if (::strcasecmp(arg, "verbose") == 0)
+ flag_bits |= GDBR_LOG_VERBOSE;
+ else if (::strncasecmp(arg, "watch", 5) == 0)
+ flag_bits |= GDBR_LOG_WATCHPOINTS;
+ else {
+ feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+ if (got_unknown_category == false) {
+ got_unknown_category = true;
+ ListLogCategories(feedback_strm);
+ }
+ }
}
+ if (flag_bits == 0)
+ flag_bits = GDBR_LOG_DEFAULT;
+ g_log->GetMask().Reset(flag_bits);
+ g_log->GetOptions().Reset(log_options);
+ }
+ g_log_enabled = true;
+ return g_log;
+}
+
+void ProcessGDBRemoteLog::ListLogCategories(Stream *strm) {
+ strm->Printf(
+ "Logging categories for '%s':\n"
+ " all - turn on all available logging categories\n"
+ " async - log asynchronous activity\n"
+ " break - log breakpoints\n"
+ " communication - log communication activity\n"
+ " default - enable the default set of logging categories for liblldb\n"
+ " packets - log gdb remote packets\n"
+ " memory - log memory reads and writes\n"
+ " data-short - log memory bytes for memory reads and writes for short "
+ "transactions only\n"
+ " data-long - log memory bytes for memory reads and writes for all "
+ "transactions\n"
+ " process - log process events and activities\n"
+ " thread - log thread events and activities\n"
+ " step - log step related activities\n"
+ " verbose - enable verbose logging\n"
+ " watch - log watchpoint related activities\n",
+ ProcessGDBRemote::GetPluginNameStatic().GetCString());
+}
+
+void ProcessGDBRemoteLog::LogIf(uint32_t mask, const char *format, ...) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(mask));
+ if (log) {
+ va_list args;
+ va_start(args, format);
+ log->VAPrintf(format, args);
+ va_end(args);
+ }
}
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h Tue Sep 6 15:57:50 2016
@@ -17,50 +17,44 @@
// Project includes
#include "lldb/Core/Log.h"
-#define GDBR_LOG_VERBOSE (1u << 0)
-#define GDBR_LOG_PROCESS (1u << 1)
-#define GDBR_LOG_THREAD (1u << 2)
-#define GDBR_LOG_PACKETS (1u << 3)
-#define GDBR_LOG_MEMORY (1u << 4) // Log memory reads/writes calls
-#define GDBR_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes
-#define GDBR_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes
-#define GDBR_LOG_BREAKPOINTS (1u << 7)
-#define GDBR_LOG_WATCHPOINTS (1u << 8)
-#define GDBR_LOG_STEP (1u << 9)
-#define GDBR_LOG_COMM (1u << 10)
-#define GDBR_LOG_ASYNC (1u << 11)
-#define GDBR_LOG_ALL (UINT32_MAX)
-#define GDBR_LOG_DEFAULT GDBR_LOG_PACKETS
+#define GDBR_LOG_VERBOSE (1u << 0)
+#define GDBR_LOG_PROCESS (1u << 1)
+#define GDBR_LOG_THREAD (1u << 2)
+#define GDBR_LOG_PACKETS (1u << 3)
+#define GDBR_LOG_MEMORY (1u << 4) // Log memory reads/writes calls
+#define GDBR_LOG_MEMORY_DATA_SHORT \
+ (1u << 5) // Log short memory reads/writes bytes
+#define GDBR_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes
+#define GDBR_LOG_BREAKPOINTS (1u << 7)
+#define GDBR_LOG_WATCHPOINTS (1u << 8)
+#define GDBR_LOG_STEP (1u << 9)
+#define GDBR_LOG_COMM (1u << 10)
+#define GDBR_LOG_ASYNC (1u << 11)
+#define GDBR_LOG_ALL (UINT32_MAX)
+#define GDBR_LOG_DEFAULT GDBR_LOG_PACKETS
namespace lldb_private {
namespace process_gdb_remote {
-class ProcessGDBRemoteLog
-{
+class ProcessGDBRemoteLog {
public:
- static void
- Initialize();
+ static void Initialize();
- static Log *
- GetLogIfAllCategoriesSet(uint32_t mask = 0);
-
- static Log *
- GetLogIfAnyCategoryIsSet (uint32_t mask);
-
- static void
- DisableLog (const char **categories, Stream *feedback_strm);
+ static Log *GetLogIfAllCategoriesSet(uint32_t mask = 0);
- static Log *
- EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm);
+ static Log *GetLogIfAnyCategoryIsSet(uint32_t mask);
- static void
- ListLogCategories (Stream *strm);
+ static void DisableLog(const char **categories, Stream *feedback_strm);
- static void
- LogIf (uint32_t mask, const char *format, ...);
+ static Log *EnableLog(lldb::StreamSP &log_stream_sp, uint32_t log_options,
+ const char **categories, Stream *feedback_strm);
+
+ static void ListLogCategories(Stream *strm);
+
+ static void LogIf(uint32_t mask, const char *format, ...);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_ProcessGDBRemoteLog_h_
+#endif // liblldb_ProcessGDBRemoteLog_h_
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp Tue Sep 6 15:57:50 2016
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-
#include "ThreadGDBRemote.h"
#include "lldb/Breakpoint/Watchpoint.h"
@@ -36,372 +35,318 @@ using namespace lldb_private::process_gd
// Thread Registers
//----------------------------------------------------------------------
-ThreadGDBRemote::ThreadGDBRemote (Process &process, lldb::tid_t tid) :
- Thread(process, tid),
- m_thread_name (),
- m_dispatch_queue_name (),
- m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS),
- m_dispatch_queue_t (LLDB_INVALID_ADDRESS),
- m_queue_kind (eQueueKindUnknown),
- m_queue_serial_number (LLDB_INVALID_QUEUE_ID),
- m_associated_with_libdispatch_queue (eLazyBoolCalculate)
-{
- ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)",
- this,
- process.GetID(),
- GetID());
-}
-
-ThreadGDBRemote::~ThreadGDBRemote ()
-{
- ProcessSP process_sp(GetProcess());
- ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::~ThreadGDBRemote (pid = %i, tid = 0x%4.4x)",
- this,
- process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID,
- GetID());
- DestroyThread();
-}
-
-const char *
-ThreadGDBRemote::GetName ()
-{
- if (m_thread_name.empty())
- return NULL;
- return m_thread_name.c_str();
-}
-
-void
-ThreadGDBRemote::ClearQueueInfo ()
-{
- m_dispatch_queue_name.clear();
- m_queue_kind = eQueueKindUnknown;
- m_queue_serial_number = 0;
- m_dispatch_queue_t = LLDB_INVALID_ADDRESS;
- m_associated_with_libdispatch_queue = eLazyBoolCalculate;
-}
-
-void
-ThreadGDBRemote::SetQueueInfo (std::string &&queue_name, QueueKind queue_kind, uint64_t queue_serial, addr_t dispatch_queue_t, LazyBool associated_with_libdispatch_queue)
-{
- m_dispatch_queue_name = queue_name;
- m_queue_kind = queue_kind;
- m_queue_serial_number = queue_serial;
- m_dispatch_queue_t = dispatch_queue_t;
- m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
+ThreadGDBRemote::ThreadGDBRemote(Process &process, lldb::tid_t tid)
+ : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(),
+ m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS),
+ m_dispatch_queue_t(LLDB_INVALID_ADDRESS), m_queue_kind(eQueueKindUnknown),
+ m_queue_serial_number(LLDB_INVALID_QUEUE_ID),
+ m_associated_with_libdispatch_queue(eLazyBoolCalculate) {
+ ProcessGDBRemoteLog::LogIf(
+ GDBR_LOG_THREAD,
+ "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this,
+ process.GetID(), GetID());
+}
+
+ThreadGDBRemote::~ThreadGDBRemote() {
+ ProcessSP process_sp(GetProcess());
+ ProcessGDBRemoteLog::LogIf(
+ GDBR_LOG_THREAD,
+ "%p: ThreadGDBRemote::~ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this,
+ process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, GetID());
+ DestroyThread();
}
-
-const char *
-ThreadGDBRemote::GetQueueName ()
-{
- // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
- if (CachedQueueInfoIsValid())
- {
- if (m_dispatch_queue_name.empty())
- return nullptr;
- else
- return m_dispatch_queue_name.c_str();
- }
- // Always re-fetch the dispatch queue name since it can change
-
- if (m_associated_with_libdispatch_queue == eLazyBoolNo)
- return nullptr;
-
- if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- SystemRuntime *runtime = process_sp->GetSystemRuntime ();
- if (runtime)
- m_dispatch_queue_name = runtime->GetQueueNameFromThreadQAddress (m_thread_dispatch_qaddr);
- else
- m_dispatch_queue_name.clear();
-
- if (!m_dispatch_queue_name.empty())
- return m_dispatch_queue_name.c_str();
- }
- }
+const char *ThreadGDBRemote::GetName() {
+ if (m_thread_name.empty())
return NULL;
+ return m_thread_name.c_str();
}
-QueueKind
-ThreadGDBRemote::GetQueueKind ()
-{
- // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
- if (CachedQueueInfoIsValid())
- {
- return m_queue_kind;
- }
+void ThreadGDBRemote::ClearQueueInfo() {
+ m_dispatch_queue_name.clear();
+ m_queue_kind = eQueueKindUnknown;
+ m_queue_serial_number = 0;
+ m_dispatch_queue_t = LLDB_INVALID_ADDRESS;
+ m_associated_with_libdispatch_queue = eLazyBoolCalculate;
+}
+
+void ThreadGDBRemote::SetQueueInfo(std::string &&queue_name,
+ QueueKind queue_kind, uint64_t queue_serial,
+ addr_t dispatch_queue_t,
+ LazyBool associated_with_libdispatch_queue) {
+ m_dispatch_queue_name = queue_name;
+ m_queue_kind = queue_kind;
+ m_queue_serial_number = queue_serial;
+ m_dispatch_queue_t = dispatch_queue_t;
+ m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
+}
+
+const char *ThreadGDBRemote::GetQueueName() {
+ // If our cached queue info is valid, then someone called
+ // ThreadGDBRemote::SetQueueInfo(...)
+ // with valid information that was gleaned from the stop reply packet. In this
+ // case we trust
+ // that the info is valid in m_dispatch_queue_name without refetching it
+ if (CachedQueueInfoIsValid()) {
+ if (m_dispatch_queue_name.empty())
+ return nullptr;
+ else
+ return m_dispatch_queue_name.c_str();
+ }
+ // Always re-fetch the dispatch queue name since it can change
- if (m_associated_with_libdispatch_queue == eLazyBoolNo)
- return eQueueKindUnknown;
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
+ return nullptr;
- if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- SystemRuntime *runtime = process_sp->GetSystemRuntime ();
- if (runtime)
- m_queue_kind = runtime->GetQueueKind (m_thread_dispatch_qaddr);
- return m_queue_kind;
- }
- }
+ if (m_thread_dispatch_qaddr != 0 &&
+ m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime();
+ if (runtime)
+ m_dispatch_queue_name =
+ runtime->GetQueueNameFromThreadQAddress(m_thread_dispatch_qaddr);
+ else
+ m_dispatch_queue_name.clear();
+
+ if (!m_dispatch_queue_name.empty())
+ return m_dispatch_queue_name.c_str();
+ }
+ }
+ return NULL;
+}
+
+QueueKind ThreadGDBRemote::GetQueueKind() {
+ // If our cached queue info is valid, then someone called
+ // ThreadGDBRemote::SetQueueInfo(...)
+ // with valid information that was gleaned from the stop reply packet. In this
+ // case we trust
+ // that the info is valid in m_dispatch_queue_name without refetching it
+ if (CachedQueueInfoIsValid()) {
+ return m_queue_kind;
+ }
+
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
return eQueueKindUnknown;
-}
+ if (m_thread_dispatch_qaddr != 0 &&
+ m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime();
+ if (runtime)
+ m_queue_kind = runtime->GetQueueKind(m_thread_dispatch_qaddr);
+ return m_queue_kind;
+ }
+ }
+ return eQueueKindUnknown;
+}
+
+queue_id_t ThreadGDBRemote::GetQueueID() {
+ // If our cached queue info is valid, then someone called
+ // ThreadGDBRemote::SetQueueInfo(...)
+ // with valid information that was gleaned from the stop reply packet. In this
+ // case we trust
+ // that the info is valid in m_dispatch_queue_name without refetching it
+ if (CachedQueueInfoIsValid())
+ return m_queue_serial_number;
-queue_id_t
-ThreadGDBRemote::GetQueueID ()
-{
- // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
- if (CachedQueueInfoIsValid())
- return m_queue_serial_number;
-
- if (m_associated_with_libdispatch_queue == eLazyBoolNo)
- return LLDB_INVALID_QUEUE_ID;
-
- if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- SystemRuntime *runtime = process_sp->GetSystemRuntime ();
- if (runtime)
- {
- return runtime->GetQueueIDFromThreadQAddress (m_thread_dispatch_qaddr);
- }
- }
- }
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
return LLDB_INVALID_QUEUE_ID;
+
+ if (m_thread_dispatch_qaddr != 0 &&
+ m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime();
+ if (runtime) {
+ return runtime->GetQueueIDFromThreadQAddress(m_thread_dispatch_qaddr);
+ }
+ }
+ }
+ return LLDB_INVALID_QUEUE_ID;
}
-QueueSP
-ThreadGDBRemote::GetQueue ()
-{
- queue_id_t queue_id = GetQueueID();
- QueueSP queue;
- if (queue_id != LLDB_INVALID_QUEUE_ID)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- queue = process_sp->GetQueueList().FindQueueByID (queue_id);
- }
+QueueSP ThreadGDBRemote::GetQueue() {
+ queue_id_t queue_id = GetQueueID();
+ QueueSP queue;
+ if (queue_id != LLDB_INVALID_QUEUE_ID) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ queue = process_sp->GetQueueList().FindQueueByID(queue_id);
}
- return queue;
+ }
+ return queue;
}
-addr_t
-ThreadGDBRemote::GetQueueLibdispatchQueueAddress ()
-{
- if (m_dispatch_queue_t == LLDB_INVALID_ADDRESS)
- {
- if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- SystemRuntime *runtime = process_sp->GetSystemRuntime ();
- if (runtime)
- {
- m_dispatch_queue_t = runtime->GetLibdispatchQueueAddressFromThreadQAddress (m_thread_dispatch_qaddr);
- }
- }
+addr_t ThreadGDBRemote::GetQueueLibdispatchQueueAddress() {
+ if (m_dispatch_queue_t == LLDB_INVALID_ADDRESS) {
+ if (m_thread_dispatch_qaddr != 0 &&
+ m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime();
+ if (runtime) {
+ m_dispatch_queue_t =
+ runtime->GetLibdispatchQueueAddressFromThreadQAddress(
+ m_thread_dispatch_qaddr);
}
+ }
}
- return m_dispatch_queue_t;
+ }
+ return m_dispatch_queue_t;
}
-void
-ThreadGDBRemote::SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t)
-{
- m_dispatch_queue_t = dispatch_queue_t;
-}
-
-bool
-ThreadGDBRemote::ThreadHasQueueInformation () const
-{
- if (m_thread_dispatch_qaddr != 0
- && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS
- && m_dispatch_queue_t != LLDB_INVALID_ADDRESS
- && m_queue_kind != eQueueKindUnknown
- && m_queue_serial_number != 0)
- {
- return true;
- }
- return false;
+void ThreadGDBRemote::SetQueueLibdispatchQueueAddress(
+ lldb::addr_t dispatch_queue_t) {
+ m_dispatch_queue_t = dispatch_queue_t;
}
-LazyBool
-ThreadGDBRemote::GetAssociatedWithLibdispatchQueue ()
-{
- return m_associated_with_libdispatch_queue;
-}
-
-void
-ThreadGDBRemote::SetAssociatedWithLibdispatchQueue (LazyBool associated_with_libdispatch_queue)
-{
- m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
-}
-
-StructuredData::ObjectSP
-ThreadGDBRemote::FetchThreadExtendedInfo ()
-{
- StructuredData::ObjectSP object_sp;
- const lldb::user_id_t tid = GetProtocolID();
- Log *log(GetLogIfAnyCategoriesSet (GDBR_LOG_THREAD));
- if (log)
- log->Printf ("Fetching extended information for thread %4.4" PRIx64, tid);
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
- object_sp = gdb_process->GetExtendedInfoForThread (tid);
- }
- return object_sp;
+bool ThreadGDBRemote::ThreadHasQueueInformation() const {
+ if (m_thread_dispatch_qaddr != 0 &&
+ m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS &&
+ m_dispatch_queue_t != LLDB_INVALID_ADDRESS &&
+ m_queue_kind != eQueueKindUnknown && m_queue_serial_number != 0) {
+ return true;
+ }
+ return false;
}
-void
-ThreadGDBRemote::WillResume (StateType resume_state)
-{
- int signo = GetResumeSignal();
- const lldb::user_id_t tid = GetProtocolID();
- Log *log(GetLogIfAnyCategoriesSet (GDBR_LOG_THREAD));
- if (log)
- log->Printf ("Resuming thread: %4.4" PRIx64 " with state: %s.", tid, StateAsCString(resume_state));
-
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
- switch (resume_state)
- {
- case eStateSuspended:
- case eStateStopped:
- // Don't append anything for threads that should stay stopped.
- break;
-
- case eStateRunning:
- if (gdb_process->GetUnixSignals()->SignalIsValid(signo))
- gdb_process->m_continue_C_tids.push_back(std::make_pair(tid, signo));
- else
- gdb_process->m_continue_c_tids.push_back(tid);
- break;
-
- case eStateStepping:
- if (gdb_process->GetUnixSignals()->SignalIsValid(signo))
- gdb_process->m_continue_S_tids.push_back(std::make_pair(tid, signo));
- else
- gdb_process->m_continue_s_tids.push_back(tid);
- break;
-
- default:
- break;
- }
- }
+LazyBool ThreadGDBRemote::GetAssociatedWithLibdispatchQueue() {
+ return m_associated_with_libdispatch_queue;
}
-void
-ThreadGDBRemote::RefreshStateAfterStop()
-{
- // Invalidate all registers in our register context. We don't set "force" to
- // true because the stop reply packet might have had some register values
- // that were expedited and these will already be copied into the register
- // context by the time this function gets called. The GDBRemoteRegisterContext
- // class has been made smart enough to detect when it needs to invalidate
- // which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
- const bool force = false;
- GetRegisterContext()->InvalidateIfNeeded (force);
-}
-
-bool
-ThreadGDBRemote::ThreadIDIsValid (lldb::tid_t thread)
-{
- return thread != 0;
-}
-
-void
-ThreadGDBRemote::Dump(Log *log, uint32_t index)
-{
+void ThreadGDBRemote::SetAssociatedWithLibdispatchQueue(
+ LazyBool associated_with_libdispatch_queue) {
+ m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
+}
+
+StructuredData::ObjectSP ThreadGDBRemote::FetchThreadExtendedInfo() {
+ StructuredData::ObjectSP object_sp;
+ const lldb::user_id_t tid = GetProtocolID();
+ Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD));
+ if (log)
+ log->Printf("Fetching extended information for thread %4.4" PRIx64, tid);
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ ProcessGDBRemote *gdb_process =
+ static_cast<ProcessGDBRemote *>(process_sp.get());
+ object_sp = gdb_process->GetExtendedInfoForThread(tid);
+ }
+ return object_sp;
+}
+
+void ThreadGDBRemote::WillResume(StateType resume_state) {
+ int signo = GetResumeSignal();
+ const lldb::user_id_t tid = GetProtocolID();
+ Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD));
+ if (log)
+ log->Printf("Resuming thread: %4.4" PRIx64 " with state: %s.", tid,
+ StateAsCString(resume_state));
+
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ ProcessGDBRemote *gdb_process =
+ static_cast<ProcessGDBRemote *>(process_sp.get());
+ switch (resume_state) {
+ case eStateSuspended:
+ case eStateStopped:
+ // Don't append anything for threads that should stay stopped.
+ break;
+
+ case eStateRunning:
+ if (gdb_process->GetUnixSignals()->SignalIsValid(signo))
+ gdb_process->m_continue_C_tids.push_back(std::make_pair(tid, signo));
+ else
+ gdb_process->m_continue_c_tids.push_back(tid);
+ break;
+
+ case eStateStepping:
+ if (gdb_process->GetUnixSignals()->SignalIsValid(signo))
+ gdb_process->m_continue_S_tids.push_back(std::make_pair(tid, signo));
+ else
+ gdb_process->m_continue_s_tids.push_back(tid);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void ThreadGDBRemote::RefreshStateAfterStop() {
+ // Invalidate all registers in our register context. We don't set "force" to
+ // true because the stop reply packet might have had some register values
+ // that were expedited and these will already be copied into the register
+ // context by the time this function gets called. The GDBRemoteRegisterContext
+ // class has been made smart enough to detect when it needs to invalidate
+ // which registers are valid by putting hooks in the register read and
+ // register supply functions where they check the process stop ID and do
+ // the right thing.
+ const bool force = false;
+ GetRegisterContext()->InvalidateIfNeeded(force);
+}
+
+bool ThreadGDBRemote::ThreadIDIsValid(lldb::tid_t thread) {
+ return thread != 0;
+}
+
+void ThreadGDBRemote::Dump(Log *log, uint32_t index) {}
+
+bool ThreadGDBRemote::ShouldStop(bool &step_more) { return true; }
+lldb::RegisterContextSP ThreadGDBRemote::GetRegisterContext() {
+ if (m_reg_context_sp.get() == NULL)
+ m_reg_context_sp = CreateRegisterContextForFrame(NULL);
+ return m_reg_context_sp;
}
-
-bool
-ThreadGDBRemote::ShouldStop (bool &step_more)
-{
- return true;
-}
lldb::RegisterContextSP
-ThreadGDBRemote::GetRegisterContext ()
-{
- if (m_reg_context_sp.get() == NULL)
- m_reg_context_sp = CreateRegisterContextForFrame (NULL);
- return m_reg_context_sp;
-}
+ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) {
+ lldb::RegisterContextSP reg_ctx_sp;
+ uint32_t concrete_frame_idx = 0;
-lldb::RegisterContextSP
-ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
-{
- lldb::RegisterContextSP reg_ctx_sp;
- uint32_t concrete_frame_idx = 0;
-
- if (frame)
- concrete_frame_idx = frame->GetConcreteFrameIndex ();
-
-
- if (concrete_frame_idx == 0)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
- // read_all_registers_at_once will be true if 'p' packet is not supported.
- bool read_all_registers_at_once = !gdb_process->GetGDBRemote().GetpPacketSupported (GetID());
- reg_ctx_sp.reset (new GDBRemoteRegisterContext (*this, concrete_frame_idx, gdb_process->m_register_info, read_all_registers_at_once));
- }
- }
- else
- {
- Unwind *unwinder = GetUnwinder ();
- if (unwinder)
- reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
- }
- return reg_ctx_sp;
-}
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex();
-bool
-ThreadGDBRemote::PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data)
-{
- GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get());
- assert (gdb_reg_ctx);
- return gdb_reg_ctx->PrivateSetRegisterValue(reg, data);
-}
-
-bool
-ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, uint64_t regval)
-{
- GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get());
- assert (gdb_reg_ctx);
- return gdb_reg_ctx->PrivateSetRegisterValue (reg, regval);
-}
-
-bool
-ThreadGDBRemote::CalculateStopInfo ()
-{
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- return static_cast<ProcessGDBRemote *>(process_sp.get())->CalculateThreadStopInfo(this);
- return false;
+ if (concrete_frame_idx == 0) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ ProcessGDBRemote *gdb_process =
+ static_cast<ProcessGDBRemote *>(process_sp.get());
+ // read_all_registers_at_once will be true if 'p' packet is not supported.
+ bool read_all_registers_at_once =
+ !gdb_process->GetGDBRemote().GetpPacketSupported(GetID());
+ reg_ctx_sp.reset(new GDBRemoteRegisterContext(
+ *this, concrete_frame_idx, gdb_process->m_register_info,
+ read_all_registers_at_once));
+ }
+ } else {
+ Unwind *unwinder = GetUnwinder();
+ if (unwinder)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
+ }
+ return reg_ctx_sp;
+}
+
+bool ThreadGDBRemote::PrivateSetRegisterValue(uint32_t reg,
+ llvm::ArrayRef<uint8_t> data) {
+ GDBRemoteRegisterContext *gdb_reg_ctx =
+ static_cast<GDBRemoteRegisterContext *>(GetRegisterContext().get());
+ assert(gdb_reg_ctx);
+ return gdb_reg_ctx->PrivateSetRegisterValue(reg, data);
+}
+
+bool ThreadGDBRemote::PrivateSetRegisterValue(uint32_t reg, uint64_t regval) {
+ GDBRemoteRegisterContext *gdb_reg_ctx =
+ static_cast<GDBRemoteRegisterContext *>(GetRegisterContext().get());
+ assert(gdb_reg_ctx);
+ return gdb_reg_ctx->PrivateSetRegisterValue(reg, regval);
+}
+
+bool ThreadGDBRemote::CalculateStopInfo() {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp)
+ return static_cast<ProcessGDBRemote *>(process_sp.get())
+ ->CalculateThreadStopInfo(this);
+ return false;
}
-
-
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h Tue Sep 6 15:57:50 2016
@@ -27,125 +27,94 @@ namespace process_gdb_remote {
class ProcessGDBRemote;
-class ThreadGDBRemote : public Thread
-{
+class ThreadGDBRemote : public Thread {
public:
- ThreadGDBRemote (Process &process, lldb::tid_t tid);
+ ThreadGDBRemote(Process &process, lldb::tid_t tid);
- ~ThreadGDBRemote() override;
+ ~ThreadGDBRemote() override;
- void
- WillResume (lldb::StateType resume_state) override;
+ void WillResume(lldb::StateType resume_state) override;
- void
- RefreshStateAfterStop() override;
+ void RefreshStateAfterStop() override;
- const char *
- GetName () override;
+ const char *GetName() override;
- const char *
- GetQueueName () override;
+ const char *GetQueueName() override;
- lldb::QueueKind
- GetQueueKind () override;
+ lldb::QueueKind GetQueueKind() override;
- lldb::queue_id_t
- GetQueueID () override;
+ lldb::queue_id_t GetQueueID() override;
- lldb::QueueSP
- GetQueue () override;
+ lldb::QueueSP GetQueue() override;
- lldb::addr_t
- GetQueueLibdispatchQueueAddress () override;
+ lldb::addr_t GetQueueLibdispatchQueueAddress() override;
- void
- SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t) override;
+ void SetQueueLibdispatchQueueAddress(lldb::addr_t dispatch_queue_t) override;
- bool
- ThreadHasQueueInformation () const override;
+ bool ThreadHasQueueInformation() const override;
- lldb::RegisterContextSP
- GetRegisterContext () override;
+ lldb::RegisterContextSP GetRegisterContext() override;
- lldb::RegisterContextSP
- CreateRegisterContextForFrame (StackFrame *frame) override;
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(StackFrame *frame) override;
- void
- Dump (Log *log, uint32_t index);
+ void Dump(Log *log, uint32_t index);
- static bool
- ThreadIDIsValid (lldb::tid_t thread);
+ static bool ThreadIDIsValid(lldb::tid_t thread);
- bool
- ShouldStop (bool &step_more);
+ bool ShouldStop(bool &step_more);
- const char *
- GetBasicInfoAsString ();
+ const char *GetBasicInfoAsString();
- void
- SetName (const char *name) override
- {
- if (name && name[0])
- m_thread_name.assign (name);
- else
- m_thread_name.clear();
- }
+ void SetName(const char *name) override {
+ if (name && name[0])
+ m_thread_name.assign(name);
+ else
+ m_thread_name.clear();
+ }
- lldb::addr_t
- GetThreadDispatchQAddr ()
- {
- return m_thread_dispatch_qaddr;
- }
+ lldb::addr_t GetThreadDispatchQAddr() { return m_thread_dispatch_qaddr; }
- void
- SetThreadDispatchQAddr (lldb::addr_t thread_dispatch_qaddr)
- {
- m_thread_dispatch_qaddr = thread_dispatch_qaddr;
- }
+ void SetThreadDispatchQAddr(lldb::addr_t thread_dispatch_qaddr) {
+ m_thread_dispatch_qaddr = thread_dispatch_qaddr;
+ }
- void
- ClearQueueInfo ();
-
- void
- SetQueueInfo (std::string &&queue_name, lldb::QueueKind queue_kind, uint64_t queue_serial, lldb::addr_t dispatch_queue_t, lldb_private::LazyBool associated_with_libdispatch_queue);
+ void ClearQueueInfo();
- lldb_private::LazyBool
- GetAssociatedWithLibdispatchQueue () override;
+ void SetQueueInfo(std::string &&queue_name, lldb::QueueKind queue_kind,
+ uint64_t queue_serial, lldb::addr_t dispatch_queue_t,
+ lldb_private::LazyBool associated_with_libdispatch_queue);
- void
- SetAssociatedWithLibdispatchQueue (lldb_private::LazyBool associated_with_libdispatch_queue) override;
+ lldb_private::LazyBool GetAssociatedWithLibdispatchQueue() override;
- StructuredData::ObjectSP
- FetchThreadExtendedInfo () override;
+ void SetAssociatedWithLibdispatchQueue(
+ lldb_private::LazyBool associated_with_libdispatch_queue) override;
+
+ StructuredData::ObjectSP FetchThreadExtendedInfo() override;
protected:
- friend class ProcessGDBRemote;
+ friend class ProcessGDBRemote;
- std::string m_thread_name;
- std::string m_dispatch_queue_name;
- lldb::addr_t m_thread_dispatch_qaddr;
- lldb::addr_t m_dispatch_queue_t;
- lldb::QueueKind m_queue_kind; // Queue info from stop reply/stop info for thread
- uint64_t m_queue_serial_number; // Queue info from stop reply/stop info for thread
- lldb_private::LazyBool m_associated_with_libdispatch_queue;
-
- bool
- PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data);
-
- bool
- PrivateSetRegisterValue (uint32_t reg,
- uint64_t regval);
-
- bool
- CachedQueueInfoIsValid() const
- {
- return m_queue_kind != lldb::eQueueKindUnknown;
- }
- void
- SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id);
+ std::string m_thread_name;
+ std::string m_dispatch_queue_name;
+ lldb::addr_t m_thread_dispatch_qaddr;
+ lldb::addr_t m_dispatch_queue_t;
+ lldb::QueueKind
+ m_queue_kind; // Queue info from stop reply/stop info for thread
+ uint64_t
+ m_queue_serial_number; // Queue info from stop reply/stop info for thread
+ lldb_private::LazyBool m_associated_with_libdispatch_queue;
+
+ bool PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data);
+
+ bool PrivateSetRegisterValue(uint32_t reg, uint64_t regval);
+
+ bool CachedQueueInfoIsValid() const {
+ return m_queue_kind != lldb::eQueueKindUnknown;
+ }
+ void SetStopInfoFromPacket(StringExtractor &stop_packet, uint32_t stop_id);
- bool
- CalculateStopInfo () override;
+ bool CalculateStopInfo() override;
};
} // namespace process_gdb_remote
Modified: lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp (original)
+++ lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp Tue Sep 6 15:57:50 2016
@@ -1,4 +1,5 @@
-//===-- ProcessMachCore.cpp ------------------------------------------*- C++ -*-===//
+//===-- ProcessMachCore.cpp ------------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -32,639 +33,576 @@
// Project includes
#include "ProcessMachCore.h"
-#include "ThreadMachCore.h"
#include "StopInfoMachException.h"
+#include "ThreadMachCore.h"
// Needed for the plug-in names for the dynamic loaders.
#include "lldb/Utility/SafeMachO.h"
-#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
+#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
using namespace lldb;
using namespace lldb_private;
-ConstString
-ProcessMachCore::GetPluginNameStatic()
-{
- static ConstString g_name("mach-o-core");
- return g_name;
-}
-
-const char *
-ProcessMachCore::GetPluginDescriptionStatic()
-{
- return "Mach-O core file debugging plug-in.";
-}
-
-void
-ProcessMachCore::Terminate()
-{
- PluginManager::UnregisterPlugin (ProcessMachCore::CreateInstance);
+ConstString ProcessMachCore::GetPluginNameStatic() {
+ static ConstString g_name("mach-o-core");
+ return g_name;
}
+const char *ProcessMachCore::GetPluginDescriptionStatic() {
+ return "Mach-O core file debugging plug-in.";
+}
-lldb::ProcessSP
-ProcessMachCore::CreateInstance (lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file)
-{
- lldb::ProcessSP process_sp;
- if (crash_file)
- {
- const size_t header_size = sizeof(llvm::MachO::mach_header);
- lldb::DataBufferSP data_sp (crash_file->ReadFileContents(0, header_size));
- if (data_sp && data_sp->GetByteSize() == header_size)
- {
- DataExtractor data(data_sp, lldb::eByteOrderLittle, 4);
-
- lldb::offset_t data_offset = 0;
- llvm::MachO::mach_header mach_header;
- if (ObjectFileMachO::ParseHeader(data, &data_offset, mach_header))
- {
- if (mach_header.filetype == llvm::MachO::MH_CORE)
- process_sp.reset(new ProcessMachCore (target_sp, listener_sp, *crash_file));
- }
- }
-
- }
- return process_sp;
-}
-
-bool
-ProcessMachCore::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name)
-{
- if (plugin_specified_by_name)
- return true;
+void ProcessMachCore::Terminate() {
+ PluginManager::UnregisterPlugin(ProcessMachCore::CreateInstance);
+}
+
+lldb::ProcessSP ProcessMachCore::CreateInstance(lldb::TargetSP target_sp,
+ ListenerSP listener_sp,
+ const FileSpec *crash_file) {
+ lldb::ProcessSP process_sp;
+ if (crash_file) {
+ const size_t header_size = sizeof(llvm::MachO::mach_header);
+ lldb::DataBufferSP data_sp(crash_file->ReadFileContents(0, header_size));
+ if (data_sp && data_sp->GetByteSize() == header_size) {
+ DataExtractor data(data_sp, lldb::eByteOrderLittle, 4);
- // For now we are just making sure the file exists for a given module
- if (!m_core_module_sp && m_core_file.Exists())
- {
- // Don't add the Target's architecture to the ModuleSpec - we may be working
- // with a core file that doesn't have the correct cpusubtype in the header
- // but we should still try to use it - ModuleSpecList::FindMatchingModuleSpec
- // enforces a strict arch mach.
- ModuleSpec core_module_spec(m_core_file);
- Error error (ModuleList::GetSharedModule (core_module_spec,
- m_core_module_sp,
- NULL,
- NULL,
- NULL));
-
- if (m_core_module_sp)
- {
- ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
- if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
- return true;
- }
+ lldb::offset_t data_offset = 0;
+ llvm::MachO::mach_header mach_header;
+ if (ObjectFileMachO::ParseHeader(data, &data_offset, mach_header)) {
+ if (mach_header.filetype == llvm::MachO::MH_CORE)
+ process_sp.reset(
+ new ProcessMachCore(target_sp, listener_sp, *crash_file));
+ }
}
- return false;
+ }
+ return process_sp;
+}
+
+bool ProcessMachCore::CanDebug(lldb::TargetSP target_sp,
+ 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
+ if (!m_core_module_sp && m_core_file.Exists()) {
+ // Don't add the Target's architecture to the ModuleSpec - we may be working
+ // with a core file that doesn't have the correct cpusubtype in the header
+ // but we should still try to use it -
+ // ModuleSpecList::FindMatchingModuleSpec
+ // enforces a strict arch mach.
+ ModuleSpec core_module_spec(m_core_file);
+ Error error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,
+ NULL, NULL, NULL));
+
+ if (m_core_module_sp) {
+ ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+ if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
+ return true;
+ }
+ }
+ return false;
}
//----------------------------------------------------------------------
// ProcessMachCore constructor
//----------------------------------------------------------------------
-ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec &core_file)
- : Process(target_sp, listener_sp),
- m_core_aranges(),
- m_core_range_infos(),
- m_core_module_sp(),
- m_core_file(core_file),
+ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp,
+ ListenerSP listener_sp,
+ const FileSpec &core_file)
+ : Process(target_sp, listener_sp), m_core_aranges(), m_core_range_infos(),
+ m_core_module_sp(), m_core_file(core_file),
m_dyld_addr(LLDB_INVALID_ADDRESS),
- m_mach_kernel_addr(LLDB_INVALID_ADDRESS),
- m_dyld_plugin_name()
-{
-}
+ m_mach_kernel_addr(LLDB_INVALID_ADDRESS), m_dyld_plugin_name() {}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-ProcessMachCore::~ProcessMachCore()
-{
- 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();
+ProcessMachCore::~ProcessMachCore() {
+ 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
//----------------------------------------------------------------------
-ConstString
-ProcessMachCore::GetPluginName()
-{
- return GetPluginNameStatic();
-}
-
-uint32_t
-ProcessMachCore::GetPluginVersion()
-{
- return 1;
-}
-
-bool
-ProcessMachCore::GetDynamicLoaderAddress (lldb::addr_t addr)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_PROCESS));
- llvm::MachO::mach_header header;
- Error error;
- if (DoReadMemory (addr, &header, sizeof(header), error) != sizeof(header))
- return false;
- if (header.magic == llvm::MachO::MH_CIGAM ||
- header.magic == llvm::MachO::MH_CIGAM_64)
- {
- header.magic = llvm::ByteSwap_32(header.magic);
- header.cputype = llvm::ByteSwap_32(header.cputype);
- header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype);
- header.filetype = llvm::ByteSwap_32(header.filetype);
- header.ncmds = llvm::ByteSwap_32(header.ncmds);
- header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds);
- header.flags = llvm::ByteSwap_32(header.flags);
- }
-
- // TODO: swap header if needed...
- //printf("0x%16.16" PRIx64 ": magic = 0x%8.8x, file_type= %u\n", vaddr, header.magic, header.filetype);
- if (header.magic == llvm::MachO::MH_MAGIC ||
- header.magic == llvm::MachO::MH_MAGIC_64)
- {
- // Check MH_EXECUTABLE to see if we can find the mach image
- // that contains the shared library list. The dynamic loader
- // (dyld) is what contains the list for user applications,
- // and the mach kernel contains a global that has the list
- // of kexts to load
- switch (header.filetype)
- {
- case llvm::MachO::MH_DYLINKER:
- //printf("0x%16.16" PRIx64 ": file_type = MH_DYLINKER\n", vaddr);
- // Address of dyld "struct mach_header" in the core file
- if (log)
- log->Printf ("ProcessMachCore::GetDynamicLoaderAddress found a user process dyld binary image at 0x%" PRIx64, addr);
- m_dyld_addr = addr;
- return true;
-
- case llvm::MachO::MH_EXECUTE:
- //printf("0x%16.16" PRIx64 ": file_type = MH_EXECUTE\n", vaddr);
- // Check MH_EXECUTABLE file types to see if the dynamic link object flag
- // is NOT set. If it isn't, then we have a mach_kernel.
- if ((header.flags & llvm::MachO::MH_DYLDLINK) == 0)
- {
- if (log)
- log->Printf ("ProcessMachCore::GetDynamicLoaderAddress found a mach kernel binary image at 0x%" PRIx64, addr);
- // Address of the mach kernel "struct mach_header" in the core file.
- m_mach_kernel_addr = addr;
- return true;
- }
- break;
- }
- }
+ConstString ProcessMachCore::GetPluginName() { return GetPluginNameStatic(); }
+
+uint32_t ProcessMachCore::GetPluginVersion() { return 1; }
+
+bool ProcessMachCore::GetDynamicLoaderAddress(lldb::addr_t addr) {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER |
+ LIBLLDB_LOG_PROCESS));
+ llvm::MachO::mach_header header;
+ Error error;
+ if (DoReadMemory(addr, &header, sizeof(header), error) != sizeof(header))
return false;
+ if (header.magic == llvm::MachO::MH_CIGAM ||
+ header.magic == llvm::MachO::MH_CIGAM_64) {
+ header.magic = llvm::ByteSwap_32(header.magic);
+ header.cputype = llvm::ByteSwap_32(header.cputype);
+ header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype);
+ header.filetype = llvm::ByteSwap_32(header.filetype);
+ header.ncmds = llvm::ByteSwap_32(header.ncmds);
+ header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds);
+ header.flags = llvm::ByteSwap_32(header.flags);
+ }
+
+ // TODO: swap header if needed...
+ // printf("0x%16.16" PRIx64 ": magic = 0x%8.8x, file_type= %u\n", vaddr,
+ // header.magic, header.filetype);
+ if (header.magic == llvm::MachO::MH_MAGIC ||
+ header.magic == llvm::MachO::MH_MAGIC_64) {
+ // Check MH_EXECUTABLE to see if we can find the mach image
+ // that contains the shared library list. The dynamic loader
+ // (dyld) is what contains the list for user applications,
+ // and the mach kernel contains a global that has the list
+ // of kexts to load
+ switch (header.filetype) {
+ case llvm::MachO::MH_DYLINKER:
+ // printf("0x%16.16" PRIx64 ": file_type = MH_DYLINKER\n", vaddr);
+ // Address of dyld "struct mach_header" in the core file
+ if (log)
+ log->Printf("ProcessMachCore::GetDynamicLoaderAddress found a user "
+ "process dyld binary image at 0x%" PRIx64,
+ addr);
+ m_dyld_addr = addr;
+ return true;
+
+ case llvm::MachO::MH_EXECUTE:
+ // printf("0x%16.16" PRIx64 ": file_type = MH_EXECUTE\n", vaddr);
+ // Check MH_EXECUTABLE file types to see if the dynamic link object flag
+ // is NOT set. If it isn't, then we have a mach_kernel.
+ if ((header.flags & llvm::MachO::MH_DYLDLINK) == 0) {
+ if (log)
+ log->Printf("ProcessMachCore::GetDynamicLoaderAddress found a mach "
+ "kernel binary image at 0x%" PRIx64,
+ addr);
+ // Address of the mach kernel "struct mach_header" in the core file.
+ m_mach_kernel_addr = addr;
+ return true;
+ }
+ break;
+ }
+ }
+ return false;
}
//----------------------------------------------------------------------
// Process Control
//----------------------------------------------------------------------
-Error
-ProcessMachCore::DoLoadCore ()
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_PROCESS));
- Error error;
- if (!m_core_module_sp)
- {
- error.SetErrorString ("invalid core module");
- return error;
- }
+Error ProcessMachCore::DoLoadCore() {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER |
+ LIBLLDB_LOG_PROCESS));
+ Error error;
+ if (!m_core_module_sp) {
+ error.SetErrorString("invalid core module");
+ return error;
+ }
- ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
- if (core_objfile == NULL)
- {
- error.SetErrorString ("invalid core object file");
- return error;
- }
-
- if (core_objfile->GetNumThreadContexts() == 0)
- {
- error.SetErrorString ("core file doesn't contain any LC_THREAD load commands, or the LC_THREAD architecture is not supported in this lldb");
- return error;
- }
-
- SectionList *section_list = core_objfile->GetSectionList();
- if (section_list == NULL)
- {
- error.SetErrorString ("core file has no sections");
- return error;
- }
-
- const uint32_t num_sections = section_list->GetNumSections(0);
- if (num_sections == 0)
- {
- error.SetErrorString ("core file has no sections");
- return error;
- }
-
- SetCanJIT(false);
-
- llvm::MachO::mach_header header;
- DataExtractor data (&header,
- sizeof(header),
- m_core_module_sp->GetArchitecture().GetByteOrder(),
- m_core_module_sp->GetArchitecture().GetAddressByteSize());
-
- bool ranges_are_sorted = true;
- addr_t vm_addr = 0;
- for (uint32_t i=0; i<num_sections; ++i)
- {
- Section *section = section_list->GetSectionAtIndex (i).get();
- if (section)
- {
- lldb::addr_t section_vm_addr = section->GetFileAddress();
- FileRange file_range (section->GetFileOffset(), section->GetFileSize());
- VMRangeToFileOffset::Entry range_entry (section_vm_addr,
- section->GetByteSize(),
- file_range);
-
- if (vm_addr > section_vm_addr)
- ranges_are_sorted = false;
- vm_addr = section->GetFileAddress();
- VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
-// printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n",
-// i,
-// range_entry.GetRangeBase(),
-// range_entry.GetRangeEnd(),
-// range_entry.data.GetRangeBase(),
-// range_entry.data.GetRangeEnd());
-
- if (last_entry &&
- last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
- last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
- {
- last_entry->SetRangeEnd (range_entry.GetRangeEnd());
- last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
- //puts("combine");
- }
- else
- {
- m_core_aranges.Append(range_entry);
- }
- // Some core files don't fill in the permissions correctly. If that is the case
- // assume read + execute so clients don't think the memory is not readable,
- // or executable. The memory isn't writable since this plug-in doesn't implement
- // DoWriteMemory.
- uint32_t permissions = section->GetPermissions();
- if (permissions == 0)
- permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
- m_core_range_infos.Append(
- VMRangeToPermissions::Entry(section_vm_addr, section->GetByteSize(), permissions));
- }
- }
- if (!ranges_are_sorted)
- {
- m_core_aranges.Sort();
- m_core_range_infos.Sort();
- }
-
- if (m_dyld_addr == LLDB_INVALID_ADDRESS || m_mach_kernel_addr == LLDB_INVALID_ADDRESS)
- {
- // We need to locate the main executable in the memory ranges
- // we have in the core file. We need to search for both a user-process dyld binary
- // and a kernel binary in memory; we must look at all the pages in the binary so
- // we don't miss one or the other. Step through all memory segments searching for
- // a kernel binary and for a user process dyld -- we'll decide which to prefer
- // later if both are present.
-
- const size_t num_core_aranges = m_core_aranges.GetSize();
- for (size_t i = 0; i < num_core_aranges; ++i)
- {
- const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i);
- lldb::addr_t section_vm_addr_start = entry->GetRangeBase();
- lldb::addr_t section_vm_addr_end = entry->GetRangeEnd();
- for (lldb::addr_t section_vm_addr = section_vm_addr_start;
- section_vm_addr < section_vm_addr_end;
- section_vm_addr += 0x1000)
- {
- GetDynamicLoaderAddress (section_vm_addr);
- }
- }
- }
-
-
- if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS)
- {
- // In the case of multiple kernel images found in the core file via exhaustive
- // search, we may not pick the correct one. See if the DynamicLoaderDarwinKernel's
- // search heuristics might identify the correct one.
- // Most of the time, I expect the address from SearchForDarwinKernel() will be the
- // same as the address we found via exhaustive search.
-
- if (GetTarget().GetArchitecture().IsValid() == false && m_core_module_sp.get())
- {
- GetTarget().SetArchitecture (m_core_module_sp->GetArchitecture());
- }
-
- // SearchForDarwinKernel will end up calling back into this this class in the GetImageInfoAddress
- // method which will give it the m_mach_kernel_addr/m_dyld_addr it already has. Save that aside
- // and set m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily so
- // DynamicLoaderDarwinKernel does a real search for the kernel using its own heuristics.
-
- addr_t saved_mach_kernel_addr = m_mach_kernel_addr;
- addr_t saved_user_dyld_addr = m_dyld_addr;
- m_mach_kernel_addr = LLDB_INVALID_ADDRESS;
- m_dyld_addr = LLDB_INVALID_ADDRESS;
-
- addr_t better_kernel_address = DynamicLoaderDarwinKernel::SearchForDarwinKernel (this);
-
- m_mach_kernel_addr = saved_mach_kernel_addr;
- m_dyld_addr = saved_user_dyld_addr;
-
- if (better_kernel_address != LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf ("ProcessMachCore::DoLoadCore: Using the kernel address from DynamicLoaderDarwinKernel");
- m_mach_kernel_addr = better_kernel_address;
- }
- }
-
-
- // If we found both a user-process dyld and a kernel binary, we need to decide
- // which to prefer.
- if (GetCorefilePreference() == eKernelCorefile)
- {
- if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf ("ProcessMachCore::DoLoadCore: Using kernel corefile image at 0x%" PRIx64, m_mach_kernel_addr);
- m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
- }
- else if (m_dyld_addr != LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf ("ProcessMachCore::DoLoadCore: Using user process dyld image at 0x%" PRIx64, m_dyld_addr);
- m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
- }
- }
- else
- {
- if (m_dyld_addr != LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf ("ProcessMachCore::DoLoadCore: Using user process dyld image at 0x%" PRIx64, m_dyld_addr);
- m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
- }
- else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf ("ProcessMachCore::DoLoadCore: Using kernel corefile image at 0x%" PRIx64, m_mach_kernel_addr);
- m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
- }
- }
-
- if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic())
- {
- // For non-user process core files, the permissions on the core file segments are usually
- // meaningless, they may be just "read", because we're dealing with kernel coredumps or
- // early startup coredumps and the dumper is grabbing pages of memory without knowing
- // what they are. If they aren't marked as "exeuctable", that can break the unwinder
- // which will check a pc value to see if it is in an executable segment and stop the
- // backtrace early if it is not ("executable" and "unknown" would both be fine, but
- // "not executable" will break the unwinder).
- size_t core_range_infos_size = m_core_range_infos.GetSize();
- for (size_t i = 0; i < core_range_infos_size; i++)
- {
- VMRangeToPermissions::Entry *ent = m_core_range_infos.GetMutableEntryAtIndex (i);
- ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
- }
- }
-
- // Even if the architecture is set in the target, we need to override
- // it to match the core file which is always single arch.
- ArchSpec arch (m_core_module_sp->GetArchitecture());
- if (arch.GetCore() == ArchSpec::eCore_x86_32_i486)
- {
- arch.SetTriple ("i386", GetTarget().GetPlatform().get());
- }
- if (arch.IsValid())
- GetTarget().SetArchitecture(arch);
+ ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+ if (core_objfile == NULL) {
+ error.SetErrorString("invalid core object file");
+ return error;
+ }
+ if (core_objfile->GetNumThreadContexts() == 0) {
+ error.SetErrorString("core file doesn't contain any LC_THREAD load "
+ "commands, or the LC_THREAD architecture is not "
+ "supported in this lldb");
return error;
-}
+ }
-lldb_private::DynamicLoader *
-ProcessMachCore::GetDynamicLoader ()
-{
- if (m_dyld_ap.get() == NULL)
- m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString()));
- return m_dyld_ap.get();
-}
-
-bool
-ProcessMachCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
-{
- if (old_thread_list.GetSize(false) == 0)
- {
- // Make up the thread the first time this is called so we can setup our one and only
- // core thread state.
- ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
-
- if (core_objfile)
- {
- const uint32_t num_threads = core_objfile->GetNumThreadContexts ();
- for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
- {
- ThreadSP thread_sp(new ThreadMachCore (*this, tid));
- new_thread_list.AddThread (thread_sp);
- }
- }
- }
- else
- {
- const uint32_t num_threads = old_thread_list.GetSize(false);
- for (uint32_t i=0; i<num_threads; ++i)
- new_thread_list.AddThread (old_thread_list.GetThreadAtIndex (i, false));
- }
- return new_thread_list.GetSize(false) > 0;
-}
-
-void
-ProcessMachCore::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
-ProcessMachCore::DoDestroy ()
-{
- return Error();
+ SectionList *section_list = core_objfile->GetSectionList();
+ if (section_list == NULL) {
+ error.SetErrorString("core file has no sections");
+ return error;
+ }
+
+ const uint32_t num_sections = section_list->GetNumSections(0);
+ if (num_sections == 0) {
+ error.SetErrorString("core file has no sections");
+ return error;
+ }
+
+ SetCanJIT(false);
+
+ llvm::MachO::mach_header header;
+ DataExtractor data(&header, sizeof(header),
+ m_core_module_sp->GetArchitecture().GetByteOrder(),
+ m_core_module_sp->GetArchitecture().GetAddressByteSize());
+
+ bool ranges_are_sorted = true;
+ addr_t vm_addr = 0;
+ for (uint32_t i = 0; i < num_sections; ++i) {
+ Section *section = section_list->GetSectionAtIndex(i).get();
+ if (section) {
+ lldb::addr_t section_vm_addr = section->GetFileAddress();
+ FileRange file_range(section->GetFileOffset(), section->GetFileSize());
+ VMRangeToFileOffset::Entry range_entry(
+ section_vm_addr, section->GetByteSize(), file_range);
+
+ if (vm_addr > section_vm_addr)
+ ranges_are_sorted = false;
+ vm_addr = section->GetFileAddress();
+ VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
+ // printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " -
+ // 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n",
+ // i,
+ // range_entry.GetRangeBase(),
+ // range_entry.GetRangeEnd(),
+ // range_entry.data.GetRangeBase(),
+ // range_entry.data.GetRangeEnd());
+
+ if (last_entry &&
+ last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
+ last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) {
+ last_entry->SetRangeEnd(range_entry.GetRangeEnd());
+ last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
+ // puts("combine");
+ } else {
+ m_core_aranges.Append(range_entry);
+ }
+ // Some core files don't fill in the permissions correctly. If that is the
+ // case
+ // assume read + execute so clients don't think the memory is not
+ // readable,
+ // or executable. The memory isn't writable since this plug-in doesn't
+ // implement
+ // DoWriteMemory.
+ uint32_t permissions = section->GetPermissions();
+ if (permissions == 0)
+ permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
+ m_core_range_infos.Append(VMRangeToPermissions::Entry(
+ section_vm_addr, section->GetByteSize(), permissions));
+ }
+ }
+ if (!ranges_are_sorted) {
+ m_core_aranges.Sort();
+ m_core_range_infos.Sort();
+ }
+
+ if (m_dyld_addr == LLDB_INVALID_ADDRESS ||
+ m_mach_kernel_addr == LLDB_INVALID_ADDRESS) {
+ // We need to locate the main executable in the memory ranges
+ // we have in the core file. We need to search for both a user-process dyld
+ // binary
+ // and a kernel binary in memory; we must look at all the pages in the
+ // binary so
+ // we don't miss one or the other. Step through all memory segments
+ // searching for
+ // a kernel binary and for a user process dyld -- we'll decide which to
+ // prefer
+ // later if both are present.
+
+ const size_t num_core_aranges = m_core_aranges.GetSize();
+ for (size_t i = 0; i < num_core_aranges; ++i) {
+ const VMRangeToFileOffset::Entry *entry =
+ m_core_aranges.GetEntryAtIndex(i);
+ lldb::addr_t section_vm_addr_start = entry->GetRangeBase();
+ lldb::addr_t section_vm_addr_end = entry->GetRangeEnd();
+ for (lldb::addr_t section_vm_addr = section_vm_addr_start;
+ section_vm_addr < section_vm_addr_end; section_vm_addr += 0x1000) {
+ GetDynamicLoaderAddress(section_vm_addr);
+ }
+ }
+ }
+
+ if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
+ // In the case of multiple kernel images found in the core file via
+ // exhaustive
+ // search, we may not pick the correct one. See if the
+ // DynamicLoaderDarwinKernel's
+ // search heuristics might identify the correct one.
+ // Most of the time, I expect the address from SearchForDarwinKernel() will
+ // be the
+ // same as the address we found via exhaustive search.
+
+ if (GetTarget().GetArchitecture().IsValid() == false &&
+ m_core_module_sp.get()) {
+ GetTarget().SetArchitecture(m_core_module_sp->GetArchitecture());
+ }
+
+ // SearchForDarwinKernel will end up calling back into this this class in
+ // the GetImageInfoAddress
+ // method which will give it the m_mach_kernel_addr/m_dyld_addr it already
+ // has. Save that aside
+ // and set m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily
+ // so
+ // DynamicLoaderDarwinKernel does a real search for the kernel using its own
+ // heuristics.
+
+ addr_t saved_mach_kernel_addr = m_mach_kernel_addr;
+ addr_t saved_user_dyld_addr = m_dyld_addr;
+ m_mach_kernel_addr = LLDB_INVALID_ADDRESS;
+ m_dyld_addr = LLDB_INVALID_ADDRESS;
+
+ addr_t better_kernel_address =
+ DynamicLoaderDarwinKernel::SearchForDarwinKernel(this);
+
+ m_mach_kernel_addr = saved_mach_kernel_addr;
+ m_dyld_addr = saved_user_dyld_addr;
+
+ if (better_kernel_address != LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("ProcessMachCore::DoLoadCore: Using the kernel address "
+ "from DynamicLoaderDarwinKernel");
+ m_mach_kernel_addr = better_kernel_address;
+ }
+ }
+
+ // If we found both a user-process dyld and a kernel binary, we need to decide
+ // which to prefer.
+ if (GetCorefilePreference() == eKernelCorefile) {
+ if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("ProcessMachCore::DoLoadCore: Using kernel corefile image "
+ "at 0x%" PRIx64,
+ m_mach_kernel_addr);
+ m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
+ } else if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("ProcessMachCore::DoLoadCore: Using user process dyld "
+ "image at 0x%" PRIx64,
+ m_dyld_addr);
+ m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
+ }
+ } else {
+ if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("ProcessMachCore::DoLoadCore: Using user process dyld "
+ "image at 0x%" PRIx64,
+ m_dyld_addr);
+ m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
+ } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("ProcessMachCore::DoLoadCore: Using kernel corefile image "
+ "at 0x%" PRIx64,
+ m_mach_kernel_addr);
+ m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
+ }
+ }
+
+ if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic()) {
+ // For non-user process core files, the permissions on the core file
+ // segments are usually
+ // meaningless, they may be just "read", because we're dealing with kernel
+ // coredumps or
+ // early startup coredumps and the dumper is grabbing pages of memory
+ // without knowing
+ // what they are. If they aren't marked as "exeuctable", that can break the
+ // unwinder
+ // which will check a pc value to see if it is in an executable segment and
+ // stop the
+ // backtrace early if it is not ("executable" and "unknown" would both be
+ // fine, but
+ // "not executable" will break the unwinder).
+ size_t core_range_infos_size = m_core_range_infos.GetSize();
+ for (size_t i = 0; i < core_range_infos_size; i++) {
+ VMRangeToPermissions::Entry *ent =
+ m_core_range_infos.GetMutableEntryAtIndex(i);
+ ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
+ }
+ }
+
+ // Even if the architecture is set in the target, we need to override
+ // it to match the core file which is always single arch.
+ ArchSpec arch(m_core_module_sp->GetArchitecture());
+ if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) {
+ arch.SetTriple("i386", GetTarget().GetPlatform().get());
+ }
+ if (arch.IsValid())
+ GetTarget().SetArchitecture(arch);
+
+ return error;
+}
+
+lldb_private::DynamicLoader *ProcessMachCore::GetDynamicLoader() {
+ if (m_dyld_ap.get() == NULL)
+ m_dyld_ap.reset(DynamicLoader::FindPlugin(
+ this,
+ m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString()));
+ return m_dyld_ap.get();
+}
+
+bool ProcessMachCore::UpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) {
+ if (old_thread_list.GetSize(false) == 0) {
+ // Make up the thread the first time this is called so we can setup our one
+ // and only
+ // core thread state.
+ ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+
+ if (core_objfile) {
+ const uint32_t num_threads = core_objfile->GetNumThreadContexts();
+ for (lldb::tid_t tid = 0; tid < num_threads; ++tid) {
+ ThreadSP thread_sp(new ThreadMachCore(*this, tid));
+ new_thread_list.AddThread(thread_sp);
+ }
+ }
+ } else {
+ const uint32_t num_threads = old_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < num_threads; ++i)
+ new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false));
+ }
+ return new_thread_list.GetSize(false) > 0;
+}
+
+void ProcessMachCore::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 ProcessMachCore::DoDestroy() { return Error(); }
+
//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------
-bool
-ProcessMachCore::IsAlive ()
-{
- return true;
-}
+bool ProcessMachCore::IsAlive() { return true; }
-bool
-ProcessMachCore::WarnBeforeDetach () const
-{
- return false;
-}
+bool ProcessMachCore::WarnBeforeDetach() const { return false; }
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
-size_t
-ProcessMachCore::ReadMemory (addr_t addr, void *buf, size_t size, Error &error)
-{
- // Don't allow the caching that lldb_private::Process::ReadMemory does
- // since in core files we have it all cached our our core file anyway.
- return DoReadMemory (addr, buf, size, error);
+size_t ProcessMachCore::ReadMemory(addr_t addr, void *buf, size_t size,
+ Error &error) {
+ // Don't allow the caching that lldb_private::Process::ReadMemory does
+ // since in core files we have it all cached our our core file anyway.
+ return DoReadMemory(addr, buf, size, error);
+}
+
+size_t ProcessMachCore::DoReadMemory(addr_t addr, void *buf, size_t size,
+ Error &error) {
+ ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+ size_t bytes_read = 0;
+
+ if (core_objfile) {
+ //----------------------------------------------------------------------
+ // Segments are not always contiguous in mach-o core files. We have core
+ // files that have segments like:
+ // Address Size File off File size
+ // ---------- ---------- ---------- ----------
+ // LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- --- 0
+ // 0x00000000 __TEXT
+ // LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000 --- --- 0
+ // 0x00000000 __TEXT
+ // LC_SEGMENT 0x000f7000 0x00001000 0x1d60aee8 0x00001000 --- --- 0
+ // 0x00000000 __TEXT
+ //
+ // Any if the user executes the following command:
+ //
+ // (lldb) mem read 0xf6ff0
+ //
+ // We would attempt to read 32 bytes from 0xf6ff0 but would only
+ // get 16 unless we loop through consecutive memory ranges that are
+ // contiguous in the address space, but not in the file data.
+ //----------------------------------------------------------------------
+ while (bytes_read < size) {
+ const addr_t curr_addr = addr + bytes_read;
+ const VMRangeToFileOffset::Entry *core_memory_entry =
+ m_core_aranges.FindEntryThatContains(curr_addr);
+
+ if (core_memory_entry) {
+ const addr_t offset = curr_addr - core_memory_entry->GetRangeBase();
+ const addr_t bytes_left = core_memory_entry->GetRangeEnd() - curr_addr;
+ const size_t bytes_to_read =
+ std::min(size - bytes_read, (size_t)bytes_left);
+ const size_t curr_bytes_read = core_objfile->CopyData(
+ core_memory_entry->data.GetRangeBase() + offset, bytes_to_read,
+ (char *)buf + bytes_read);
+ if (curr_bytes_read == 0)
+ break;
+ bytes_read += curr_bytes_read;
+ } else {
+ // Only set the error if we didn't read any bytes
+ if (bytes_read == 0)
+ error.SetErrorStringWithFormat(
+ "core file does not contain 0x%" PRIx64, curr_addr);
+ break;
+ }
+ }
+ }
+
+ return bytes_read;
+}
+
+Error ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr,
+ MemoryRegionInfo ®ion_info) {
+ region_info.Clear();
+ const VMRangeToPermissions::Entry *permission_entry =
+ m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);
+ if (permission_entry) {
+ if (permission_entry->Contains(load_addr)) {
+ region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());
+ region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());
+ const Flags permissions(permission_entry->data);
+ region_info.SetReadable(permissions.Test(ePermissionsReadable)
+ ? MemoryRegionInfo::eYes
+ : MemoryRegionInfo::eNo);
+ region_info.SetWritable(permissions.Test(ePermissionsWritable)
+ ? MemoryRegionInfo::eYes
+ : MemoryRegionInfo::eNo);
+ region_info.SetExecutable(permissions.Test(ePermissionsExecutable)
+ ? MemoryRegionInfo::eYes
+ : MemoryRegionInfo::eNo);
+ region_info.SetMapped(MemoryRegionInfo::eYes);
+ } else if (load_addr < permission_entry->GetRangeBase()) {
+ region_info.GetRange().SetRangeBase(load_addr);
+ region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());
+ region_info.SetReadable(MemoryRegionInfo::eNo);
+ region_info.SetWritable(MemoryRegionInfo::eNo);
+ region_info.SetExecutable(MemoryRegionInfo::eNo);
+ region_info.SetMapped(MemoryRegionInfo::eNo);
+ }
+ return Error();
+ }
+
+ region_info.GetRange().SetRangeBase(load_addr);
+ region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
+ region_info.SetReadable(MemoryRegionInfo::eNo);
+ region_info.SetWritable(MemoryRegionInfo::eNo);
+ region_info.SetExecutable(MemoryRegionInfo::eNo);
+ region_info.SetMapped(MemoryRegionInfo::eNo);
+ return Error();
}
-size_t
-ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
-{
- ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
- size_t bytes_read = 0;
+void ProcessMachCore::Clear() { m_thread_list.Clear(); }
- if (core_objfile)
- {
- //----------------------------------------------------------------------
- // Segments are not always contiguous in mach-o core files. We have core
- // files that have segments like:
- // Address Size File off File size
- // ---------- ---------- ---------- ----------
- // LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- --- 0 0x00000000 __TEXT
- // LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000 --- --- 0 0x00000000 __TEXT
- // LC_SEGMENT 0x000f7000 0x00001000 0x1d60aee8 0x00001000 --- --- 0 0x00000000 __TEXT
- //
- // Any if the user executes the following command:
- //
- // (lldb) mem read 0xf6ff0
- //
- // We would attempt to read 32 bytes from 0xf6ff0 but would only
- // get 16 unless we loop through consecutive memory ranges that are
- // contiguous in the address space, but not in the file data.
- //----------------------------------------------------------------------
- while (bytes_read < size)
- {
- const addr_t curr_addr = addr + bytes_read;
- const VMRangeToFileOffset::Entry *core_memory_entry = m_core_aranges.FindEntryThatContains(curr_addr);
-
- if (core_memory_entry)
- {
- const addr_t offset = curr_addr - core_memory_entry->GetRangeBase();
- const addr_t bytes_left = core_memory_entry->GetRangeEnd() - curr_addr;
- const size_t bytes_to_read = std::min(size - bytes_read, (size_t)bytes_left);
- const size_t curr_bytes_read = core_objfile->CopyData(core_memory_entry->data.GetRangeBase() + offset,
- bytes_to_read, (char *)buf + bytes_read);
- if (curr_bytes_read == 0)
- break;
- bytes_read += curr_bytes_read;
- }
- else
- {
- // Only set the error if we didn't read any bytes
- if (bytes_read == 0)
- error.SetErrorStringWithFormat("core file does not contain 0x%" PRIx64, curr_addr);
- break;
- }
- }
- }
-
- return bytes_read;
-}
-
-Error
-ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr, MemoryRegionInfo ®ion_info)
-{
- region_info.Clear();
- const VMRangeToPermissions::Entry *permission_entry = m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);
- if (permission_entry)
- {
- if (permission_entry->Contains(load_addr))
- {
- region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());
- region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());
- const Flags permissions(permission_entry->data);
- region_info.SetReadable(permissions.Test(ePermissionsReadable) ? MemoryRegionInfo::eYes
- : MemoryRegionInfo::eNo);
- region_info.SetWritable(permissions.Test(ePermissionsWritable) ? MemoryRegionInfo::eYes
- : MemoryRegionInfo::eNo);
- region_info.SetExecutable(permissions.Test(ePermissionsExecutable) ? MemoryRegionInfo::eYes
- : MemoryRegionInfo::eNo);
- region_info.SetMapped(MemoryRegionInfo::eYes);
- }
- else if (load_addr < permission_entry->GetRangeBase())
- {
- region_info.GetRange().SetRangeBase(load_addr);
- region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());
- region_info.SetReadable(MemoryRegionInfo::eNo);
- region_info.SetWritable(MemoryRegionInfo::eNo);
- region_info.SetExecutable(MemoryRegionInfo::eNo);
- region_info.SetMapped(MemoryRegionInfo::eNo);
- }
- return Error();
- }
-
- region_info.GetRange().SetRangeBase(load_addr);
- region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
- region_info.SetReadable(MemoryRegionInfo::eNo);
- region_info.SetWritable(MemoryRegionInfo::eNo);
- region_info.SetExecutable(MemoryRegionInfo::eNo);
- region_info.SetMapped(MemoryRegionInfo::eNo);
- return Error();
+void ProcessMachCore::Initialize() {
+ static std::once_flag g_once_flag;
+
+ std::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+ });
}
-void
-ProcessMachCore::Clear()
-{
- m_thread_list.Clear();
-}
-
-void
-ProcessMachCore::Initialize()
-{
- static std::once_flag g_once_flag;
-
- std::call_once(g_once_flag, []() {
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance);
- });
-}
-
-addr_t
-ProcessMachCore::GetImageInfoAddress()
-{
- // If we found both a user-process dyld and a kernel binary, we need to decide
- // which to prefer.
- if (GetCorefilePreference() == eKernelCorefile)
- {
- if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS)
- {
- return m_mach_kernel_addr;
- }
- return m_dyld_addr;
- }
- else
- {
- if (m_dyld_addr != LLDB_INVALID_ADDRESS)
- {
- return m_dyld_addr;
- }
- return m_mach_kernel_addr;
+addr_t ProcessMachCore::GetImageInfoAddress() {
+ // If we found both a user-process dyld and a kernel binary, we need to decide
+ // which to prefer.
+ if (GetCorefilePreference() == eKernelCorefile) {
+ if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
+ return m_mach_kernel_addr;
+ }
+ return m_dyld_addr;
+ } else {
+ if (m_dyld_addr != LLDB_INVALID_ADDRESS) {
+ return m_dyld_addr;
}
+ return m_mach_kernel_addr;
+ }
}
-
-lldb_private::ObjectFile *
-ProcessMachCore::GetCoreObjectFile ()
-{
- return m_core_module_sp->GetObjectFile();
+lldb_private::ObjectFile *ProcessMachCore::GetCoreObjectFile() {
+ return m_core_module_sp->GetObjectFile();
}
Modified: lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.h (original)
+++ lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.h Tue Sep 6 15:57:50 2016
@@ -23,147 +23,131 @@
class ThreadKDP;
-class ProcessMachCore : public lldb_private::Process
-{
+class ProcessMachCore : public lldb_private::Process {
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- ProcessMachCore(lldb::TargetSP target_sp,
- lldb::ListenerSP listener,
- const lldb_private::FileSpec &core_file);
-
- ~ProcessMachCore() override;
-
- static lldb::ProcessSP
- CreateInstance (lldb::TargetSP target_sp,
- lldb::ListenerSP listener,
- const lldb_private::FileSpec *crash_file_path);
-
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb_private::ConstString
- GetPluginNameStatic();
-
- static const char *
- GetPluginDescriptionStatic();
-
- //------------------------------------------------------------------
- // Check if a given Process
- //------------------------------------------------------------------
- bool
- CanDebug (lldb::TargetSP target_sp,
- bool plugin_specified_by_name) override;
-
- //------------------------------------------------------------------
- // Creating a new process, or attaching to an existing one
- //------------------------------------------------------------------
- lldb_private::Error
- DoLoadCore () override;
-
- lldb_private::DynamicLoader *
- GetDynamicLoader () override;
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString
- GetPluginName() override;
-
- uint32_t
- GetPluginVersion() override;
-
- //------------------------------------------------------------------
- // Process Control
- //------------------------------------------------------------------
- lldb_private::Error
- DoDestroy () override;
-
- void
- RefreshStateAfterStop() override;
-
- //------------------------------------------------------------------
- // Process Queries
- //------------------------------------------------------------------
- bool
- IsAlive () override;
-
- bool
- WarnBeforeDetach () const override;
-
- //------------------------------------------------------------------
- // Process Memory
- //------------------------------------------------------------------
- size_t
- ReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override;
-
- size_t
- DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override;
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ ProcessMachCore(lldb::TargetSP target_sp, lldb::ListenerSP listener,
+ const lldb_private::FileSpec &core_file);
- lldb_private::Error
- GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo ®ion_info) override;
+ ~ProcessMachCore() override;
- lldb::addr_t
- GetImageInfoAddress () override;
+ static lldb::ProcessSP
+ CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener,
+ const lldb_private::FileSpec *crash_file_path);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ //------------------------------------------------------------------
+ // Check if a given Process
+ //------------------------------------------------------------------
+ bool CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) override;
+
+ //------------------------------------------------------------------
+ // Creating a new process, or attaching to an existing one
+ //------------------------------------------------------------------
+ lldb_private::Error DoLoadCore() override;
+
+ lldb_private::DynamicLoader *GetDynamicLoader() override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ //------------------------------------------------------------------
+ // Process Control
+ //------------------------------------------------------------------
+ lldb_private::Error DoDestroy() override;
+
+ void RefreshStateAfterStop() override;
+
+ //------------------------------------------------------------------
+ // Process Queries
+ //------------------------------------------------------------------
+ bool IsAlive() override;
+
+ bool WarnBeforeDetach() const override;
+
+ //------------------------------------------------------------------
+ // Process Memory
+ //------------------------------------------------------------------
+ size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ lldb_private::Error &error) override;
+
+ size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ lldb_private::Error &error) override;
+
+ lldb_private::Error
+ GetMemoryRegionInfo(lldb::addr_t load_addr,
+ lldb_private::MemoryRegionInfo ®ion_info) override;
+
+ lldb::addr_t GetImageInfoAddress() override;
protected:
- friend class ThreadMachCore;
-
- void
- Clear ( );
-
- bool
- UpdateThreadList (lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &new_thread_list) override;
-
- lldb_private::ObjectFile *
- GetCoreObjectFile ();
-private:
- bool
- GetDynamicLoaderAddress (lldb::addr_t addr);
+ friend class ThreadMachCore;
+
+ void Clear();
+
+ bool UpdateThreadList(lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &new_thread_list) override;
- typedef enum CorefilePreference { eUserProcessCorefile, eKernelCorefile } CorefilePreferences;
+ lldb_private::ObjectFile *GetCoreObjectFile();
+
+private:
+ bool GetDynamicLoaderAddress(lldb::addr_t addr);
- //------------------------------------------------------------------
- /// If a core file can be interpreted multiple ways, this establishes
- /// which style wins.
- ///
- /// If a core file contains both a kernel binary and a user-process
- /// dynamic loader, lldb needs to pick one over the other. This could
- /// be a kernel corefile that happens to have a copy of dyld in its
- /// memory. Or it could be a user process coredump of lldb while doing
- /// kernel debugging - so a copy of the kernel is in its heap. This
- /// should become a setting so it can be over-ridden when necessary.
- //------------------------------------------------------------------
- CorefilePreference
- GetCorefilePreference ()
- {
- // For now, if both user process and kernel binaries a present,
- // assume this is a kernel coredump which has a copy of a user
- // process dyld in one of its pages.
- return eKernelCorefile;
- }
-
- //------------------------------------------------------------------
- // For ProcessMachCore only
- //------------------------------------------------------------------
- typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange;
- typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange> VMRangeToFileOffset;
- typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t> VMRangeToPermissions;
-
- VMRangeToFileOffset m_core_aranges;
- VMRangeToPermissions m_core_range_infos;
- lldb::ModuleSP m_core_module_sp;
- lldb_private::FileSpec m_core_file;
- lldb::addr_t m_dyld_addr;
- lldb::addr_t m_mach_kernel_addr;
- lldb_private::ConstString m_dyld_plugin_name;
+ typedef enum CorefilePreference {
+ eUserProcessCorefile,
+ eKernelCorefile
+ } CorefilePreferences;
+
+ //------------------------------------------------------------------
+ /// If a core file can be interpreted multiple ways, this establishes
+ /// which style wins.
+ ///
+ /// If a core file contains both a kernel binary and a user-process
+ /// dynamic loader, lldb needs to pick one over the other. This could
+ /// be a kernel corefile that happens to have a copy of dyld in its
+ /// memory. Or it could be a user process coredump of lldb while doing
+ /// kernel debugging - so a copy of the kernel is in its heap. This
+ /// should become a setting so it can be over-ridden when necessary.
+ //------------------------------------------------------------------
+ CorefilePreference GetCorefilePreference() {
+ // For now, if both user process and kernel binaries a present,
+ // assume this is a kernel coredump which has a copy of a user
+ // process dyld in one of its pages.
+ return eKernelCorefile;
+ }
+
+ //------------------------------------------------------------------
+ // For ProcessMachCore only
+ //------------------------------------------------------------------
+ typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange;
+ typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange>
+ VMRangeToFileOffset;
+ typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t>
+ VMRangeToPermissions;
+
+ VMRangeToFileOffset m_core_aranges;
+ VMRangeToPermissions m_core_range_infos;
+ lldb::ModuleSP m_core_module_sp;
+ lldb_private::FileSpec m_core_file;
+ lldb::addr_t m_dyld_addr;
+ lldb::addr_t m_mach_kernel_addr;
+ lldb_private::ConstString m_dyld_plugin_name;
- DISALLOW_COPY_AND_ASSIGN (ProcessMachCore);
+ DISALLOW_COPY_AND_ASSIGN(ProcessMachCore);
};
#endif // liblldb_ProcessMachCore_h_
Modified: lldb/trunk/source/Plugins/Process/mach-core/ThreadMachCore.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/mach-core/ThreadMachCore.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/mach-core/ThreadMachCore.cpp (original)
+++ lldb/trunk/source/Plugins/Process/mach-core/ThreadMachCore.cpp Tue Sep 6 15:57:50 2016
@@ -7,22 +7,21 @@
//
//===----------------------------------------------------------------------===//
-
#include "ThreadMachCore.h"
#include "lldb/Utility/SafeMachO.h"
+#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/StreamString.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Unwind.h"
-#include "lldb/Breakpoint/Watchpoint.h"
#include "ProcessMachCore.h"
//#include "RegisterContextKDP_arm.h"
@@ -36,97 +35,71 @@ using namespace lldb_private;
// Thread Registers
//----------------------------------------------------------------------
-ThreadMachCore::ThreadMachCore (Process &process, lldb::tid_t tid) :
- Thread(process, tid),
- m_thread_name (),
- m_dispatch_queue_name (),
- m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS),
- m_thread_reg_ctx_sp ()
-{
-}
-
-ThreadMachCore::~ThreadMachCore ()
-{
- DestroyThread();
-}
-
-const char *
-ThreadMachCore::GetName ()
-{
- if (m_thread_name.empty())
- return NULL;
- return m_thread_name.c_str();
-}
-
-void
-ThreadMachCore::RefreshStateAfterStop()
-{
- // Invalidate all registers in our register context. We don't set "force" to
- // true because the stop reply packet might have had some register values
- // that were expedited and these will already be copied into the register
- // context by the time this function gets called. The KDPRegisterContext
- // class has been made smart enough to detect when it needs to invalidate
- // which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
- const bool force = false;
- GetRegisterContext()->InvalidateIfNeeded (force);
-}
-
-bool
-ThreadMachCore::ThreadIDIsValid (lldb::tid_t thread)
-{
- return thread != 0;
-}
-
-lldb::RegisterContextSP
-ThreadMachCore::GetRegisterContext ()
-{
- if (m_reg_context_sp.get() == NULL)
- m_reg_context_sp = CreateRegisterContextForFrame (NULL);
- return m_reg_context_sp;
+ThreadMachCore::ThreadMachCore(Process &process, lldb::tid_t tid)
+ : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(),
+ m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS), m_thread_reg_ctx_sp() {}
+
+ThreadMachCore::~ThreadMachCore() { DestroyThread(); }
+
+const char *ThreadMachCore::GetName() {
+ if (m_thread_name.empty())
+ return NULL;
+ return m_thread_name.c_str();
+}
+
+void ThreadMachCore::RefreshStateAfterStop() {
+ // Invalidate all registers in our register context. We don't set "force" to
+ // true because the stop reply packet might have had some register values
+ // that were expedited and these will already be copied into the register
+ // context by the time this function gets called. The KDPRegisterContext
+ // class has been made smart enough to detect when it needs to invalidate
+ // which registers are valid by putting hooks in the register read and
+ // register supply functions where they check the process stop ID and do
+ // the right thing.
+ const bool force = false;
+ GetRegisterContext()->InvalidateIfNeeded(force);
+}
+
+bool ThreadMachCore::ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; }
+
+lldb::RegisterContextSP ThreadMachCore::GetRegisterContext() {
+ if (m_reg_context_sp.get() == NULL)
+ m_reg_context_sp = CreateRegisterContextForFrame(NULL);
+ return m_reg_context_sp;
}
lldb::RegisterContextSP
-ThreadMachCore::CreateRegisterContextForFrame (StackFrame *frame)
-{
- lldb::RegisterContextSP reg_ctx_sp;
- uint32_t concrete_frame_idx = 0;
-
- if (frame)
- concrete_frame_idx = frame->GetConcreteFrameIndex ();
-
- if (concrete_frame_idx == 0)
- {
- if (!m_thread_reg_ctx_sp)
- {
- ProcessSP process_sp (GetProcess());
-
- ObjectFile *core_objfile = static_cast<ProcessMachCore *>(process_sp.get())->GetCoreObjectFile ();
- if (core_objfile)
- m_thread_reg_ctx_sp = core_objfile->GetThreadContextAtIndex (GetID(), *this);
- }
- reg_ctx_sp = m_thread_reg_ctx_sp;
- }
- else
- {
- Unwind *unwinder = GetUnwinder ();
- if (unwinder)
- reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
+ThreadMachCore::CreateRegisterContextForFrame(StackFrame *frame) {
+ lldb::RegisterContextSP reg_ctx_sp;
+ uint32_t concrete_frame_idx = 0;
+
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex();
+
+ if (concrete_frame_idx == 0) {
+ if (!m_thread_reg_ctx_sp) {
+ ProcessSP process_sp(GetProcess());
+
+ ObjectFile *core_objfile =
+ static_cast<ProcessMachCore *>(process_sp.get())->GetCoreObjectFile();
+ if (core_objfile)
+ m_thread_reg_ctx_sp =
+ core_objfile->GetThreadContextAtIndex(GetID(), *this);
}
- return reg_ctx_sp;
+ reg_ctx_sp = m_thread_reg_ctx_sp;
+ } else {
+ Unwind *unwinder = GetUnwinder();
+ if (unwinder)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
+ }
+ return reg_ctx_sp;
+}
+
+bool ThreadMachCore::CalculateStopInfo() {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, SIGSTOP));
+ return true;
+ }
+ return false;
}
-
-bool
-ThreadMachCore::CalculateStopInfo ()
-{
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
- return true;
- }
- return false;
-}
-
-
Modified: lldb/trunk/source/Plugins/Process/mach-core/ThreadMachCore.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/mach-core/ThreadMachCore.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/mach-core/ThreadMachCore.h (original)
+++ lldb/trunk/source/Plugins/Process/mach-core/ThreadMachCore.h Tue Sep 6 15:57:50 2016
@@ -20,72 +20,55 @@
class ProcessMachCore;
-class ThreadMachCore : public lldb_private::Thread
-{
+class ThreadMachCore : public lldb_private::Thread {
public:
- ThreadMachCore (lldb_private::Process &process,
- lldb::tid_t tid);
+ ThreadMachCore(lldb_private::Process &process, lldb::tid_t tid);
- ~ThreadMachCore() override;
+ ~ThreadMachCore() override;
- void
- RefreshStateAfterStop() override;
+ void RefreshStateAfterStop() override;
- const char *
- GetName() override;
-
- lldb::RegisterContextSP
- GetRegisterContext() override;
-
- lldb::RegisterContextSP
- CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
-
- static bool
- ThreadIDIsValid (lldb::tid_t thread);
-
- bool
- ShouldStop (bool &step_more);
-
- const char *
- GetBasicInfoAsString ();
-
- void
- SetName(const char *name) override
- {
- if (name && name[0])
- m_thread_name.assign (name);
- else
- m_thread_name.clear();
- }
-
- lldb::addr_t
- GetThreadDispatchQAddr ()
- {
- return m_thread_dispatch_qaddr;
- }
-
- void
- SetThreadDispatchQAddr (lldb::addr_t thread_dispatch_qaddr)
- {
- m_thread_dispatch_qaddr = thread_dispatch_qaddr;
- }
+ const char *GetName() override;
+
+ lldb::RegisterContextSP GetRegisterContext() override;
+
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
+
+ static bool ThreadIDIsValid(lldb::tid_t thread);
+
+ bool ShouldStop(bool &step_more);
+
+ const char *GetBasicInfoAsString();
+
+ void SetName(const char *name) override {
+ if (name && name[0])
+ m_thread_name.assign(name);
+ else
+ m_thread_name.clear();
+ }
+
+ lldb::addr_t GetThreadDispatchQAddr() { return m_thread_dispatch_qaddr; }
+
+ void SetThreadDispatchQAddr(lldb::addr_t thread_dispatch_qaddr) {
+ m_thread_dispatch_qaddr = thread_dispatch_qaddr;
+ }
protected:
- friend class ProcessMachCore;
+ friend class ProcessMachCore;
- //------------------------------------------------------------------
- // Member variables.
- //------------------------------------------------------------------
- std::string m_thread_name;
- std::string m_dispatch_queue_name;
- lldb::addr_t m_thread_dispatch_qaddr;
- lldb::RegisterContextSP m_thread_reg_ctx_sp;
-
- //------------------------------------------------------------------
- // Protected member functions.
- //------------------------------------------------------------------
- bool
- CalculateStopInfo() override;
+ //------------------------------------------------------------------
+ // Member variables.
+ //------------------------------------------------------------------
+ std::string m_thread_name;
+ std::string m_dispatch_queue_name;
+ lldb::addr_t m_thread_dispatch_qaddr;
+ lldb::RegisterContextSP m_thread_reg_ctx_sp;
+
+ //------------------------------------------------------------------
+ // Protected member functions.
+ //------------------------------------------------------------------
+ bool CalculateStopInfo() override;
};
#endif // liblldb_ThreadMachCore_h_
Modified: lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp (original)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp Tue Sep 6 15:57:50 2016
@@ -1,4 +1,5 @@
-//===-- MinidumpParser.cpp ---------------------------------------*- C++ -*-===//
+//===-- MinidumpParser.cpp ---------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,143 +19,136 @@ using namespace lldb_private;
using namespace minidump;
llvm::Optional<MinidumpParser>
-MinidumpParser::Create(const lldb::DataBufferSP &data_buf_sp)
-{
- if (data_buf_sp->GetByteSize() < sizeof(MinidumpHeader))
- {
- return llvm::None;
+MinidumpParser::Create(const lldb::DataBufferSP &data_buf_sp) {
+ if (data_buf_sp->GetByteSize() < sizeof(MinidumpHeader)) {
+ return llvm::None;
+ }
+
+ llvm::ArrayRef<uint8_t> header_data(data_buf_sp->GetBytes(),
+ sizeof(MinidumpHeader));
+ const MinidumpHeader *header = MinidumpHeader::Parse(header_data);
+
+ if (header == nullptr) {
+ return llvm::None;
+ }
+
+ lldb::offset_t directory_list_offset = header->stream_directory_rva;
+ // check if there is enough data for the parsing of the directory list
+ if ((directory_list_offset +
+ sizeof(MinidumpDirectory) * header->streams_count) >
+ data_buf_sp->GetByteSize()) {
+ return llvm::None;
+ }
+
+ const MinidumpDirectory *directory = nullptr;
+ Error error;
+ llvm::ArrayRef<uint8_t> directory_data(
+ data_buf_sp->GetBytes() + directory_list_offset,
+ sizeof(MinidumpDirectory) * header->streams_count);
+ llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> directory_map;
+
+ for (uint32_t i = 0; i < header->streams_count; ++i) {
+ error = consumeObject(directory_data, directory);
+ if (error.Fail()) {
+ return llvm::None;
}
+ directory_map[static_cast<const uint32_t>(directory->stream_type)] =
+ directory->location;
+ }
- llvm::ArrayRef<uint8_t> header_data(data_buf_sp->GetBytes(), sizeof(MinidumpHeader));
- const MinidumpHeader *header = MinidumpHeader::Parse(header_data);
-
- if (header == nullptr)
- {
- return llvm::None;
- }
-
- lldb::offset_t directory_list_offset = header->stream_directory_rva;
- // check if there is enough data for the parsing of the directory list
- if ((directory_list_offset + sizeof(MinidumpDirectory) * header->streams_count) > data_buf_sp->GetByteSize())
- {
- return llvm::None;
- }
+ MinidumpParser parser(data_buf_sp, header, directory_map);
+ return llvm::Optional<MinidumpParser>(parser);
+}
- const MinidumpDirectory *directory = nullptr;
- Error error;
- llvm::ArrayRef<uint8_t> directory_data(data_buf_sp->GetBytes() + directory_list_offset,
- sizeof(MinidumpDirectory) * header->streams_count);
- llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> directory_map;
-
- for (uint32_t i = 0; i < header->streams_count; ++i)
- {
- error = consumeObject(directory_data, directory);
- if (error.Fail())
- {
- return llvm::None;
- }
- directory_map[static_cast<const uint32_t>(directory->stream_type)] = directory->location;
- }
+MinidumpParser::MinidumpParser(
+ const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
+ const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &directory_map)
+ : m_data_sp(data_buf_sp), m_header(header), m_directory_map(directory_map) {
+}
- MinidumpParser parser(data_buf_sp, header, directory_map);
- return llvm::Optional<MinidumpParser>(parser);
+lldb::offset_t MinidumpParser::GetByteSize() {
+ return m_data_sp->GetByteSize();
}
-MinidumpParser::MinidumpParser(const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
- const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &directory_map)
- : m_data_sp(data_buf_sp), m_header(header), m_directory_map(directory_map)
-{
+llvm::Optional<llvm::ArrayRef<uint8_t>>
+MinidumpParser::GetStream(MinidumpStreamType stream_type) {
+ auto iter = m_directory_map.find(static_cast<uint32_t>(stream_type));
+ if (iter == m_directory_map.end())
+ return llvm::None;
+
+ // check if there is enough data
+ if (iter->second.rva + iter->second.data_size > m_data_sp->GetByteSize())
+ return llvm::None;
+
+ llvm::ArrayRef<uint8_t> arr_ref(m_data_sp->GetBytes() + iter->second.rva,
+ iter->second.data_size);
+ return llvm::Optional<llvm::ArrayRef<uint8_t>>(arr_ref);
}
-lldb::offset_t
-MinidumpParser::GetByteSize()
-{
- return m_data_sp->GetByteSize();
+llvm::Optional<std::vector<const MinidumpThread *>>
+MinidumpParser::GetThreads() {
+ llvm::Optional<llvm::ArrayRef<uint8_t>> data =
+ GetStream(MinidumpStreamType::ThreadList);
+
+ if (!data)
+ return llvm::None;
+
+ return MinidumpThread::ParseThreadList(data.getValue());
}
-llvm::Optional<llvm::ArrayRef<uint8_t>>
-MinidumpParser::GetStream(MinidumpStreamType stream_type)
-{
- auto iter = m_directory_map.find(static_cast<uint32_t>(stream_type));
- if (iter == m_directory_map.end())
- return llvm::None;
-
- // check if there is enough data
- if (iter->second.rva + iter->second.data_size > m_data_sp->GetByteSize())
- return llvm::None;
+const MinidumpSystemInfo *MinidumpParser::GetSystemInfo() {
+ llvm::Optional<llvm::ArrayRef<uint8_t>> data =
+ GetStream(MinidumpStreamType::SystemInfo);
+
+ if (!data)
+ return nullptr;
- llvm::ArrayRef<uint8_t> arr_ref(m_data_sp->GetBytes() + iter->second.rva, iter->second.data_size);
- return llvm::Optional<llvm::ArrayRef<uint8_t>>(arr_ref);
+ return MinidumpSystemInfo::Parse(data.getValue());
}
-llvm::Optional<std::vector<const MinidumpThread *>>
-MinidumpParser::GetThreads()
-{
- llvm::Optional<llvm::ArrayRef<uint8_t>> data = GetStream(MinidumpStreamType::ThreadList);
-
- if (!data)
- return llvm::None;
-
- return MinidumpThread::ParseThreadList(data.getValue());
-}
-
-const MinidumpSystemInfo *
-MinidumpParser::GetSystemInfo()
-{
- llvm::Optional<llvm::ArrayRef<uint8_t>> data = GetStream(MinidumpStreamType::SystemInfo);
-
- if (!data)
- return nullptr;
-
- return MinidumpSystemInfo::Parse(data.getValue());
-}
-
-ArchSpec
-MinidumpParser::GetArchitecture()
-{
- ArchSpec arch_spec;
- arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);
- arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
- arch_spec.GetTriple().setArch(llvm::Triple::ArchType::UnknownArch);
-
- // TODO should we add the OS type here, or somewhere else ?
-
- const MinidumpSystemInfo *system_info = GetSystemInfo();
-
- if (!system_info)
- return arch_spec;
-
- // TODO what to do about big endiand flavors of arm ?
- // TODO set the arm subarch stuff if the minidump has info about it
-
- const MinidumpCPUArchitecture arch =
- static_cast<const MinidumpCPUArchitecture>(static_cast<const uint32_t>(system_info->processor_arch));
- switch (arch)
- {
- case MinidumpCPUArchitecture::X86:
- arch_spec.GetTriple().setArch(llvm::Triple::ArchType::x86);
- break;
- case MinidumpCPUArchitecture::AMD64:
- arch_spec.GetTriple().setArch(llvm::Triple::ArchType::x86_64);
- break;
- case MinidumpCPUArchitecture::ARM:
- arch_spec.GetTriple().setArch(llvm::Triple::ArchType::arm);
- break;
- case MinidumpCPUArchitecture::ARM64:
- arch_spec.GetTriple().setArch(llvm::Triple::ArchType::aarch64);
- break;
- }
+ArchSpec MinidumpParser::GetArchitecture() {
+ ArchSpec arch_spec;
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);
+ arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
+ arch_spec.GetTriple().setArch(llvm::Triple::ArchType::UnknownArch);
+ // TODO should we add the OS type here, or somewhere else ?
+
+ const MinidumpSystemInfo *system_info = GetSystemInfo();
+
+ if (!system_info)
return arch_spec;
-}
-const MinidumpMiscInfo *
-MinidumpParser::GetMiscInfo()
-{
- llvm::Optional<llvm::ArrayRef<uint8_t>> data = GetStream(MinidumpStreamType::MiscInfo);
+ // TODO what to do about big endiand flavors of arm ?
+ // TODO set the arm subarch stuff if the minidump has info about it
+
+ const MinidumpCPUArchitecture arch =
+ static_cast<const MinidumpCPUArchitecture>(
+ static_cast<const uint32_t>(system_info->processor_arch));
+ switch (arch) {
+ case MinidumpCPUArchitecture::X86:
+ arch_spec.GetTriple().setArch(llvm::Triple::ArchType::x86);
+ break;
+ case MinidumpCPUArchitecture::AMD64:
+ arch_spec.GetTriple().setArch(llvm::Triple::ArchType::x86_64);
+ break;
+ case MinidumpCPUArchitecture::ARM:
+ arch_spec.GetTriple().setArch(llvm::Triple::ArchType::arm);
+ break;
+ case MinidumpCPUArchitecture::ARM64:
+ arch_spec.GetTriple().setArch(llvm::Triple::ArchType::aarch64);
+ break;
+ }
+
+ return arch_spec;
+}
+
+const MinidumpMiscInfo *MinidumpParser::GetMiscInfo() {
+ llvm::Optional<llvm::ArrayRef<uint8_t>> data =
+ GetStream(MinidumpStreamType::MiscInfo);
- if (!data)
- return nullptr;
+ if (!data)
+ return nullptr;
- return MinidumpMiscInfo::Parse(data.getValue());
+ return MinidumpMiscInfo::Parse(data.getValue());
}
Modified: lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h (original)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.h Tue Sep 6 15:57:50 2016
@@ -1,4 +1,5 @@
-//===-- MinidumpParser.h -----------------------------------------*- C++ -*-===//
+//===-- MinidumpParser.h -----------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -28,44 +29,37 @@
#include <cstring>
#include <unordered_map>
+namespace lldb_private {
-namespace lldb_private
-{
+namespace minidump {
-namespace minidump
-{
-
-class MinidumpParser
-{
+class MinidumpParser {
public:
- static llvm::Optional<MinidumpParser>
- Create(const lldb::DataBufferSP &data_buf_sp);
+ static llvm::Optional<MinidumpParser>
+ Create(const lldb::DataBufferSP &data_buf_sp);
- lldb::offset_t
- GetByteSize();
+ lldb::offset_t GetByteSize();
- llvm::Optional<llvm::ArrayRef<uint8_t>>
- GetStream(MinidumpStreamType stream_type);
+ llvm::Optional<llvm::ArrayRef<uint8_t>>
+ GetStream(MinidumpStreamType stream_type);
- llvm::Optional<std::vector<const MinidumpThread *>>
- GetThreads();
+ llvm::Optional<std::vector<const MinidumpThread *>> GetThreads();
- const MinidumpSystemInfo *
- GetSystemInfo();
+ const MinidumpSystemInfo *GetSystemInfo();
- ArchSpec
- GetArchitecture();
+ ArchSpec GetArchitecture();
- const MinidumpMiscInfo *
- GetMiscInfo();
+ const MinidumpMiscInfo *GetMiscInfo();
private:
- lldb::DataBufferSP m_data_sp;
- const MinidumpHeader *m_header;
- llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> m_directory_map;
-
- MinidumpParser(const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
- const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &directory_map);
+ lldb::DataBufferSP m_data_sp;
+ const MinidumpHeader *m_header;
+ llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> m_directory_map;
+
+ MinidumpParser(const lldb::DataBufferSP &data_buf_sp,
+ const MinidumpHeader *header,
+ const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor>
+ &directory_map);
};
} // namespace minidump
Modified: lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp (original)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.cpp Tue Sep 6 15:57:50 2016
@@ -18,81 +18,75 @@
using namespace lldb_private;
using namespace minidump;
-const MinidumpHeader *
-MinidumpHeader::Parse(llvm::ArrayRef<uint8_t> &data)
-{
- const MinidumpHeader *header = nullptr;
- Error error = consumeObject(data, header);
-
- const MinidumpHeaderConstants signature =
- static_cast<const MinidumpHeaderConstants>(static_cast<const uint32_t>(header->signature));
- const MinidumpHeaderConstants version =
- static_cast<const MinidumpHeaderConstants>(static_cast<const uint32_t>(header->version) & 0x0000ffff);
- // the high 16 bits of the version field are implementation specific
+const MinidumpHeader *MinidumpHeader::Parse(llvm::ArrayRef<uint8_t> &data) {
+ const MinidumpHeader *header = nullptr;
+ Error error = consumeObject(data, header);
+
+ const MinidumpHeaderConstants signature =
+ static_cast<const MinidumpHeaderConstants>(
+ static_cast<const uint32_t>(header->signature));
+ const MinidumpHeaderConstants version =
+ static_cast<const MinidumpHeaderConstants>(
+ static_cast<const uint32_t>(header->version) & 0x0000ffff);
+ // the high 16 bits of the version field are implementation specific
+
+ if (error.Fail() || signature != MinidumpHeaderConstants::Signature ||
+ version != MinidumpHeaderConstants::Version)
+ return nullptr;
- if (error.Fail() || signature != MinidumpHeaderConstants::Signature || version != MinidumpHeaderConstants::Version)
- return nullptr;
+ // TODO check for max number of streams ?
+ // TODO more sanity checks ?
- // TODO check for max number of streams ?
- // TODO more sanity checks ?
-
- return header;
+ return header;
}
// MinidumpThread
-const MinidumpThread *
-MinidumpThread::Parse(llvm::ArrayRef<uint8_t> &data)
-{
- const MinidumpThread *thread = nullptr;
- Error error = consumeObject(data, thread);
- if (error.Fail())
- return nullptr;
+const MinidumpThread *MinidumpThread::Parse(llvm::ArrayRef<uint8_t> &data) {
+ const MinidumpThread *thread = nullptr;
+ Error error = consumeObject(data, thread);
+ if (error.Fail())
+ return nullptr;
- return thread;
+ return thread;
}
llvm::Optional<std::vector<const MinidumpThread *>>
-MinidumpThread::ParseThreadList(llvm::ArrayRef<uint8_t> &data)
-{
- std::vector<const MinidumpThread *> thread_list;
-
- const llvm::support::ulittle32_t *thread_count;
- Error error = consumeObject(data, thread_count);
- if (error.Fail())
- return llvm::None;
-
- const MinidumpThread *thread;
- for (uint32_t i = 0; i < *thread_count; ++i)
- {
- thread = MinidumpThread::Parse(data);
- if (thread == nullptr)
- return llvm::None;
- thread_list.push_back(thread);
- }
+MinidumpThread::ParseThreadList(llvm::ArrayRef<uint8_t> &data) {
+ std::vector<const MinidumpThread *> thread_list;
+
+ const llvm::support::ulittle32_t *thread_count;
+ Error error = consumeObject(data, thread_count);
+ if (error.Fail())
+ return llvm::None;
+
+ const MinidumpThread *thread;
+ for (uint32_t i = 0; i < *thread_count; ++i) {
+ thread = MinidumpThread::Parse(data);
+ if (thread == nullptr)
+ return llvm::None;
+ thread_list.push_back(thread);
+ }
- return llvm::Optional<std::vector<const MinidumpThread *>>(thread_list);
+ return llvm::Optional<std::vector<const MinidumpThread *>>(thread_list);
}
// MinidumpSystemInfo
const MinidumpSystemInfo *
-MinidumpSystemInfo::Parse(llvm::ArrayRef<uint8_t> &data)
-{
- const MinidumpSystemInfo *system_info;
- Error error = consumeObject(data, system_info);
- if (error.Fail())
- return nullptr;
+MinidumpSystemInfo::Parse(llvm::ArrayRef<uint8_t> &data) {
+ const MinidumpSystemInfo *system_info;
+ Error error = consumeObject(data, system_info);
+ if (error.Fail())
+ return nullptr;
- return system_info;
+ return system_info;
}
// MinidumpMiscInfo
-const MinidumpMiscInfo *
-MinidumpMiscInfo::Parse(llvm::ArrayRef<uint8_t> &data)
-{
- const MinidumpMiscInfo *misc_info;
- Error error = consumeObject(data, misc_info);
- if (error.Fail())
- return nullptr;
+const MinidumpMiscInfo *MinidumpMiscInfo::Parse(llvm::ArrayRef<uint8_t> &data) {
+ const MinidumpMiscInfo *misc_info;
+ Error error = consumeObject(data, misc_info);
+ if (error.Fail())
+ return nullptr;
- return misc_info;
+ return misc_info;
}
Modified: lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h (original)
+++ lldb/trunk/source/Plugins/Process/minidump/MinidumpTypes.h Tue Sep 6 15:57:50 2016
@@ -27,271 +27,267 @@
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms679293(v=vs.85).aspx
// https://chromium.googlesource.com/breakpad/breakpad/
-namespace lldb_private
-{
+namespace lldb_private {
-namespace minidump
-{
+namespace minidump {
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
-enum class MinidumpHeaderConstants : uint32_t
-{
- Signature = 0x504d444d, // 'PMDM'
- Version = 0x0000a793, // 42899
- LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Signature)
+enum class MinidumpHeaderConstants : uint32_t {
+ Signature = 0x504d444d, // 'PMDM'
+ Version = 0x0000a793, // 42899
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Signature)
};
-// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680394.aspx
-enum class MinidumpStreamType : uint32_t
-{
- Unused = 0,
- Reserved0 = 1,
- Reserved1 = 2,
- ThreadList = 3,
- ModuleList = 4,
- MemoryList = 5,
- Exception = 6,
- SystemInfo = 7,
- ThreadExList = 8,
- Memory64List = 9,
- CommentA = 10,
- CommentW = 11,
- HandleData = 12,
- FunctionTable = 13,
- UnloadedModuleList = 14,
- MiscInfo = 15,
- MemoryInfoList = 16,
- ThreadInfoList = 17,
- HandleOperationList = 18,
- Token = 19,
- JavascriptData = 20,
- SystemMemoryInfo = 21,
- ProcessVMCounters = 22,
- LastReserved = 0x0000ffff,
-
- /* Breakpad extension types. 0x4767 = "Gg" */
- BreakpadInfo = 0x47670001,
- AssertionInfo = 0x47670002,
- /* These are additional minidump stream values which are specific to
- * the linux breakpad implementation. */
- LinuxCPUInfo = 0x47670003, /* /proc/cpuinfo */
- LinuxProcStatus = 0x47670004, /* /proc/$x/status */
- LinuxLSBRelease = 0x47670005, /* /etc/lsb-release */
- LinuxCMDLine = 0x47670006, /* /proc/$x/cmdline */
- LinuxEnviron = 0x47670007, /* /proc/$x/environ */
- LinuxAuxv = 0x47670008, /* /proc/$x/auxv */
- LinuxMaps = 0x47670009, /* /proc/$x/maps */
- LinuxDSODebug = 0x4767000A
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680394.aspx
+enum class MinidumpStreamType : uint32_t {
+ Unused = 0,
+ Reserved0 = 1,
+ Reserved1 = 2,
+ ThreadList = 3,
+ ModuleList = 4,
+ MemoryList = 5,
+ Exception = 6,
+ SystemInfo = 7,
+ ThreadExList = 8,
+ Memory64List = 9,
+ CommentA = 10,
+ CommentW = 11,
+ HandleData = 12,
+ FunctionTable = 13,
+ UnloadedModuleList = 14,
+ MiscInfo = 15,
+ MemoryInfoList = 16,
+ ThreadInfoList = 17,
+ HandleOperationList = 18,
+ Token = 19,
+ JavascriptData = 20,
+ SystemMemoryInfo = 21,
+ ProcessVMCounters = 22,
+ LastReserved = 0x0000ffff,
+
+ /* Breakpad extension types. 0x4767 = "Gg" */
+ BreakpadInfo = 0x47670001,
+ AssertionInfo = 0x47670002,
+ /* These are additional minidump stream values which are specific to
+ * the linux breakpad implementation. */
+ LinuxCPUInfo = 0x47670003, /* /proc/cpuinfo */
+ LinuxProcStatus = 0x47670004, /* /proc/$x/status */
+ LinuxLSBRelease = 0x47670005, /* /etc/lsb-release */
+ LinuxCMDLine = 0x47670006, /* /proc/$x/cmdline */
+ LinuxEnviron = 0x47670007, /* /proc/$x/environ */
+ LinuxAuxv = 0x47670008, /* /proc/$x/auxv */
+ LinuxMaps = 0x47670009, /* /proc/$x/maps */
+ LinuxDSODebug = 0x4767000A
};
// for MinidumpSystemInfo.processor_arch
-enum class MinidumpCPUArchitecture : uint16_t
-{
- X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */
- MIPS = 1, /* PROCESSOR_ARCHITECTURE_MIPS */
- Alpha = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */
- PPC = 3, /* PROCESSOR_ARCHITECTURE_PPC */
- SHX = 4, /* PROCESSOR_ARCHITECTURE_SHX (Super-H) */
- ARM = 5, /* PROCESSOR_ARCHITECTURE_ARM */
- IA64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */
- Alpha64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */
- MSIL = 8, /* PROCESSOR_ARCHITECTURE_MSIL
- * (Microsoft Intermediate Language) */
- AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */
- X86Win64 = 10, /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */
- SPARC = 0x8001, /* Breakpad-defined value for SPARC */
- PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */
- ARM64 = 0x8003, /* Breakpad-defined value for ARM64 */
- MIPS64 = 0x8004, /* Breakpad-defined value for MIPS64 */
- Unknown = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */
+enum class MinidumpCPUArchitecture : uint16_t {
+ X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */
+ MIPS = 1, /* PROCESSOR_ARCHITECTURE_MIPS */
+ Alpha = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */
+ PPC = 3, /* PROCESSOR_ARCHITECTURE_PPC */
+ SHX = 4, /* PROCESSOR_ARCHITECTURE_SHX (Super-H) */
+ ARM = 5, /* PROCESSOR_ARCHITECTURE_ARM */
+ IA64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */
+ Alpha64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */
+ MSIL = 8, /* PROCESSOR_ARCHITECTURE_MSIL
+ * (Microsoft Intermediate Language) */
+ AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */
+ X86Win64 = 10, /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */
+ SPARC = 0x8001, /* Breakpad-defined value for SPARC */
+ PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */
+ ARM64 = 0x8003, /* Breakpad-defined value for ARM64 */
+ MIPS64 = 0x8004, /* Breakpad-defined value for MIPS64 */
+ Unknown = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */
};
// for MinidumpSystemInfo.platform_id
-enum class MinidumpOSPlatform : uint32_t
-{
- Win32S = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */
- Win32Windows = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */
- Win32NT = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */
- Win32CE = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH
- * (Windows CE, Windows Mobile, "Handheld") */
-
- /* The following values are Breakpad-defined. */
- Unix = 0x8000, /* Generic Unix-ish */
- MacOSX = 0x8101, /* Mac OS X/Darwin */
- IOS = 0x8102, /* iOS */
- Linux = 0x8201, /* Linux */
- Solaris = 0x8202, /* Solaris */
- Android = 0x8203, /* Android */
- PS3 = 0x8204, /* PS3 */
- NaCl = 0x8205 /* Native Client (NaCl) */
+enum class MinidumpOSPlatform : uint32_t {
+ Win32S = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */
+ Win32Windows = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */
+ Win32NT = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */
+ Win32CE = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH
+ * (Windows CE, Windows Mobile, "Handheld") */
+
+ /* The following values are Breakpad-defined. */
+ Unix = 0x8000, /* Generic Unix-ish */
+ MacOSX = 0x8101, /* Mac OS X/Darwin */
+ IOS = 0x8102, /* iOS */
+ Linux = 0x8201, /* Linux */
+ Solaris = 0x8202, /* Solaris */
+ Android = 0x8203, /* Android */
+ PS3 = 0x8204, /* PS3 */
+ NaCl = 0x8205 /* Native Client (NaCl) */
};
// For MinidumpCPUInfo.arm_cpu_info.elf_hwcaps.
// This matches the Linux kernel definitions from <asm/hwcaps.h>
-enum class MinidumpPCPUInformationARMElfHwCaps : uint32_t
-{
- SWP = (1 << 0),
- Half = (1 << 1),
- Thumb = (1 << 2),
- _26BIT = (1 << 3),
- FastMult = (1 << 4),
- FPA = (1 << 5),
- VFP = (1 << 6),
- EDSP = (1 << 7),
- Java = (1 << 8),
- IWMMXT = (1 << 9),
- Crunch = (1 << 10),
- ThumbEE = (1 << 11),
- Neon = (1 << 12),
- VFPv3 = (1 << 13),
- VFPv3D16 = (1 << 14),
- TLS = (1 << 15),
- VFPv4 = (1 << 16),
- IDIVA = (1 << 17),
- IDIVT = (1 << 18),
- LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IDIVT)
+enum class MinidumpPCPUInformationARMElfHwCaps : uint32_t {
+ SWP = (1 << 0),
+ Half = (1 << 1),
+ Thumb = (1 << 2),
+ _26BIT = (1 << 3),
+ FastMult = (1 << 4),
+ FPA = (1 << 5),
+ VFP = (1 << 6),
+ EDSP = (1 << 7),
+ Java = (1 << 8),
+ IWMMXT = (1 << 9),
+ Crunch = (1 << 10),
+ ThumbEE = (1 << 11),
+ Neon = (1 << 12),
+ VFPv3 = (1 << 13),
+ VFPv3D16 = (1 << 14),
+ TLS = (1 << 15),
+ VFPv4 = (1 << 16),
+ IDIVA = (1 << 17),
+ IDIVT = (1 << 18),
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IDIVT)
};
template <typename T>
-Error
-consumeObject(llvm::ArrayRef<uint8_t> &Buffer, const T *&Object)
-{
- Error error;
- if (Buffer.size() < sizeof(T))
- {
- error.SetErrorString("Insufficient buffer!");
- return error;
- }
-
- Object = reinterpret_cast<const T *>(Buffer.data());
- Buffer = Buffer.drop_front(sizeof(T));
+Error consumeObject(llvm::ArrayRef<uint8_t> &Buffer, const T *&Object) {
+ Error error;
+ if (Buffer.size() < sizeof(T)) {
+ error.SetErrorString("Insufficient buffer!");
return error;
+ }
+
+ Object = reinterpret_cast<const T *>(Buffer.data());
+ Buffer = Buffer.drop_front(sizeof(T));
+ return error;
}
-// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680378(v=vs.85).aspx
-struct MinidumpHeader
-{
- llvm::support::ulittle32_t signature;
- llvm::support::ulittle32_t version; // The high 16 bits of version field are implementation specific
- llvm::support::ulittle32_t streams_count;
- llvm::support::ulittle32_t stream_directory_rva; // offset of the stream directory
- llvm::support::ulittle32_t checksum;
- llvm::support::ulittle32_t time_date_stamp; // time_t format
- llvm::support::ulittle64_t flags;
-
- static const MinidumpHeader *
- Parse(llvm::ArrayRef<uint8_t> &data);
-};
-static_assert(sizeof(MinidumpHeader) == 32, "sizeof MinidumpHeader is not correct!");
-
-// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680383.aspx
-struct MinidumpLocationDescriptor
-{
- llvm::support::ulittle32_t data_size;
- llvm::support::ulittle32_t rva;
-};
-static_assert(sizeof(MinidumpLocationDescriptor) == 8, "sizeof MinidumpLocationDescriptor is not correct!");
-
-// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680384(v=vs.85).aspx
-struct MinidumpMemoryDescriptor
-{
- llvm::support::ulittle64_t start_of_memory_range;
- MinidumpLocationDescriptor memory;
-};
-static_assert(sizeof(MinidumpMemoryDescriptor) == 16, "sizeof MinidumpMemoryDescriptor is not correct!");
-
-// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680365.aspx
-struct MinidumpDirectory
-{
- llvm::support::ulittle32_t stream_type;
- MinidumpLocationDescriptor location;
-};
-static_assert(sizeof(MinidumpDirectory) == 12, "sizeof MinidumpDirectory is not correct!");
-
-// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680517(v=vs.85).aspx
-struct MinidumpThread
-{
- llvm::support::ulittle32_t thread_id;
- llvm::support::ulittle32_t suspend_count;
- llvm::support::ulittle32_t priority_class;
- llvm::support::ulittle32_t priority;
- llvm::support::ulittle64_t teb;
- MinidumpMemoryDescriptor stack;
- MinidumpLocationDescriptor thread_context;
-
- static const MinidumpThread *
- Parse(llvm::ArrayRef<uint8_t> &data);
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680378(v=vs.85).aspx
+struct MinidumpHeader {
+ llvm::support::ulittle32_t signature;
+ llvm::support::ulittle32_t
+ version; // The high 16 bits of version field are implementation specific
+ llvm::support::ulittle32_t streams_count;
+ llvm::support::ulittle32_t
+ stream_directory_rva; // offset of the stream directory
+ llvm::support::ulittle32_t checksum;
+ llvm::support::ulittle32_t time_date_stamp; // time_t format
+ llvm::support::ulittle64_t flags;
+
+ static const MinidumpHeader *Parse(llvm::ArrayRef<uint8_t> &data);
+};
+static_assert(sizeof(MinidumpHeader) == 32,
+ "sizeof MinidumpHeader is not correct!");
+
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680383.aspx
+struct MinidumpLocationDescriptor {
+ llvm::support::ulittle32_t data_size;
+ llvm::support::ulittle32_t rva;
+};
+static_assert(sizeof(MinidumpLocationDescriptor) == 8,
+ "sizeof MinidumpLocationDescriptor is not correct!");
+
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680384(v=vs.85).aspx
+struct MinidumpMemoryDescriptor {
+ llvm::support::ulittle64_t start_of_memory_range;
+ MinidumpLocationDescriptor memory;
+};
+static_assert(sizeof(MinidumpMemoryDescriptor) == 16,
+ "sizeof MinidumpMemoryDescriptor is not correct!");
+
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680365.aspx
+struct MinidumpDirectory {
+ llvm::support::ulittle32_t stream_type;
+ MinidumpLocationDescriptor location;
+};
+static_assert(sizeof(MinidumpDirectory) == 12,
+ "sizeof MinidumpDirectory is not correct!");
+
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680517(v=vs.85).aspx
+struct MinidumpThread {
+ llvm::support::ulittle32_t thread_id;
+ llvm::support::ulittle32_t suspend_count;
+ llvm::support::ulittle32_t priority_class;
+ llvm::support::ulittle32_t priority;
+ llvm::support::ulittle64_t teb;
+ MinidumpMemoryDescriptor stack;
+ MinidumpLocationDescriptor thread_context;
+
+ static const MinidumpThread *Parse(llvm::ArrayRef<uint8_t> &data);
- static llvm::Optional<std::vector<const MinidumpThread *>>
- ParseThreadList(llvm::ArrayRef<uint8_t> &data);
+ static llvm::Optional<std::vector<const MinidumpThread *>>
+ ParseThreadList(llvm::ArrayRef<uint8_t> &data);
};
-static_assert(sizeof(MinidumpThread) == 48, "sizeof MinidumpThread is not correct!");
+static_assert(sizeof(MinidumpThread) == 48,
+ "sizeof MinidumpThread is not correct!");
-// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx
union MinidumpCPUInfo {
- struct
- {
- llvm::support::ulittle32_t vendor_id[3]; /* cpuid 0: ebx, edx, ecx */
- llvm::support::ulittle32_t version_information; /* cpuid 1: eax */
- llvm::support::ulittle32_t feature_information; /* cpuid 1: edx */
- llvm::support::ulittle32_t amd_extended_cpu_features; /* cpuid 0x80000001, ebx */
- } x86_cpu_info;
- struct
- {
- llvm::support::ulittle32_t cpuid;
- llvm::support::ulittle32_t elf_hwcaps; /* linux specific, 0 otherwise */
- } arm_cpu_info;
- struct
- {
- llvm::support::ulittle64_t processor_features[2];
- } other_cpu_info;
-};
-static_assert(sizeof(MinidumpCPUInfo) == 24, "sizeof MinidumpCPUInfo is not correct!");
-
-// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx
-struct MinidumpSystemInfo
-{
- llvm::support::ulittle16_t processor_arch;
- llvm::support::ulittle16_t processor_level;
- llvm::support::ulittle16_t processor_revision;
-
- uint8_t number_of_processors;
- uint8_t product_type;
-
- llvm::support::ulittle32_t major_version;
- llvm::support::ulittle32_t minor_version;
- llvm::support::ulittle32_t build_number;
- llvm::support::ulittle32_t platform_id;
- llvm::support::ulittle32_t csd_version_rva;
-
- llvm::support::ulittle16_t suit_mask;
- llvm::support::ulittle16_t reserved2;
+ struct {
+ llvm::support::ulittle32_t vendor_id[3]; /* cpuid 0: ebx, edx, ecx */
+ llvm::support::ulittle32_t version_information; /* cpuid 1: eax */
+ llvm::support::ulittle32_t feature_information; /* cpuid 1: edx */
+ llvm::support::ulittle32_t
+ amd_extended_cpu_features; /* cpuid 0x80000001, ebx */
+ } x86_cpu_info;
+ struct {
+ llvm::support::ulittle32_t cpuid;
+ llvm::support::ulittle32_t elf_hwcaps; /* linux specific, 0 otherwise */
+ } arm_cpu_info;
+ struct {
+ llvm::support::ulittle64_t processor_features[2];
+ } other_cpu_info;
+};
+static_assert(sizeof(MinidumpCPUInfo) == 24,
+ "sizeof MinidumpCPUInfo is not correct!");
+
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680396(v=vs.85).aspx
+struct MinidumpSystemInfo {
+ llvm::support::ulittle16_t processor_arch;
+ llvm::support::ulittle16_t processor_level;
+ llvm::support::ulittle16_t processor_revision;
+
+ uint8_t number_of_processors;
+ uint8_t product_type;
+
+ llvm::support::ulittle32_t major_version;
+ llvm::support::ulittle32_t minor_version;
+ llvm::support::ulittle32_t build_number;
+ llvm::support::ulittle32_t platform_id;
+ llvm::support::ulittle32_t csd_version_rva;
+
+ llvm::support::ulittle16_t suit_mask;
+ llvm::support::ulittle16_t reserved2;
- MinidumpCPUInfo cpu;
+ MinidumpCPUInfo cpu;
- static const MinidumpSystemInfo *
- Parse(llvm::ArrayRef<uint8_t> &data);
+ static const MinidumpSystemInfo *Parse(llvm::ArrayRef<uint8_t> &data);
};
-static_assert(sizeof(MinidumpSystemInfo) == 56, "sizeof MinidumpSystemInfo is not correct!");
+static_assert(sizeof(MinidumpSystemInfo) == 56,
+ "sizeof MinidumpSystemInfo is not correct!");
// TODO check flags to see what's valid
// TODO misc2, misc3 ?
-// Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680389(v=vs.85).aspx
-struct MinidumpMiscInfo
-{
- llvm::support::ulittle32_t size;
- llvm::support::ulittle32_t flags1;
- llvm::support::ulittle32_t process_id;
- llvm::support::ulittle32_t process_create_time;
- llvm::support::ulittle32_t process_user_time;
- llvm::support::ulittle32_t process_kernel_time;
+// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680389(v=vs.85).aspx
+struct MinidumpMiscInfo {
+ llvm::support::ulittle32_t size;
+ llvm::support::ulittle32_t flags1;
+ llvm::support::ulittle32_t process_id;
+ llvm::support::ulittle32_t process_create_time;
+ llvm::support::ulittle32_t process_user_time;
+ llvm::support::ulittle32_t process_kernel_time;
- static const MinidumpMiscInfo *
- Parse(llvm::ArrayRef<uint8_t> &data);
+ static const MinidumpMiscInfo *Parse(llvm::ArrayRef<uint8_t> &data);
};
-static_assert(sizeof(MinidumpMiscInfo) == 24, "sizeof MinidumpMiscInfo is not correct!");
+static_assert(sizeof(MinidumpMiscInfo) == 24,
+ "sizeof MinidumpMiscInfo is not correct!");
} // namespace minidump
} // namespace lldb_private
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp Tue Sep 6 15:57:50 2016
@@ -21,73 +21,51 @@ using namespace lldb;
using namespace lldb_private;
ScriptInterpreterNone::ScriptInterpreterNone(CommandInterpreter &interpreter)
- : ScriptInterpreter(interpreter, eScriptLanguageNone)
-{
-}
+ : ScriptInterpreter(interpreter, eScriptLanguageNone) {}
-ScriptInterpreterNone::~ScriptInterpreterNone()
-{
-}
+ScriptInterpreterNone::~ScriptInterpreterNone() {}
-bool
-ScriptInterpreterNone::ExecuteOneLine(const char *command, CommandReturnObject *, const ExecuteScriptOptions &)
-{
- m_interpreter.GetDebugger().GetErrorFile()->PutCString(
- "error: there is no embedded script interpreter in this mode.\n");
- return false;
+bool ScriptInterpreterNone::ExecuteOneLine(const char *command,
+ CommandReturnObject *,
+ const ExecuteScriptOptions &) {
+ m_interpreter.GetDebugger().GetErrorFile()->PutCString(
+ "error: there is no embedded script interpreter in this mode.\n");
+ return false;
}
-void
-ScriptInterpreterNone::ExecuteInterpreterLoop()
-{
- m_interpreter.GetDebugger().GetErrorFile()->PutCString(
- "error: there is no embedded script interpreter in this mode.\n");
+void ScriptInterpreterNone::ExecuteInterpreterLoop() {
+ m_interpreter.GetDebugger().GetErrorFile()->PutCString(
+ "error: there is no embedded script interpreter in this mode.\n");
}
-void
-ScriptInterpreterNone::Initialize()
-{
- static std::once_flag g_once_flag;
+void ScriptInterpreterNone::Initialize() {
+ static std::once_flag g_once_flag;
- std::call_once(g_once_flag, []()
- {
- PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(),
- lldb::eScriptLanguageNone, CreateInstance);
- });
+ std::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ lldb::eScriptLanguageNone, CreateInstance);
+ });
}
-void
-ScriptInterpreterNone::Terminate()
-{
-}
+void ScriptInterpreterNone::Terminate() {}
lldb::ScriptInterpreterSP
-ScriptInterpreterNone::CreateInstance(CommandInterpreter &interpreter)
-{
- return std::make_shared<ScriptInterpreterNone>(interpreter);
+ScriptInterpreterNone::CreateInstance(CommandInterpreter &interpreter) {
+ return std::make_shared<ScriptInterpreterNone>(interpreter);
}
-lldb_private::ConstString
-ScriptInterpreterNone::GetPluginNameStatic()
-{
- static ConstString g_name("script-none");
- return g_name;
+lldb_private::ConstString ScriptInterpreterNone::GetPluginNameStatic() {
+ static ConstString g_name("script-none");
+ return g_name;
}
-const char *
-ScriptInterpreterNone::GetPluginDescriptionStatic()
-{
- return "Null script interpreter";
+const char *ScriptInterpreterNone::GetPluginDescriptionStatic() {
+ return "Null script interpreter";
}
-lldb_private::ConstString
-ScriptInterpreterNone::GetPluginName()
-{
- return GetPluginNameStatic();
+lldb_private::ConstString ScriptInterpreterNone::GetPluginName() {
+ return GetPluginNameStatic();
}
-uint32_t
-ScriptInterpreterNone::GetPluginVersion()
-{
- return 1;
-}
+uint32_t ScriptInterpreterNone::GetPluginVersion() { return 1; }
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h Tue Sep 6 15:57:50 2016
@@ -16,49 +16,40 @@
// Project includes
#include "lldb/Interpreter/ScriptInterpreter.h"
-namespace lldb_private
-{
+namespace lldb_private {
-class ScriptInterpreterNone : public ScriptInterpreter
-{
- public:
- ScriptInterpreterNone(CommandInterpreter &interpreter);
+class ScriptInterpreterNone : public ScriptInterpreter {
+public:
+ ScriptInterpreterNone(CommandInterpreter &interpreter);
- ~ScriptInterpreterNone() override;
+ ~ScriptInterpreterNone() override;
- bool
- ExecuteOneLine(const char *command, CommandReturnObject *result,
- const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
+ bool ExecuteOneLine(
+ const char *command, CommandReturnObject *result,
+ const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
- void
- ExecuteInterpreterLoop() override;
+ void ExecuteInterpreterLoop() override;
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
- static void
- Terminate();
+ static void Terminate();
- static lldb::ScriptInterpreterSP
- CreateInstance(CommandInterpreter &interpreter);
+ static lldb::ScriptInterpreterSP
+ CreateInstance(CommandInterpreter &interpreter);
- static lldb_private::ConstString
- GetPluginNameStatic();
+ static lldb_private::ConstString GetPluginNameStatic();
- static const char *
- GetPluginDescriptionStatic();
+ static const char *GetPluginDescriptionStatic();
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString
- GetPluginName() override;
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
- uint32_t
- GetPluginVersion() override;
+ uint32_t GetPluginVersion() override;
};
} // namespace lldb_private
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp Tue Sep 6 15:57:50 2016
@@ -1,4 +1,5 @@
-//===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===//
+//===-- PythonDataObjects.cpp ------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -30,1284 +31,1020 @@
using namespace lldb_private;
using namespace lldb;
-void
-StructuredPythonObject::Dump(Stream &s, bool pretty_print) const
-{
- s << "Python Obj: 0x" << GetValue();
+void StructuredPythonObject::Dump(Stream &s, bool pretty_print) const {
+ s << "Python Obj: 0x" << GetValue();
}
//----------------------------------------------------------------------
// PythonObject
//----------------------------------------------------------------------
-void
-PythonObject::Dump(Stream &strm) const
-{
- if (m_py_obj)
- {
- FILE *file = ::tmpfile();
- if (file)
- {
- ::PyObject_Print (m_py_obj, file, 0);
- const long length = ftell (file);
- if (length)
- {
- ::rewind(file);
- std::vector<char> file_contents (length,'\0');
- const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
- if (length_read > 0)
- strm.Write (file_contents.data(), length_read);
- }
- ::fclose (file);
- }
- }
- else
- strm.PutCString ("NULL");
-}
-
-PyObjectType
-PythonObject::GetObjectType() const
-{
- if (!IsAllocated())
- return PyObjectType::None;
-
- if (PythonModule::Check(m_py_obj))
- return PyObjectType::Module;
- if (PythonList::Check(m_py_obj))
- return PyObjectType::List;
- if (PythonTuple::Check(m_py_obj))
- return PyObjectType::Tuple;
- if (PythonDictionary::Check(m_py_obj))
- return PyObjectType::Dictionary;
- if (PythonString::Check(m_py_obj))
- return PyObjectType::String;
+void PythonObject::Dump(Stream &strm) const {
+ if (m_py_obj) {
+ FILE *file = ::tmpfile();
+ if (file) {
+ ::PyObject_Print(m_py_obj, file, 0);
+ const long length = ftell(file);
+ if (length) {
+ ::rewind(file);
+ std::vector<char> file_contents(length, '\0');
+ const size_t length_read =
+ ::fread(file_contents.data(), 1, file_contents.size(), file);
+ if (length_read > 0)
+ strm.Write(file_contents.data(), length_read);
+ }
+ ::fclose(file);
+ }
+ } else
+ strm.PutCString("NULL");
+}
+
+PyObjectType PythonObject::GetObjectType() const {
+ if (!IsAllocated())
+ return PyObjectType::None;
+
+ if (PythonModule::Check(m_py_obj))
+ return PyObjectType::Module;
+ if (PythonList::Check(m_py_obj))
+ return PyObjectType::List;
+ if (PythonTuple::Check(m_py_obj))
+ return PyObjectType::Tuple;
+ if (PythonDictionary::Check(m_py_obj))
+ return PyObjectType::Dictionary;
+ if (PythonString::Check(m_py_obj))
+ return PyObjectType::String;
#if PY_MAJOR_VERSION >= 3
- if (PythonBytes::Check(m_py_obj))
- return PyObjectType::Bytes;
+ if (PythonBytes::Check(m_py_obj))
+ return PyObjectType::Bytes;
#endif
- if (PythonByteArray::Check(m_py_obj))
- return PyObjectType::ByteArray;
- if (PythonInteger::Check(m_py_obj))
- return PyObjectType::Integer;
- if (PythonFile::Check(m_py_obj))
- return PyObjectType::File;
- if (PythonCallable::Check(m_py_obj))
- return PyObjectType::Callable;
- return PyObjectType::Unknown;
-}
-
-PythonString
-PythonObject::Repr() const
-{
- if (!m_py_obj)
- return PythonString();
- PyObject *repr = PyObject_Repr(m_py_obj);
- if (!repr)
- return PythonString();
- return PythonString(PyRefType::Owned, repr);
-}
-
-PythonString
-PythonObject::Str() const
-{
- if (!m_py_obj)
- return PythonString();
- PyObject *str = PyObject_Str(m_py_obj);
- if (!str)
- return PythonString();
- return PythonString(PyRefType::Owned, str);
+ if (PythonByteArray::Check(m_py_obj))
+ return PyObjectType::ByteArray;
+ if (PythonInteger::Check(m_py_obj))
+ return PyObjectType::Integer;
+ if (PythonFile::Check(m_py_obj))
+ return PyObjectType::File;
+ if (PythonCallable::Check(m_py_obj))
+ return PyObjectType::Callable;
+ return PyObjectType::Unknown;
+}
+
+PythonString PythonObject::Repr() const {
+ if (!m_py_obj)
+ return PythonString();
+ PyObject *repr = PyObject_Repr(m_py_obj);
+ if (!repr)
+ return PythonString();
+ return PythonString(PyRefType::Owned, repr);
+}
+
+PythonString PythonObject::Str() const {
+ if (!m_py_obj)
+ return PythonString();
+ PyObject *str = PyObject_Str(m_py_obj);
+ if (!str)
+ return PythonString();
+ return PythonString(PyRefType::Owned, str);
}
PythonObject
-PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
-{
- size_t dot_pos = name.find_first_of('.');
- llvm::StringRef piece = name.substr(0, dot_pos);
- PythonObject result = dict.GetItemForKey(PythonString(piece));
- if (dot_pos == llvm::StringRef::npos)
- {
- // There was no dot, we're done.
- return result;
- }
+PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
+ const PythonDictionary &dict) {
+ size_t dot_pos = name.find_first_of('.');
+ llvm::StringRef piece = name.substr(0, dot_pos);
+ PythonObject result = dict.GetItemForKey(PythonString(piece));
+ if (dot_pos == llvm::StringRef::npos) {
+ // There was no dot, we're done.
+ return result;
+ }
+
+ // There was a dot. The remaining portion of the name should be looked up in
+ // the context of the object that was found in the dictionary.
+ return result.ResolveName(name.substr(dot_pos + 1));
+}
+
+PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
+ // Resolve the name in the context of the specified object. If,
+ // for example, `this` refers to a PyModule, then this will look for
+ // `name` in this module. If `this` refers to a PyType, then it will
+ // resolve `name` as an attribute of that type. If `this` refers to
+ // an instance of an object, then it will resolve `name` as the value
+ // of the specified field.
+ //
+ // This function handles dotted names so that, for example, if `m_py_obj`
+ // refers to the `sys` module, and `name` == "path.append", then it
+ // will find the function `sys.path.append`.
+
+ size_t dot_pos = name.find_first_of('.');
+ if (dot_pos == llvm::StringRef::npos) {
+ // No dots in the name, we should be able to find the value immediately
+ // as an attribute of `m_py_obj`.
+ return GetAttributeValue(name);
+ }
+
+ // Look up the first piece of the name, and resolve the rest as a child of
+ // that.
+ PythonObject parent = ResolveName(name.substr(0, dot_pos));
+ if (!parent.IsAllocated())
+ return PythonObject();
- // There was a dot. The remaining portion of the name should be looked up in
- // the context of the object that was found in the dictionary.
- return result.ResolveName(name.substr(dot_pos + 1));
+ // Tail recursion.. should be optimized by the compiler
+ return parent.ResolveName(name.substr(dot_pos + 1));
}
-PythonObject
-PythonObject::ResolveName(llvm::StringRef name) const
-{
- // Resolve the name in the context of the specified object. If,
- // for example, `this` refers to a PyModule, then this will look for
- // `name` in this module. If `this` refers to a PyType, then it will
- // resolve `name` as an attribute of that type. If `this` refers to
- // an instance of an object, then it will resolve `name` as the value
- // of the specified field.
- //
- // This function handles dotted names so that, for example, if `m_py_obj`
- // refers to the `sys` module, and `name` == "path.append", then it
- // will find the function `sys.path.append`.
-
- size_t dot_pos = name.find_first_of('.');
- if (dot_pos == llvm::StringRef::npos)
- {
- // No dots in the name, we should be able to find the value immediately
- // as an attribute of `m_py_obj`.
- return GetAttributeValue(name);
- }
+bool PythonObject::HasAttribute(llvm::StringRef attr) const {
+ if (!IsValid())
+ return false;
+ PythonString py_attr(attr);
+ return !!PyObject_HasAttr(m_py_obj, py_attr.get());
+}
+
+PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
+ if (!IsValid())
+ return PythonObject();
+
+ PythonString py_attr(attr);
+ if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
+ return PythonObject();
- // Look up the first piece of the name, and resolve the rest as a child of that.
- PythonObject parent = ResolveName(name.substr(0, dot_pos));
- if (!parent.IsAllocated())
- return PythonObject();
-
- // Tail recursion.. should be optimized by the compiler
- return parent.ResolveName(name.substr(dot_pos + 1));
-}
-
-bool
-PythonObject::HasAttribute(llvm::StringRef attr) const
-{
- if (!IsValid())
- return false;
- PythonString py_attr(attr);
- return !!PyObject_HasAttr(m_py_obj, py_attr.get());
+ return PythonObject(PyRefType::Owned,
+ PyObject_GetAttr(m_py_obj, py_attr.get()));
}
-PythonObject
-PythonObject::GetAttributeValue(llvm::StringRef attr) const
-{
- if (!IsValid())
- return PythonObject();
-
- PythonString py_attr(attr);
- if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
- return PythonObject();
-
- return PythonObject(PyRefType::Owned,
- PyObject_GetAttr(m_py_obj, py_attr.get()));
-}
-
-bool
-PythonObject::IsNone() const
-{
- return m_py_obj == Py_None;
-}
-
-bool
-PythonObject::IsValid() const
-{
- return m_py_obj != nullptr;
-}
-
-bool
-PythonObject::IsAllocated() const
-{
- return IsValid() && !IsNone();
-}
-
-StructuredData::ObjectSP
-PythonObject::CreateStructuredObject() const
-{
- switch (GetObjectType())
- {
- case PyObjectType::Dictionary:
- return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
- case PyObjectType::Integer:
- return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
- case PyObjectType::List:
- return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
- case PyObjectType::String:
- return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
- case PyObjectType::Bytes:
- return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
- case PyObjectType::ByteArray:
- return PythonByteArray(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
- case PyObjectType::None:
- return StructuredData::ObjectSP();
- default:
- return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
- }
+bool PythonObject::IsNone() const { return m_py_obj == Py_None; }
+
+bool PythonObject::IsValid() const { return m_py_obj != nullptr; }
+
+bool PythonObject::IsAllocated() const { return IsValid() && !IsNone(); }
+
+StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
+ switch (GetObjectType()) {
+ case PyObjectType::Dictionary:
+ return PythonDictionary(PyRefType::Borrowed, m_py_obj)
+ .CreateStructuredDictionary();
+ case PyObjectType::Integer:
+ return PythonInteger(PyRefType::Borrowed, m_py_obj)
+ .CreateStructuredInteger();
+ case PyObjectType::List:
+ return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
+ case PyObjectType::String:
+ return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
+ case PyObjectType::Bytes:
+ return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
+ case PyObjectType::ByteArray:
+ return PythonByteArray(PyRefType::Borrowed, m_py_obj)
+ .CreateStructuredString();
+ case PyObjectType::None:
+ return StructuredData::ObjectSP();
+ default:
+ return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
+ }
}
//----------------------------------------------------------------------
// PythonString
//----------------------------------------------------------------------
-PythonBytes::PythonBytes() : PythonObject()
-{
-}
+PythonBytes::PythonBytes() : PythonObject() {}
-PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject()
-{
- SetBytes(bytes);
+PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() {
+ SetBytes(bytes);
}
-PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject()
-{
- SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
+PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() {
+ SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
}
-PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject()
-{
- Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
+PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() {
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
}
-PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object)
-{
-}
+PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object) {}
-PythonBytes::~PythonBytes()
-{
-}
+PythonBytes::~PythonBytes() {}
-bool
-PythonBytes::Check(PyObject *py_obj)
-{
- if (!py_obj)
- return false;
- if (PyBytes_Check(py_obj))
- return true;
+bool PythonBytes::Check(PyObject *py_obj) {
+ if (!py_obj)
return false;
+ if (PyBytes_Check(py_obj))
+ return true;
+ return false;
}
-void
-PythonBytes::Reset(PyRefType type, PyObject *py_obj)
-{
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
- PythonObject result(type, py_obj);
-
- if (!PythonBytes::Check(py_obj))
- {
- PythonObject::Reset();
- return;
- }
+void PythonBytes::Reset(PyRefType type, PyObject *py_obj) {
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
- // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
- // back into the virtual implementation.
- PythonObject::Reset(PyRefType::Borrowed, result.get());
-}
-
-llvm::ArrayRef<uint8_t>
-PythonBytes::GetBytes() const
-{
- if (!IsValid())
- return llvm::ArrayRef<uint8_t>();
-
- Py_ssize_t size;
- char *c;
-
- PyBytes_AsStringAndSize(m_py_obj, &c, &size);
- return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
-}
-
-size_t
-PythonBytes::GetSize() const
-{
- if (!IsValid())
- return 0;
- return PyBytes_Size(m_py_obj);
-}
-
-void
-PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes)
-{
- const char *data = reinterpret_cast<const char *>(bytes.data());
- PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
- PythonObject::Reset(PyRefType::Owned, py_bytes);
-}
-
-StructuredData::StringSP
-PythonBytes::CreateStructuredString() const
-{
- StructuredData::StringSP result(new StructuredData::String);
- Py_ssize_t size;
- char *c;
- PyBytes_AsStringAndSize(m_py_obj, &c, &size);
- result->SetValue(std::string(c, size));
- return result;
+ if (!PythonBytes::Check(py_obj)) {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
}
-PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) : PythonByteArray(bytes.data(), bytes.size())
-{
+llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
+ if (!IsValid())
+ return llvm::ArrayRef<uint8_t>();
+
+ Py_ssize_t size;
+ char *c;
+
+ PyBytes_AsStringAndSize(m_py_obj, &c, &size);
+ return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
}
-PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length)
-{
- const char *str = reinterpret_cast<const char *>(bytes);
- Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length));
+size_t PythonBytes::GetSize() const {
+ if (!IsValid())
+ return 0;
+ return PyBytes_Size(m_py_obj);
}
-PythonByteArray::PythonByteArray(PyRefType type, PyObject *o)
-{
- Reset(type, o);
+void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
+ const char *data = reinterpret_cast<const char *>(bytes.data());
+ PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
+ PythonObject::Reset(PyRefType::Owned, py_bytes);
}
-PythonByteArray::PythonByteArray(const PythonBytes &object) : PythonObject(object)
-{
+StructuredData::StringSP PythonBytes::CreateStructuredString() const {
+ StructuredData::StringSP result(new StructuredData::String);
+ Py_ssize_t size;
+ char *c;
+ PyBytes_AsStringAndSize(m_py_obj, &c, &size);
+ result->SetValue(std::string(c, size));
+ return result;
}
-PythonByteArray::~PythonByteArray()
-{
+PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
+ : PythonByteArray(bytes.data(), bytes.size()) {}
+
+PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
+ const char *str = reinterpret_cast<const char *>(bytes);
+ Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length));
+}
+
+PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) {
+ Reset(type, o);
}
-bool
-PythonByteArray::Check(PyObject *py_obj)
-{
- if (!py_obj)
- return false;
- if (PyByteArray_Check(py_obj))
- return true;
+PythonByteArray::PythonByteArray(const PythonBytes &object)
+ : PythonObject(object) {}
+
+PythonByteArray::~PythonByteArray() {}
+
+bool PythonByteArray::Check(PyObject *py_obj) {
+ if (!py_obj)
return false;
+ if (PyByteArray_Check(py_obj))
+ return true;
+ return false;
}
-void
-PythonByteArray::Reset(PyRefType type, PyObject *py_obj)
-{
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
- PythonObject result(type, py_obj);
-
- if (!PythonByteArray::Check(py_obj))
- {
- PythonObject::Reset();
- return;
- }
+void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) {
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
- // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
- // back into the virtual implementation.
- PythonObject::Reset(PyRefType::Borrowed, result.get());
-}
-
-llvm::ArrayRef<uint8_t>
-PythonByteArray::GetBytes() const
-{
- if (!IsValid())
- return llvm::ArrayRef<uint8_t>();
-
- char *c = PyByteArray_AsString(m_py_obj);
- size_t size = GetSize();
- return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
-}
-
-size_t
-PythonByteArray::GetSize() const
-{
- if (!IsValid())
- return 0;
-
- return PyByteArray_Size(m_py_obj);
-}
-
-StructuredData::StringSP
-PythonByteArray::CreateStructuredString() const
-{
- StructuredData::StringSP result(new StructuredData::String);
- llvm::ArrayRef<uint8_t> bytes = GetBytes();
- const char *str = reinterpret_cast<const char *>(bytes.data());
- result->SetValue(std::string(str, bytes.size()));
- return result;
+ if (!PythonByteArray::Check(py_obj)) {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
}
-//----------------------------------------------------------------------
-// PythonString
-//----------------------------------------------------------------------
+llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
+ if (!IsValid())
+ return llvm::ArrayRef<uint8_t>();
-PythonString::PythonString(PyRefType type, PyObject *py_obj)
- : PythonObject()
-{
- Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
+ char *c = PyByteArray_AsString(m_py_obj);
+ size_t size = GetSize();
+ return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
}
-PythonString::PythonString(const PythonString &object)
- : PythonObject(object)
-{
+size_t PythonByteArray::GetSize() const {
+ if (!IsValid())
+ return 0;
+
+ return PyByteArray_Size(m_py_obj);
}
-PythonString::PythonString(llvm::StringRef string)
- : PythonObject()
-{
- SetString(string);
+StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
+ StructuredData::StringSP result(new StructuredData::String);
+ llvm::ArrayRef<uint8_t> bytes = GetBytes();
+ const char *str = reinterpret_cast<const char *>(bytes.data());
+ result->SetValue(std::string(str, bytes.size()));
+ return result;
}
-PythonString::PythonString(const char *string)
- : PythonObject()
-{
- SetString(llvm::StringRef(string));
+//----------------------------------------------------------------------
+// PythonString
+//----------------------------------------------------------------------
+
+PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() {
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
}
-PythonString::PythonString()
- : PythonObject()
-{
+PythonString::PythonString(const PythonString &object) : PythonObject(object) {}
+
+PythonString::PythonString(llvm::StringRef string) : PythonObject() {
+ SetString(string);
}
-PythonString::~PythonString ()
-{
+PythonString::PythonString(const char *string) : PythonObject() {
+ SetString(llvm::StringRef(string));
}
-bool
-PythonString::Check(PyObject *py_obj)
-{
- if (!py_obj)
- return false;
+PythonString::PythonString() : PythonObject() {}
- if (PyUnicode_Check(py_obj))
- return true;
+PythonString::~PythonString() {}
+
+bool PythonString::Check(PyObject *py_obj) {
+ if (!py_obj)
+ return false;
+
+ if (PyUnicode_Check(py_obj))
+ return true;
#if PY_MAJOR_VERSION < 3
- if (PyString_Check(py_obj))
- return true;
+ if (PyString_Check(py_obj))
+ return true;
#endif
- return false;
+ return false;
}
-void
-PythonString::Reset(PyRefType type, PyObject *py_obj)
-{
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
- PythonObject result(type, py_obj);
-
- if (!PythonString::Check(py_obj))
- {
- PythonObject::Reset();
- return;
- }
+void PythonString::Reset(PyRefType type, PyObject *py_obj) {
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonString::Check(py_obj)) {
+ PythonObject::Reset();
+ return;
+ }
#if PY_MAJOR_VERSION < 3
- // In Python 2, Don't store PyUnicode objects directly, because we need
- // access to their underlying character buffers which Python 2 doesn't
- // provide.
- if (PyUnicode_Check(py_obj))
- result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
+ // In Python 2, Don't store PyUnicode objects directly, because we need
+ // access to their underlying character buffers which Python 2 doesn't
+ // provide.
+ if (PyUnicode_Check(py_obj))
+ result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
#endif
- // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
- // back into the virtual implementation.
- PythonObject::Reset(PyRefType::Borrowed, result.get());
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
}
-llvm::StringRef
-PythonString::GetString() const
-{
- if (!IsValid())
- return llvm::StringRef();
+llvm::StringRef PythonString::GetString() const {
+ if (!IsValid())
+ return llvm::StringRef();
- Py_ssize_t size;
- char *c;
+ Py_ssize_t size;
+ char *c;
#if PY_MAJOR_VERSION >= 3
- c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
+ c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
#else
- PyString_AsStringAndSize(m_py_obj, &c, &size);
+ PyString_AsStringAndSize(m_py_obj, &c, &size);
#endif
- return llvm::StringRef(c, size);
+ return llvm::StringRef(c, size);
}
-size_t
-PythonString::GetSize() const
-{
- if (IsValid())
- {
+size_t PythonString::GetSize() const {
+ if (IsValid()) {
#if PY_MAJOR_VERSION >= 3
- return PyUnicode_GetSize(m_py_obj);
+ return PyUnicode_GetSize(m_py_obj);
#else
- return PyString_Size(m_py_obj);
+ return PyString_Size(m_py_obj);
#endif
- }
- return 0;
+ }
+ return 0;
}
-void
-PythonString::SetString (llvm::StringRef string)
-{
+void PythonString::SetString(llvm::StringRef string) {
#if PY_MAJOR_VERSION >= 3
- PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
- PythonObject::Reset(PyRefType::Owned, unicode);
+ PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
+ PythonObject::Reset(PyRefType::Owned, unicode);
#else
- PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
- PythonObject::Reset(PyRefType::Owned, str);
+ PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
+ PythonObject::Reset(PyRefType::Owned, str);
#endif
}
-StructuredData::StringSP
-PythonString::CreateStructuredString() const
-{
- StructuredData::StringSP result(new StructuredData::String);
- result->SetValue(GetString());
- return result;
+StructuredData::StringSP PythonString::CreateStructuredString() const {
+ StructuredData::StringSP result(new StructuredData::String);
+ result->SetValue(GetString());
+ return result;
}
//----------------------------------------------------------------------
// PythonInteger
//----------------------------------------------------------------------
-PythonInteger::PythonInteger()
- : PythonObject()
-{
-
-}
+PythonInteger::PythonInteger() : PythonObject() {}
PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
- : PythonObject()
-{
- Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
+ : PythonObject() {
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
}
PythonInteger::PythonInteger(const PythonInteger &object)
- : PythonObject(object)
-{
-}
+ : PythonObject(object) {}
-PythonInteger::PythonInteger(int64_t value)
- : PythonObject()
-{
- SetInteger(value);
+PythonInteger::PythonInteger(int64_t value) : PythonObject() {
+ SetInteger(value);
}
+PythonInteger::~PythonInteger() {}
-PythonInteger::~PythonInteger ()
-{
-}
-
-bool
-PythonInteger::Check(PyObject *py_obj)
-{
- if (!py_obj)
- return false;
+bool PythonInteger::Check(PyObject *py_obj) {
+ if (!py_obj)
+ return false;
#if PY_MAJOR_VERSION >= 3
- // Python 3 does not have PyInt_Check. There is only one type of
- // integral value, long.
- return PyLong_Check(py_obj);
+ // Python 3 does not have PyInt_Check. There is only one type of
+ // integral value, long.
+ return PyLong_Check(py_obj);
#else
- return PyLong_Check(py_obj) || PyInt_Check(py_obj);
+ return PyLong_Check(py_obj) || PyInt_Check(py_obj);
#endif
}
-void
-PythonInteger::Reset(PyRefType type, PyObject *py_obj)
-{
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
- PythonObject result(type, py_obj);
-
- if (!PythonInteger::Check(py_obj))
- {
- PythonObject::Reset();
- return;
- }
+void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonInteger::Check(py_obj)) {
+ PythonObject::Reset();
+ return;
+ }
#if PY_MAJOR_VERSION < 3
- // Always store this as a PyLong, which makes interoperability between
- // Python 2.x and Python 3.x easier. This is only necessary in 2.x,
- // since 3.x doesn't even have a PyInt.
- if (PyInt_Check(py_obj))
- {
- // Since we converted the original object to a different type, the new
- // object is an owned object regardless of the ownership semantics requested
- // by the user.
- result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
- }
+ // Always store this as a PyLong, which makes interoperability between
+ // Python 2.x and Python 3.x easier. This is only necessary in 2.x,
+ // since 3.x doesn't even have a PyInt.
+ if (PyInt_Check(py_obj)) {
+ // Since we converted the original object to a different type, the new
+ // object is an owned object regardless of the ownership semantics requested
+ // by the user.
+ result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
+ }
#endif
- assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
+ assert(PyLong_Check(result.get()) &&
+ "Couldn't get a PyLong from this PyObject");
- // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
- // back into the virtual implementation.
- PythonObject::Reset(PyRefType::Borrowed, result.get());
-}
-
-int64_t
-PythonInteger::GetInteger() const
-{
- if (m_py_obj)
- {
- assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
-
- int overflow = 0;
- int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
- if (overflow != 0)
- {
- // We got an integer that overflows, like 18446744072853913392L
- // we can't use PyLong_AsLongLong() as it will return
- // 0xffffffffffffffff. If we use the unsigned long long
- // it will work as expected.
- const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
- result = *((int64_t *)&uval);
- }
- return result;
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+int64_t PythonInteger::GetInteger() const {
+ if (m_py_obj) {
+ assert(PyLong_Check(m_py_obj) &&
+ "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
+
+ int overflow = 0;
+ int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
+ if (overflow != 0) {
+ // We got an integer that overflows, like 18446744072853913392L
+ // we can't use PyLong_AsLongLong() as it will return
+ // 0xffffffffffffffff. If we use the unsigned long long
+ // it will work as expected.
+ const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
+ result = *((int64_t *)&uval);
}
- return UINT64_MAX;
+ return result;
+ }
+ return UINT64_MAX;
}
-void
-PythonInteger::SetInteger(int64_t value)
-{
- PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
+void PythonInteger::SetInteger(int64_t value) {
+ PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
}
-StructuredData::IntegerSP
-PythonInteger::CreateStructuredInteger() const
-{
- StructuredData::IntegerSP result(new StructuredData::Integer);
- result->SetValue(GetInteger());
- return result;
+StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
+ StructuredData::IntegerSP result(new StructuredData::Integer);
+ result->SetValue(GetInteger());
+ return result;
}
//----------------------------------------------------------------------
// PythonList
//----------------------------------------------------------------------
-PythonList::PythonList(PyInitialValue value)
- : PythonObject()
-{
- if (value == PyInitialValue::Empty)
- Reset(PyRefType::Owned, PyList_New(0));
-}
-
-PythonList::PythonList(int list_size)
- : PythonObject()
-{
- Reset(PyRefType::Owned, PyList_New(list_size));
-}
-
-PythonList::PythonList(PyRefType type, PyObject *py_obj)
- : PythonObject()
-{
- Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
-}
-
-PythonList::PythonList(const PythonList &list)
- : PythonObject(list)
-{
-}
-
-PythonList::~PythonList ()
-{
+PythonList::PythonList(PyInitialValue value) : PythonObject() {
+ if (value == PyInitialValue::Empty)
+ Reset(PyRefType::Owned, PyList_New(0));
}
-bool
-PythonList::Check(PyObject *py_obj)
-{
- if (!py_obj)
- return false;
- return PyList_Check(py_obj);
+PythonList::PythonList(int list_size) : PythonObject() {
+ Reset(PyRefType::Owned, PyList_New(list_size));
}
-void
-PythonList::Reset(PyRefType type, PyObject *py_obj)
-{
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
- PythonObject result(type, py_obj);
-
- if (!PythonList::Check(py_obj))
- {
- PythonObject::Reset();
- return;
- }
-
- // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
- // back into the virtual implementation.
- PythonObject::Reset(PyRefType::Borrowed, result.get());
-}
-
-uint32_t
-PythonList::GetSize() const
-{
- if (IsValid())
- return PyList_GET_SIZE(m_py_obj);
- return 0;
+PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() {
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
}
-PythonObject
-PythonList::GetItemAtIndex(uint32_t index) const
-{
- if (IsValid())
- return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
- return PythonObject();
-}
+PythonList::PythonList(const PythonList &list) : PythonObject(list) {}
-void
-PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
-{
- if (IsAllocated() && object.IsValid())
- {
- // PyList_SetItem is documented to "steal" a reference, so we need to
- // convert it to an owned reference by incrementing it.
- Py_INCREF(object.get());
- PyList_SetItem(m_py_obj, index, object.get());
- }
-}
+PythonList::~PythonList() {}
-void
-PythonList::AppendItem(const PythonObject &object)
-{
- if (IsAllocated() && object.IsValid())
- {
- // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
- // here like we do with `PyList_SetItem`.
- PyList_Append(m_py_obj, object.get());
- }
+bool PythonList::Check(PyObject *py_obj) {
+ if (!py_obj)
+ return false;
+ return PyList_Check(py_obj);
}
-StructuredData::ArraySP
-PythonList::CreateStructuredArray() const
-{
- StructuredData::ArraySP result(new StructuredData::Array);
- uint32_t count = GetSize();
- for (uint32_t i = 0; i < count; ++i)
- {
- PythonObject obj = GetItemAtIndex(i);
- result->AddItem(obj.CreateStructuredObject());
- }
- return result;
+void PythonList::Reset(PyRefType type, PyObject *py_obj) {
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonList::Check(py_obj)) {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+uint32_t PythonList::GetSize() const {
+ if (IsValid())
+ return PyList_GET_SIZE(m_py_obj);
+ return 0;
+}
+
+PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
+ if (IsValid())
+ return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
+ return PythonObject();
+}
+
+void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
+ if (IsAllocated() && object.IsValid()) {
+ // PyList_SetItem is documented to "steal" a reference, so we need to
+ // convert it to an owned reference by incrementing it.
+ Py_INCREF(object.get());
+ PyList_SetItem(m_py_obj, index, object.get());
+ }
+}
+
+void PythonList::AppendItem(const PythonObject &object) {
+ if (IsAllocated() && object.IsValid()) {
+ // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
+ // here like we do with `PyList_SetItem`.
+ PyList_Append(m_py_obj, object.get());
+ }
+}
+
+StructuredData::ArraySP PythonList::CreateStructuredArray() const {
+ StructuredData::ArraySP result(new StructuredData::Array);
+ uint32_t count = GetSize();
+ for (uint32_t i = 0; i < count; ++i) {
+ PythonObject obj = GetItemAtIndex(i);
+ result->AddItem(obj.CreateStructuredObject());
+ }
+ return result;
}
//----------------------------------------------------------------------
// PythonTuple
//----------------------------------------------------------------------
-PythonTuple::PythonTuple(PyInitialValue value)
- : PythonObject()
-{
- if (value == PyInitialValue::Empty)
- Reset(PyRefType::Owned, PyTuple_New(0));
+PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() {
+ if (value == PyInitialValue::Empty)
+ Reset(PyRefType::Owned, PyTuple_New(0));
}
-PythonTuple::PythonTuple(int tuple_size)
- : PythonObject()
-{
- Reset(PyRefType::Owned, PyTuple_New(tuple_size));
+PythonTuple::PythonTuple(int tuple_size) : PythonObject() {
+ Reset(PyRefType::Owned, PyTuple_New(tuple_size));
}
-PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj)
- : PythonObject()
-{
- Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
+PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() {
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
}
-PythonTuple::PythonTuple(const PythonTuple &tuple)
- : PythonObject(tuple)
-{
-}
+PythonTuple::PythonTuple(const PythonTuple &tuple) : PythonObject(tuple) {}
-PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects)
-{
- m_py_obj = PyTuple_New(objects.size());
+PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
+ m_py_obj = PyTuple_New(objects.size());
- uint32_t idx = 0;
- for (auto object : objects)
- {
- if (object.IsValid())
- SetItemAtIndex(idx, object);
- idx++;
- }
+ uint32_t idx = 0;
+ for (auto object : objects) {
+ if (object.IsValid())
+ SetItemAtIndex(idx, object);
+ idx++;
+ }
}
-PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects)
-{
- m_py_obj = PyTuple_New(objects.size());
-
- uint32_t idx = 0;
- for (auto py_object : objects)
- {
- PythonObject object(PyRefType::Borrowed, py_object);
- if (object.IsValid())
- SetItemAtIndex(idx, object);
- idx++;
- }
-}
+PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
+ m_py_obj = PyTuple_New(objects.size());
-PythonTuple::~PythonTuple()
-{
+ uint32_t idx = 0;
+ for (auto py_object : objects) {
+ PythonObject object(PyRefType::Borrowed, py_object);
+ if (object.IsValid())
+ SetItemAtIndex(idx, object);
+ idx++;
+ }
}
-bool
-PythonTuple::Check(PyObject *py_obj)
-{
- if (!py_obj)
- return false;
- return PyTuple_Check(py_obj);
-}
-
-void
-PythonTuple::Reset(PyRefType type, PyObject *py_obj)
-{
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
- PythonObject result(type, py_obj);
-
- if (!PythonTuple::Check(py_obj))
- {
- PythonObject::Reset();
- return;
- }
+PythonTuple::~PythonTuple() {}
- // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
- // back into the virtual implementation.
- PythonObject::Reset(PyRefType::Borrowed, result.get());
-}
-
-uint32_t
-PythonTuple::GetSize() const
-{
- if (IsValid())
- return PyTuple_GET_SIZE(m_py_obj);
- return 0;
-}
-
-PythonObject
-PythonTuple::GetItemAtIndex(uint32_t index) const
-{
- if (IsValid())
- return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
- return PythonObject();
-}
-
-void
-PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object)
-{
- if (IsAllocated() && object.IsValid())
- {
- // PyTuple_SetItem is documented to "steal" a reference, so we need to
- // convert it to an owned reference by incrementing it.
- Py_INCREF(object.get());
- PyTuple_SetItem(m_py_obj, index, object.get());
- }
+bool PythonTuple::Check(PyObject *py_obj) {
+ if (!py_obj)
+ return false;
+ return PyTuple_Check(py_obj);
}
-StructuredData::ArraySP
-PythonTuple::CreateStructuredArray() const
-{
- StructuredData::ArraySP result(new StructuredData::Array);
- uint32_t count = GetSize();
- for (uint32_t i = 0; i < count; ++i)
- {
- PythonObject obj = GetItemAtIndex(i);
- result->AddItem(obj.CreateStructuredObject());
- }
- return result;
+void PythonTuple::Reset(PyRefType type, PyObject *py_obj) {
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonTuple::Check(py_obj)) {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+uint32_t PythonTuple::GetSize() const {
+ if (IsValid())
+ return PyTuple_GET_SIZE(m_py_obj);
+ return 0;
+}
+
+PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
+ if (IsValid())
+ return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
+ return PythonObject();
+}
+
+void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
+ if (IsAllocated() && object.IsValid()) {
+ // PyTuple_SetItem is documented to "steal" a reference, so we need to
+ // convert it to an owned reference by incrementing it.
+ Py_INCREF(object.get());
+ PyTuple_SetItem(m_py_obj, index, object.get());
+ }
+}
+
+StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
+ StructuredData::ArraySP result(new StructuredData::Array);
+ uint32_t count = GetSize();
+ for (uint32_t i = 0; i < count; ++i) {
+ PythonObject obj = GetItemAtIndex(i);
+ result->AddItem(obj.CreateStructuredObject());
+ }
+ return result;
}
//----------------------------------------------------------------------
// PythonDictionary
//----------------------------------------------------------------------
-PythonDictionary::PythonDictionary(PyInitialValue value)
- : PythonObject()
-{
- if (value == PyInitialValue::Empty)
- Reset(PyRefType::Owned, PyDict_New());
+PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() {
+ if (value == PyInitialValue::Empty)
+ Reset(PyRefType::Owned, PyDict_New());
}
PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
- : PythonObject()
-{
- Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
+ : PythonObject() {
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
}
PythonDictionary::PythonDictionary(const PythonDictionary &object)
- : PythonObject(object)
-{
-}
+ : PythonObject(object) {}
-PythonDictionary::~PythonDictionary ()
-{
-}
+PythonDictionary::~PythonDictionary() {}
-bool
-PythonDictionary::Check(PyObject *py_obj)
-{
- if (!py_obj)
- return false;
+bool PythonDictionary::Check(PyObject *py_obj) {
+ if (!py_obj)
+ return false;
- return PyDict_Check(py_obj);
+ return PyDict_Check(py_obj);
}
-void
-PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
-{
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
- PythonObject result(type, py_obj);
+void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) {
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
- if (!PythonDictionary::Check(py_obj))
- {
- PythonObject::Reset();
- return;
- }
+ if (!PythonDictionary::Check(py_obj)) {
+ PythonObject::Reset();
+ return;
+ }
- // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
- // back into the virtual implementation.
- PythonObject::Reset(PyRefType::Borrowed, result.get());
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
}
-uint32_t
-PythonDictionary::GetSize() const
-{
- if (IsValid())
- return PyDict_Size(m_py_obj);
- return 0;
+uint32_t PythonDictionary::GetSize() const {
+ if (IsValid())
+ return PyDict_Size(m_py_obj);
+ return 0;
}
-PythonList
-PythonDictionary::GetKeys() const
-{
- if (IsValid())
- return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
- return PythonList(PyInitialValue::Invalid);
+PythonList PythonDictionary::GetKeys() const {
+ if (IsValid())
+ return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
+ return PythonList(PyInitialValue::Invalid);
}
-PythonObject
-PythonDictionary::GetItemForKey(const PythonObject &key) const
-{
- if (IsAllocated() && key.IsValid())
- return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
- return PythonObject();
+PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
+ if (IsAllocated() && key.IsValid())
+ return PythonObject(PyRefType::Borrowed,
+ PyDict_GetItem(m_py_obj, key.get()));
+ return PythonObject();
}
-void
-PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
-{
- if (IsAllocated() && key.IsValid() && value.IsValid())
- PyDict_SetItem(m_py_obj, key.get(), value.get());
+void PythonDictionary::SetItemForKey(const PythonObject &key,
+ const PythonObject &value) {
+ if (IsAllocated() && key.IsValid() && value.IsValid())
+ PyDict_SetItem(m_py_obj, key.get(), value.get());
}
StructuredData::DictionarySP
-PythonDictionary::CreateStructuredDictionary() const
-{
- StructuredData::DictionarySP result(new StructuredData::Dictionary);
- PythonList keys(GetKeys());
- uint32_t num_keys = keys.GetSize();
- for (uint32_t i = 0; i < num_keys; ++i)
- {
- PythonObject key = keys.GetItemAtIndex(i);
- PythonObject value = GetItemForKey(key);
- StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
- result->AddItem(key.Str().GetString(), structured_value);
- }
- return result;
+PythonDictionary::CreateStructuredDictionary() const {
+ StructuredData::DictionarySP result(new StructuredData::Dictionary);
+ PythonList keys(GetKeys());
+ uint32_t num_keys = keys.GetSize();
+ for (uint32_t i = 0; i < num_keys; ++i) {
+ PythonObject key = keys.GetItemAtIndex(i);
+ PythonObject value = GetItemForKey(key);
+ StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
+ result->AddItem(key.Str().GetString(), structured_value);
+ }
+ return result;
}
-PythonModule::PythonModule() : PythonObject()
-{
-}
+PythonModule::PythonModule() : PythonObject() {}
-PythonModule::PythonModule(PyRefType type, PyObject *py_obj)
-{
- Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
+PythonModule::PythonModule(PyRefType type, PyObject *py_obj) {
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
}
-PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict)
-{
-}
+PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) {}
-PythonModule::~PythonModule()
-{
-}
+PythonModule::~PythonModule() {}
-PythonModule
-PythonModule::BuiltinsModule()
-{
+PythonModule PythonModule::BuiltinsModule() {
#if PY_MAJOR_VERSION >= 3
- return AddModule("builtins");
+ return AddModule("builtins");
#else
- return AddModule("__builtin__");
+ return AddModule("__builtin__");
#endif
}
-PythonModule
-PythonModule::MainModule()
-{
- return AddModule("__main__");
-}
+PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
-PythonModule
-PythonModule::AddModule(llvm::StringRef module)
-{
- std::string str = module.str();
- return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
+PythonModule PythonModule::AddModule(llvm::StringRef module) {
+ std::string str = module.str();
+ return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
}
-
-PythonModule
-PythonModule::ImportModule(llvm::StringRef module)
-{
- std::string str = module.str();
- return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str()));
+PythonModule PythonModule::ImportModule(llvm::StringRef module) {
+ std::string str = module.str();
+ return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str()));
}
-bool
-PythonModule::Check(PyObject *py_obj)
-{
- if (!py_obj)
- return false;
+bool PythonModule::Check(PyObject *py_obj) {
+ if (!py_obj)
+ return false;
- return PyModule_Check(py_obj);
+ return PyModule_Check(py_obj);
}
-void
-PythonModule::Reset(PyRefType type, PyObject *py_obj)
-{
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
- PythonObject result(type, py_obj);
+void PythonModule::Reset(PyRefType type, PyObject *py_obj) {
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
- if (!PythonModule::Check(py_obj))
- {
- PythonObject::Reset();
- return;
- }
+ if (!PythonModule::Check(py_obj)) {
+ PythonObject::Reset();
+ return;
+ }
- // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
- // back into the virtual implementation.
- PythonObject::Reset(PyRefType::Borrowed, result.get());
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
}
-PythonDictionary
-PythonModule::GetDictionary() const
-{
- return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
+PythonDictionary PythonModule::GetDictionary() const {
+ return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
}
-PythonCallable::PythonCallable() : PythonObject()
-{
-}
+PythonCallable::PythonCallable() : PythonObject() {}
-PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj)
-{
- Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
+PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) {
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
}
PythonCallable::PythonCallable(const PythonCallable &callable)
- : PythonObject(callable)
-{
-}
+ : PythonObject(callable) {}
-PythonCallable::~PythonCallable()
-{
-}
+PythonCallable::~PythonCallable() {}
-bool
-PythonCallable::Check(PyObject *py_obj)
-{
- if (!py_obj)
- return false;
+bool PythonCallable::Check(PyObject *py_obj) {
+ if (!py_obj)
+ return false;
- return PyCallable_Check(py_obj);
+ return PyCallable_Check(py_obj);
}
-void
-PythonCallable::Reset(PyRefType type, PyObject *py_obj)
-{
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
- PythonObject result(type, py_obj);
+void PythonCallable::Reset(PyRefType type, PyObject *py_obj) {
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
- if (!PythonCallable::Check(py_obj))
- {
- PythonObject::Reset();
- return;
- }
+ if (!PythonCallable::Check(py_obj)) {
+ PythonObject::Reset();
+ return;
+ }
- // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
- // back into the virtual implementation.
- PythonObject::Reset(PyRefType::Borrowed, result.get());
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
}
+PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
+ ArgInfo result = {0, false, false, false};
+ if (!IsValid())
+ return result;
-PythonCallable::ArgInfo
-PythonCallable::GetNumArguments() const
-{
- ArgInfo result = { 0, false, false, false };
- if (!IsValid())
- return result;
-
- PyObject *py_func_obj = m_py_obj;
- if (PyMethod_Check(py_func_obj))
- {
- py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
- PythonObject im_self = GetAttributeValue("im_self");
- if (im_self.IsValid() && !im_self.IsNone())
+ PyObject *py_func_obj = m_py_obj;
+ if (PyMethod_Check(py_func_obj)) {
+ py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
+ PythonObject im_self = GetAttributeValue("im_self");
+ if (im_self.IsValid() && !im_self.IsNone())
+ result.is_bound_method = true;
+ } else {
+ // see if this is a callable object with an __call__ method
+ if (!PyFunction_Check(py_func_obj)) {
+ PythonObject __call__ = GetAttributeValue("__call__");
+ if (__call__.IsValid()) {
+ auto __callable__ = __call__.AsType<PythonCallable>();
+ if (__callable__.IsValid()) {
+ py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
+ PythonObject im_self = GetAttributeValue("im_self");
+ if (im_self.IsValid() && !im_self.IsNone())
result.is_bound_method = true;
- }
- else
- {
- // see if this is a callable object with an __call__ method
- if (!PyFunction_Check(py_func_obj))
- {
- PythonObject __call__ = GetAttributeValue("__call__");
- if (__call__.IsValid())
- {
- auto __callable__ = __call__.AsType<PythonCallable>();
- if (__callable__.IsValid())
- {
- py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
- PythonObject im_self = GetAttributeValue("im_self");
- if (im_self.IsValid() && !im_self.IsNone())
- result.is_bound_method = true;
- }
- }
}
+ }
}
+ }
- if (!py_func_obj)
- return result;
+ if (!py_func_obj)
+ return result;
- PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj);
- if (!code)
- return result;
-
- result.count = code->co_argcount;
- result.has_varargs = !!(code->co_flags & CO_VARARGS);
- result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
+ PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
+ if (!code)
return result;
-}
-PythonObject
-PythonCallable::operator ()()
-{
- return PythonObject(PyRefType::Owned,
- PyObject_CallObject(m_py_obj, nullptr));
+ result.count = code->co_argcount;
+ result.has_varargs = !!(code->co_flags & CO_VARARGS);
+ result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
+ return result;
}
-PythonObject
-PythonCallable::operator ()(std::initializer_list<PyObject*> args)
-{
- PythonTuple arg_tuple(args);
- return PythonObject(PyRefType::Owned,
- PyObject_CallObject(m_py_obj, arg_tuple.get()));
+PythonObject PythonCallable::operator()() {
+ return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
}
-PythonObject
-PythonCallable::operator ()(std::initializer_list<PythonObject> args)
-{
- PythonTuple arg_tuple(args);
- return PythonObject(PyRefType::Owned,
- PyObject_CallObject(m_py_obj, arg_tuple.get()));
+PythonObject PythonCallable::
+operator()(std::initializer_list<PyObject *> args) {
+ PythonTuple arg_tuple(args);
+ return PythonObject(PyRefType::Owned,
+ PyObject_CallObject(m_py_obj, arg_tuple.get()));
}
-PythonFile::PythonFile()
- : PythonObject()
-{
+PythonObject PythonCallable::
+operator()(std::initializer_list<PythonObject> args) {
+ PythonTuple arg_tuple(args);
+ return PythonObject(PyRefType::Owned,
+ PyObject_CallObject(m_py_obj, arg_tuple.get()));
}
-PythonFile::PythonFile(File &file, const char *mode)
-{
- Reset(file, mode);
-}
+PythonFile::PythonFile() : PythonObject() {}
-PythonFile::PythonFile(const char *path, const char *mode)
-{
- lldb_private::File file(path, GetOptionsFromMode(mode));
- Reset(file, mode);
-}
+PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); }
-PythonFile::PythonFile(PyRefType type, PyObject *o)
-{
- Reset(type, o);
+PythonFile::PythonFile(const char *path, const char *mode) {
+ lldb_private::File file(path, GetOptionsFromMode(mode));
+ Reset(file, mode);
}
-PythonFile::~PythonFile()
-{
-}
+PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); }
-bool
-PythonFile::Check(PyObject *py_obj)
-{
+PythonFile::~PythonFile() {}
+
+bool PythonFile::Check(PyObject *py_obj) {
#if PY_MAJOR_VERSION < 3
- return PyFile_Check(py_obj);
+ return PyFile_Check(py_obj);
#else
- // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
- // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper
- // over `io.open()`, which returns some object derived from `io.IOBase`.
- // As a result, the only way to detect a file in Python 3 is to check whether
- // it inherits from `io.IOBase`. Since it is possible for non-files to also
- // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
- // attribute, which should guarantee that it is backed by the file system.
- PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
- PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get()));
- PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
-
- PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
-
- if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
- return false;
- if (!object_type.HasAttribute("fileno"))
- return false;
+ // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
+ // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper
+ // over `io.open()`, which returns some object derived from `io.IOBase`.
+ // As a result, the only way to detect a file in Python 3 is to check whether
+ // it inherits from `io.IOBase`. Since it is possible for non-files to also
+ // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
+ // attribute, which should guarantee that it is backed by the file system.
+ PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
+ PythonDictionary io_dict(PyRefType::Borrowed,
+ PyModule_GetDict(io_module.get()));
+ PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
- return true;
-#endif
-}
+ PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
-void
-PythonFile::Reset(PyRefType type, PyObject *py_obj)
-{
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
- PythonObject result(type, py_obj);
-
- if (!PythonFile::Check(py_obj))
- {
- PythonObject::Reset();
- return;
- }
+ if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
+ return false;
+ if (!object_type.HasAttribute("fileno"))
+ return false;
- // Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls back into the virtual implementation.
- PythonObject::Reset(PyRefType::Borrowed, result.get());
+ return true;
+#endif
}
-void
-PythonFile::Reset(File &file, const char *mode)
-{
- if (!file.IsValid())
- {
- Reset();
- return;
- }
+void PythonFile::Reset(PyRefType type, PyObject *py_obj) {
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonFile::Check(py_obj)) {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+void PythonFile::Reset(File &file, const char *mode) {
+ if (!file.IsValid()) {
+ Reset();
+ return;
+ }
- char *cmode = const_cast<char *>(mode);
+ char *cmode = const_cast<char *>(mode);
#if PY_MAJOR_VERSION >= 3
- Reset(PyRefType::Owned,
- PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0));
+ Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode,
+ -1, nullptr, "ignore", nullptr, 0));
#else
- // Read through the Python source, doesn't seem to modify these strings
- Reset(PyRefType::Owned,
- PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr));
+ // Read through the Python source, doesn't seem to modify these strings
+ Reset(PyRefType::Owned,
+ PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode,
+ nullptr));
#endif
}
-uint32_t
-PythonFile::GetOptionsFromMode(llvm::StringRef mode)
-{
- if (mode.empty())
- return 0;
-
- return llvm::StringSwitch<uint32_t>(mode.str().c_str())
- .Case("r", File::eOpenOptionRead)
- .Case("w", File::eOpenOptionWrite)
- .Case("a", File::eOpenOptionWrite|File::eOpenOptionAppend|File::eOpenOptionCanCreate)
- .Case("r+", File::eOpenOptionRead|File::eOpenOptionWrite)
- .Case("w+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate|File::eOpenOptionTruncate)
- .Case("a+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionAppend|File::eOpenOptionCanCreate)
- .Default(0);
-}
-
-bool
-PythonFile::GetUnderlyingFile(File &file) const
-{
- if (!IsValid())
- return false;
-
- file.Close();
- // We don't own the file descriptor returned by this function, make sure the
- // File object knows about that.
- file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
- PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
- file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString()));
- return file.IsValid();
+uint32_t PythonFile::GetOptionsFromMode(llvm::StringRef mode) {
+ if (mode.empty())
+ return 0;
+
+ return llvm::StringSwitch<uint32_t>(mode.str().c_str())
+ .Case("r", File::eOpenOptionRead)
+ .Case("w", File::eOpenOptionWrite)
+ .Case("a", File::eOpenOptionWrite | File::eOpenOptionAppend |
+ File::eOpenOptionCanCreate)
+ .Case("r+", File::eOpenOptionRead | File::eOpenOptionWrite)
+ .Case("w+", File::eOpenOptionRead | File::eOpenOptionWrite |
+ File::eOpenOptionCanCreate | File::eOpenOptionTruncate)
+ .Case("a+", File::eOpenOptionRead | File::eOpenOptionWrite |
+ File::eOpenOptionAppend | File::eOpenOptionCanCreate)
+ .Default(0);
}
+bool PythonFile::GetUnderlyingFile(File &file) const {
+ if (!IsValid())
+ return false;
+
+ file.Close();
+ // We don't own the file descriptor returned by this function, make sure the
+ // File object knows about that.
+ file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
+ PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
+ file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString()));
+ return file.IsValid();
+}
#endif
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h Tue Sep 6 15:57:50 2016
@@ -36,536 +36,434 @@ class PythonList;
class PythonDictionary;
class PythonInteger;
-class StructuredPythonObject : public StructuredData::Generic
-{
+class StructuredPythonObject : public StructuredData::Generic {
public:
- StructuredPythonObject()
- : StructuredData::Generic()
- {
- }
-
- StructuredPythonObject(void *obj)
- : StructuredData::Generic(obj)
- {
- Py_XINCREF(GetValue());
- }
-
- ~StructuredPythonObject() override
- {
- if (Py_IsInitialized())
- Py_XDECREF(GetValue());
- SetValue(nullptr);
- }
-
- bool
- IsValid() const override
- {
- return GetValue() && GetValue() != Py_None;
- }
+ StructuredPythonObject() : StructuredData::Generic() {}
- void Dump(Stream &s, bool pretty_print = true) const override;
+ StructuredPythonObject(void *obj) : StructuredData::Generic(obj) {
+ Py_XINCREF(GetValue());
+ }
+
+ ~StructuredPythonObject() override {
+ if (Py_IsInitialized())
+ Py_XDECREF(GetValue());
+ SetValue(nullptr);
+ }
+
+ bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
+
+ void Dump(Stream &s, bool pretty_print = true) const override;
private:
- DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
+ DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
+};
+
+enum class PyObjectType {
+ Unknown,
+ None,
+ Integer,
+ Dictionary,
+ List,
+ String,
+ Bytes,
+ ByteArray,
+ Module,
+ Callable,
+ Tuple,
+ File
+};
+
+enum class PyRefType {
+ Borrowed, // We are not given ownership of the incoming PyObject.
+ // We cannot safely hold it without calling Py_INCREF.
+ Owned // We have ownership of the incoming PyObject. We should
+ // not call Py_INCREF.
};
-enum class PyObjectType
-{
- Unknown,
- None,
- Integer,
- Dictionary,
- List,
- String,
- Bytes,
- ByteArray,
- Module,
- Callable,
- Tuple,
- File
-};
-
-enum class PyRefType
-{
- Borrowed, // We are not given ownership of the incoming PyObject.
- // We cannot safely hold it without calling Py_INCREF.
- Owned // We have ownership of the incoming PyObject. We should
- // not call Py_INCREF.
-};
-
-enum class PyInitialValue
-{
- Invalid,
- Empty
-};
-
-class PythonObject
-{
-public:
- PythonObject()
- : m_py_obj(nullptr)
- {
- }
-
- PythonObject(PyRefType type, PyObject *py_obj)
- : m_py_obj(nullptr)
- {
- Reset(type, py_obj);
- }
-
- PythonObject(const PythonObject &rhs)
- : m_py_obj(nullptr)
- {
- Reset(rhs);
- }
-
- virtual ~PythonObject()
- {
- Reset();
- }
-
- void
- Reset()
- {
- // Avoid calling the virtual method since it's not necessary
- // to actually validate the type of the PyObject if we're
- // just setting to null.
- if (Py_IsInitialized())
- Py_XDECREF(m_py_obj);
- m_py_obj = nullptr;
- }
-
- void
- Reset(const PythonObject &rhs)
- {
- // Avoid calling the virtual method if it's not necessary
- // to actually validate the type of the PyObject.
- if (!rhs.IsValid())
- Reset();
- else
- Reset(PyRefType::Borrowed, rhs.m_py_obj);
- }
-
- // PythonObject is implicitly convertible to PyObject *, which will call the
- // wrong overload. We want to explicitly disallow this, since a PyObject
- // *always* owns its reference. Therefore the overload which takes a
- // PyRefType doesn't make sense, and the copy constructor should be used.
- void
- Reset(PyRefType type, const PythonObject &ref) = delete;
-
- virtual void
- Reset(PyRefType type, PyObject *py_obj)
- {
- if (py_obj == m_py_obj)
- return;
-
- if (Py_IsInitialized())
- Py_XDECREF(m_py_obj);
-
- m_py_obj = py_obj;
-
- // If this is a borrowed reference, we need to convert it to
- // an owned reference by incrementing it. If it is an owned
- // reference (for example the caller allocated it with PyDict_New()
- // then we must *not* increment it.
- if (Py_IsInitialized() && type == PyRefType::Borrowed)
- Py_XINCREF(m_py_obj);
- }
-
- void
- Dump () const
- {
- if (m_py_obj)
- _PyObject_Dump (m_py_obj);
- else
- puts ("NULL");
- }
-
- void
- Dump (Stream &strm) const;
-
- PyObject*
- get() const
- {
- return m_py_obj;
- }
-
- PyObject*
- release()
- {
- PyObject *result = m_py_obj;
- m_py_obj = nullptr;
- return result;
- }
-
- PythonObject &
- operator=(const PythonObject &other)
- {
- Reset(PyRefType::Borrowed, other.get());
- return *this;
- }
-
- PyObjectType
- GetObjectType() const;
-
- PythonString
- Repr() const;
-
- PythonString
- Str() const;
-
- static PythonObject
- ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict);
-
- template<typename T>
- static T
- ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
- {
- return ResolveNameWithDictionary(name, dict).AsType<T>();
- }
-
- PythonObject
- ResolveName(llvm::StringRef name) const;
-
- template<typename T>
- T
- ResolveName(llvm::StringRef name) const
- {
- return ResolveName(name).AsType<T>();
- }
-
- bool
- HasAttribute(llvm::StringRef attribute) const;
-
- PythonObject
- GetAttributeValue(llvm::StringRef attribute) const;
-
- bool
- IsValid() const;
-
- bool
- IsAllocated() const;
-
- bool
- IsNone() const;
-
- template<typename T>
- T AsType() const
- {
- if (!T::Check(m_py_obj))
- return T();
- return T(PyRefType::Borrowed, m_py_obj);
- }
+enum class PyInitialValue { Invalid, Empty };
+
+class PythonObject {
+public:
+ PythonObject() : m_py_obj(nullptr) {}
+
+ PythonObject(PyRefType type, PyObject *py_obj) : m_py_obj(nullptr) {
+ Reset(type, py_obj);
+ }
+
+ PythonObject(const PythonObject &rhs) : m_py_obj(nullptr) { Reset(rhs); }
+
+ virtual ~PythonObject() { Reset(); }
+
+ void Reset() {
+ // Avoid calling the virtual method since it's not necessary
+ // to actually validate the type of the PyObject if we're
+ // just setting to null.
+ if (Py_IsInitialized())
+ Py_XDECREF(m_py_obj);
+ m_py_obj = nullptr;
+ }
+
+ void Reset(const PythonObject &rhs) {
+ // Avoid calling the virtual method if it's not necessary
+ // to actually validate the type of the PyObject.
+ if (!rhs.IsValid())
+ Reset();
+ else
+ Reset(PyRefType::Borrowed, rhs.m_py_obj);
+ }
+
+ // PythonObject is implicitly convertible to PyObject *, which will call the
+ // wrong overload. We want to explicitly disallow this, since a PyObject
+ // *always* owns its reference. Therefore the overload which takes a
+ // PyRefType doesn't make sense, and the copy constructor should be used.
+ void Reset(PyRefType type, const PythonObject &ref) = delete;
+
+ virtual void Reset(PyRefType type, PyObject *py_obj) {
+ if (py_obj == m_py_obj)
+ return;
+
+ if (Py_IsInitialized())
+ Py_XDECREF(m_py_obj);
+
+ m_py_obj = py_obj;
+
+ // If this is a borrowed reference, we need to convert it to
+ // an owned reference by incrementing it. If it is an owned
+ // reference (for example the caller allocated it with PyDict_New()
+ // then we must *not* increment it.
+ if (Py_IsInitialized() && type == PyRefType::Borrowed)
+ Py_XINCREF(m_py_obj);
+ }
+
+ void Dump() const {
+ if (m_py_obj)
+ _PyObject_Dump(m_py_obj);
+ else
+ puts("NULL");
+ }
+
+ void Dump(Stream &strm) const;
- StructuredData::ObjectSP
- CreateStructuredObject() const;
+ PyObject *get() const { return m_py_obj; }
+
+ PyObject *release() {
+ PyObject *result = m_py_obj;
+ m_py_obj = nullptr;
+ return result;
+ }
+
+ PythonObject &operator=(const PythonObject &other) {
+ Reset(PyRefType::Borrowed, other.get());
+ return *this;
+ }
+
+ PyObjectType GetObjectType() const;
+
+ PythonString Repr() const;
+
+ PythonString Str() const;
+
+ static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
+ const PythonDictionary &dict);
+
+ template <typename T>
+ static T ResolveNameWithDictionary(llvm::StringRef name,
+ const PythonDictionary &dict) {
+ return ResolveNameWithDictionary(name, dict).AsType<T>();
+ }
+
+ PythonObject ResolveName(llvm::StringRef name) const;
+
+ template <typename T> T ResolveName(llvm::StringRef name) const {
+ return ResolveName(name).AsType<T>();
+ }
+
+ bool HasAttribute(llvm::StringRef attribute) const;
+
+ PythonObject GetAttributeValue(llvm::StringRef attribute) const;
+
+ bool IsValid() const;
+
+ bool IsAllocated() const;
+
+ bool IsNone() const;
+
+ template <typename T> T AsType() const {
+ if (!T::Check(m_py_obj))
+ return T();
+ return T(PyRefType::Borrowed, m_py_obj);
+ }
+
+ StructuredData::ObjectSP CreateStructuredObject() const;
protected:
- PyObject* m_py_obj;
+ PyObject *m_py_obj;
};
-class PythonBytes : public PythonObject
-{
+class PythonBytes : public PythonObject {
public:
- PythonBytes();
- explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
- PythonBytes(const uint8_t *bytes, size_t length);
- PythonBytes(PyRefType type, PyObject *o);
- PythonBytes(const PythonBytes &object);
+ PythonBytes();
+ explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
+ PythonBytes(const uint8_t *bytes, size_t length);
+ PythonBytes(PyRefType type, PyObject *o);
+ PythonBytes(const PythonBytes &object);
- ~PythonBytes() override;
+ ~PythonBytes() override;
- static bool
- Check(PyObject *py_obj);
+ static bool Check(PyObject *py_obj);
- // Bring in the no-argument base class version
- using PythonObject::Reset;
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
- void
- Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(PyRefType type, PyObject *py_obj) override;
- llvm::ArrayRef<uint8_t>
- GetBytes() const;
+ llvm::ArrayRef<uint8_t> GetBytes() const;
- size_t
- GetSize() const;
+ size_t GetSize() const;
- void
- SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
+ void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
- StructuredData::StringSP
- CreateStructuredString() const;
+ StructuredData::StringSP CreateStructuredString() const;
};
-class PythonByteArray : public PythonObject
-{
+class PythonByteArray : public PythonObject {
public:
- PythonByteArray();
- explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
- PythonByteArray(const uint8_t *bytes, size_t length);
- PythonByteArray(PyRefType type, PyObject *o);
- PythonByteArray(const PythonBytes &object);
+ PythonByteArray();
+ explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
+ PythonByteArray(const uint8_t *bytes, size_t length);
+ PythonByteArray(PyRefType type, PyObject *o);
+ PythonByteArray(const PythonBytes &object);
- ~PythonByteArray() override;
+ ~PythonByteArray() override;
- static bool
- Check(PyObject *py_obj);
+ static bool Check(PyObject *py_obj);
- // Bring in the no-argument base class version
- using PythonObject::Reset;
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
- void
- Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(PyRefType type, PyObject *py_obj) override;
- llvm::ArrayRef<uint8_t>
- GetBytes() const;
+ llvm::ArrayRef<uint8_t> GetBytes() const;
- size_t
- GetSize() const;
+ size_t GetSize() const;
- void
- SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
+ void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
- StructuredData::StringSP
- CreateStructuredString() const;
+ StructuredData::StringSP CreateStructuredString() const;
};
-class PythonString : public PythonObject
-{
+class PythonString : public PythonObject {
public:
- PythonString();
- explicit PythonString(llvm::StringRef string);
- explicit PythonString(const char *string);
- PythonString(PyRefType type, PyObject *o);
- PythonString(const PythonString &object);
+ PythonString();
+ explicit PythonString(llvm::StringRef string);
+ explicit PythonString(const char *string);
+ PythonString(PyRefType type, PyObject *o);
+ PythonString(const PythonString &object);
- ~PythonString() override;
+ ~PythonString() override;
- static bool Check(PyObject *py_obj);
+ static bool Check(PyObject *py_obj);
- // Bring in the no-argument base class version
- using PythonObject::Reset;
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
- void Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(PyRefType type, PyObject *py_obj) override;
- llvm::StringRef
- GetString() const;
+ llvm::StringRef GetString() const;
- size_t
- GetSize() const;
+ size_t GetSize() const;
- void SetString(llvm::StringRef string);
+ void SetString(llvm::StringRef string);
- StructuredData::StringSP CreateStructuredString() const;
+ StructuredData::StringSP CreateStructuredString() const;
};
-class PythonInteger : public PythonObject
-{
+class PythonInteger : public PythonObject {
public:
- PythonInteger();
- explicit PythonInteger(int64_t value);
- PythonInteger(PyRefType type, PyObject *o);
- PythonInteger(const PythonInteger &object);
+ PythonInteger();
+ explicit PythonInteger(int64_t value);
+ PythonInteger(PyRefType type, PyObject *o);
+ PythonInteger(const PythonInteger &object);
- ~PythonInteger() override;
+ ~PythonInteger() override;
- static bool Check(PyObject *py_obj);
+ static bool Check(PyObject *py_obj);
- // Bring in the no-argument base class version
- using PythonObject::Reset;
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
- void Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(PyRefType type, PyObject *py_obj) override;
- int64_t GetInteger() const;
+ int64_t GetInteger() const;
- void
- SetInteger (int64_t value);
+ void SetInteger(int64_t value);
- StructuredData::IntegerSP CreateStructuredInteger() const;
+ StructuredData::IntegerSP CreateStructuredInteger() const;
};
-class PythonList : public PythonObject
-{
+class PythonList : public PythonObject {
public:
- PythonList() {}
- explicit PythonList(PyInitialValue value);
- explicit PythonList(int list_size);
- PythonList(PyRefType type, PyObject *o);
- PythonList(const PythonList &list);
+ PythonList() {}
+ explicit PythonList(PyInitialValue value);
+ explicit PythonList(int list_size);
+ PythonList(PyRefType type, PyObject *o);
+ PythonList(const PythonList &list);
- ~PythonList() override;
+ ~PythonList() override;
- static bool Check(PyObject *py_obj);
+ static bool Check(PyObject *py_obj);
- // Bring in the no-argument base class version
- using PythonObject::Reset;
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
- void Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(PyRefType type, PyObject *py_obj) override;
- uint32_t GetSize() const;
+ uint32_t GetSize() const;
- PythonObject GetItemAtIndex(uint32_t index) const;
+ PythonObject GetItemAtIndex(uint32_t index) const;
- void SetItemAtIndex(uint32_t index, const PythonObject &object);
+ void SetItemAtIndex(uint32_t index, const PythonObject &object);
- void AppendItem(const PythonObject &object);
+ void AppendItem(const PythonObject &object);
- StructuredData::ArraySP CreateStructuredArray() const;
+ StructuredData::ArraySP CreateStructuredArray() const;
};
-class PythonTuple : public PythonObject
-{
+class PythonTuple : public PythonObject {
public:
- PythonTuple() {}
- explicit PythonTuple(PyInitialValue value);
- explicit PythonTuple(int tuple_size);
- PythonTuple(PyRefType type, PyObject *o);
- PythonTuple(const PythonTuple &tuple);
- PythonTuple(std::initializer_list<PythonObject> objects);
- PythonTuple(std::initializer_list<PyObject*> objects);
+ PythonTuple() {}
+ explicit PythonTuple(PyInitialValue value);
+ explicit PythonTuple(int tuple_size);
+ PythonTuple(PyRefType type, PyObject *o);
+ PythonTuple(const PythonTuple &tuple);
+ PythonTuple(std::initializer_list<PythonObject> objects);
+ PythonTuple(std::initializer_list<PyObject *> objects);
- ~PythonTuple() override;
+ ~PythonTuple() override;
- static bool Check(PyObject *py_obj);
+ static bool Check(PyObject *py_obj);
- // Bring in the no-argument base class version
- using PythonObject::Reset;
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
- void Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(PyRefType type, PyObject *py_obj) override;
- uint32_t GetSize() const;
+ uint32_t GetSize() const;
- PythonObject GetItemAtIndex(uint32_t index) const;
+ PythonObject GetItemAtIndex(uint32_t index) const;
- void SetItemAtIndex(uint32_t index, const PythonObject &object);
+ void SetItemAtIndex(uint32_t index, const PythonObject &object);
- StructuredData::ArraySP CreateStructuredArray() const;
+ StructuredData::ArraySP CreateStructuredArray() const;
};
-class PythonDictionary : public PythonObject
-{
+class PythonDictionary : public PythonObject {
public:
- PythonDictionary() {}
- explicit PythonDictionary(PyInitialValue value);
- PythonDictionary(PyRefType type, PyObject *o);
- PythonDictionary(const PythonDictionary &dict);
+ PythonDictionary() {}
+ explicit PythonDictionary(PyInitialValue value);
+ PythonDictionary(PyRefType type, PyObject *o);
+ PythonDictionary(const PythonDictionary &dict);
- ~PythonDictionary() override;
+ ~PythonDictionary() override;
- static bool Check(PyObject *py_obj);
+ static bool Check(PyObject *py_obj);
- // Bring in the no-argument base class version
- using PythonObject::Reset;
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
- void Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(PyRefType type, PyObject *py_obj) override;
- uint32_t GetSize() const;
+ uint32_t GetSize() const;
- PythonList GetKeys() const;
+ PythonList GetKeys() const;
- PythonObject GetItemForKey(const PythonObject &key) const;
- void SetItemForKey(const PythonObject &key, const PythonObject &value);
+ PythonObject GetItemForKey(const PythonObject &key) const;
+ void SetItemForKey(const PythonObject &key, const PythonObject &value);
- StructuredData::DictionarySP CreateStructuredDictionary() const;
+ StructuredData::DictionarySP CreateStructuredDictionary() const;
};
-class PythonModule : public PythonObject
-{
- public:
- PythonModule();
- PythonModule(PyRefType type, PyObject *o);
- PythonModule(const PythonModule &dict);
+class PythonModule : public PythonObject {
+public:
+ PythonModule();
+ PythonModule(PyRefType type, PyObject *o);
+ PythonModule(const PythonModule &dict);
- ~PythonModule() override;
+ ~PythonModule() override;
- static bool Check(PyObject *py_obj);
+ static bool Check(PyObject *py_obj);
- static PythonModule
- BuiltinsModule();
+ static PythonModule BuiltinsModule();
- static PythonModule
- MainModule();
+ static PythonModule MainModule();
- static PythonModule
- AddModule(llvm::StringRef module);
+ static PythonModule AddModule(llvm::StringRef module);
- static PythonModule
- ImportModule(llvm::StringRef module);
+ static PythonModule ImportModule(llvm::StringRef module);
- // Bring in the no-argument base class version
- using PythonObject::Reset;
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
- void Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(PyRefType type, PyObject *py_obj) override;
- PythonDictionary GetDictionary() const;
+ PythonDictionary GetDictionary() const;
};
-class PythonCallable : public PythonObject
-{
+class PythonCallable : public PythonObject {
public:
- struct ArgInfo {
- size_t count;
- bool is_bound_method : 1;
- bool has_varargs : 1;
- bool has_kwargs : 1;
- };
+ struct ArgInfo {
+ size_t count;
+ bool is_bound_method : 1;
+ bool has_varargs : 1;
+ bool has_kwargs : 1;
+ };
- PythonCallable();
- PythonCallable(PyRefType type, PyObject *o);
- PythonCallable(const PythonCallable &dict);
+ PythonCallable();
+ PythonCallable(PyRefType type, PyObject *o);
+ PythonCallable(const PythonCallable &dict);
- ~PythonCallable() override;
+ ~PythonCallable() override;
- static bool
- Check(PyObject *py_obj);
+ static bool Check(PyObject *py_obj);
- // Bring in the no-argument base class version
- using PythonObject::Reset;
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
- void
- Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(PyRefType type, PyObject *py_obj) override;
- ArgInfo
- GetNumArguments() const;
+ ArgInfo GetNumArguments() const;
- PythonObject
- operator ()();
+ PythonObject operator()();
- PythonObject
- operator ()(std::initializer_list<PyObject*> args);
+ PythonObject operator()(std::initializer_list<PyObject *> args);
- PythonObject
- operator ()(std::initializer_list<PythonObject> args);
+ PythonObject operator()(std::initializer_list<PythonObject> args);
- template<typename Arg, typename... Args>
- PythonObject
- operator ()(const Arg &arg, Args... args)
- {
- return operator()({ arg, args... });
- }
+ template <typename Arg, typename... Args>
+ PythonObject operator()(const Arg &arg, Args... args) {
+ return operator()({arg, args...});
+ }
};
+class PythonFile : public PythonObject {
+public:
+ PythonFile();
+ PythonFile(File &file, const char *mode);
+ PythonFile(const char *path, const char *mode);
+ PythonFile(PyRefType type, PyObject *o);
-class PythonFile : public PythonObject
-{
- public:
- PythonFile();
- PythonFile(File &file, const char *mode);
- PythonFile(const char *path, const char *mode);
- PythonFile(PyRefType type, PyObject *o);
+ ~PythonFile() override;
- ~PythonFile() override;
+ static bool Check(PyObject *py_obj);
- static bool Check(PyObject *py_obj);
+ using PythonObject::Reset;
- using PythonObject::Reset;
+ void Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(File &file, const char *mode);
- void Reset(PyRefType type, PyObject *py_obj) override;
- void Reset(File &file, const char *mode);
+ static uint32_t GetOptionsFromMode(llvm::StringRef mode);
- static uint32_t GetOptionsFromMode(llvm::StringRef mode);
-
- bool GetUnderlyingFile(File &file) const;
+ bool GetUnderlyingFile(File &file) const;
};
} // namespace lldb_private
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp Tue Sep 6 15:57:50 2016
@@ -20,184 +20,152 @@
using namespace lldb_private;
PythonExceptionState::PythonExceptionState(bool restore_on_exit)
- : m_restore_on_exit(restore_on_exit)
-{
- Acquire(restore_on_exit);
-}
-
-PythonExceptionState::~PythonExceptionState()
-{
- if (m_restore_on_exit)
- Restore();
-}
-
-void
-PythonExceptionState::Acquire(bool restore_on_exit)
-{
- // If a state is already acquired, the user needs to decide whether they
- // want to discard or restore it. Don't allow the potential silent
- // loss of a valid state.
- assert(!IsError());
-
- if (!HasErrorOccurred())
- return;
-
- PyObject *py_type = nullptr;
- PyObject *py_value = nullptr;
- PyObject *py_traceback = nullptr;
- PyErr_Fetch(&py_type, &py_value, &py_traceback);
- // PyErr_Fetch clears the error flag.
- assert(!HasErrorOccurred());
-
- // Ownership of the objects returned by `PyErr_Fetch` is transferred
- // to us.
- m_type.Reset(PyRefType::Owned, py_type);
- m_value.Reset(PyRefType::Owned, py_value);
- m_traceback.Reset(PyRefType::Owned, py_traceback);
- m_restore_on_exit = restore_on_exit;
-}
-
-void
-PythonExceptionState::Restore()
-{
- if (m_type.IsValid())
- {
- // The documentation for PyErr_Restore says "Do not pass a null type and
- // non-null value or traceback. So only restore if type was non-null
- // to begin with. In this case we're passing ownership back to Python
- // so release them all.
- PyErr_Restore(m_type.release(), m_value.release(), m_traceback.release());
- }
+ : m_restore_on_exit(restore_on_exit) {
+ Acquire(restore_on_exit);
+}
- // After we restore, we should not hold onto the exception state. Demand that
- // it be re-acquired.
+PythonExceptionState::~PythonExceptionState() {
+ if (m_restore_on_exit)
+ Restore();
+}
+
+void PythonExceptionState::Acquire(bool restore_on_exit) {
+ // If a state is already acquired, the user needs to decide whether they
+ // want to discard or restore it. Don't allow the potential silent
+ // loss of a valid state.
+ assert(!IsError());
+
+ if (!HasErrorOccurred())
+ return;
+
+ PyObject *py_type = nullptr;
+ PyObject *py_value = nullptr;
+ PyObject *py_traceback = nullptr;
+ PyErr_Fetch(&py_type, &py_value, &py_traceback);
+ // PyErr_Fetch clears the error flag.
+ assert(!HasErrorOccurred());
+
+ // Ownership of the objects returned by `PyErr_Fetch` is transferred
+ // to us.
+ m_type.Reset(PyRefType::Owned, py_type);
+ m_value.Reset(PyRefType::Owned, py_value);
+ m_traceback.Reset(PyRefType::Owned, py_traceback);
+ m_restore_on_exit = restore_on_exit;
+}
+
+void PythonExceptionState::Restore() {
+ if (m_type.IsValid()) {
+ // The documentation for PyErr_Restore says "Do not pass a null type and
+ // non-null value or traceback. So only restore if type was non-null
+ // to begin with. In this case we're passing ownership back to Python
+ // so release them all.
+ PyErr_Restore(m_type.release(), m_value.release(), m_traceback.release());
+ }
+
+ // After we restore, we should not hold onto the exception state. Demand that
+ // it be re-acquired.
+ Discard();
+}
+
+void PythonExceptionState::Discard() {
+ m_type.Reset();
+ m_value.Reset();
+ m_traceback.Reset();
+}
+
+void PythonExceptionState::Reset() {
+ if (m_restore_on_exit)
+ Restore();
+ else
Discard();
}
-void
-PythonExceptionState::Discard()
-{
- m_type.Reset();
- m_value.Reset();
- m_traceback.Reset();
-}
-
-void
-PythonExceptionState::Reset()
-{
- if (m_restore_on_exit)
- Restore();
- else
- Discard();
-}
-
-bool
-PythonExceptionState::HasErrorOccurred()
-{
- return PyErr_Occurred();
-}
-
-bool
-PythonExceptionState::IsError() const
-{
- return m_type.IsValid() || m_value.IsValid() || m_traceback.IsValid();
-}
-
-PythonObject
-PythonExceptionState::GetType() const
-{
- return m_type;
-}
-
-PythonObject
-PythonExceptionState::GetValue() const
-{
- return m_value;
-}
-
-PythonObject
-PythonExceptionState::GetTraceback() const
-{
- return m_traceback;
-}
-
-std::string
-PythonExceptionState::Format() const
-{
- // Don't allow this function to modify the error state.
- PythonExceptionState state(true);
-
- std::string backtrace = ReadBacktrace();
- if (!IsError())
- return std::string();
-
- // It's possible that ReadPythonBacktrace generated another exception.
- // If this happens we have to clear the exception, because otherwise
- // PyObject_Str() will assert below. That's why we needed to do the
- // save / restore at the beginning of this function.
- PythonExceptionState bt_error_state(false);
-
- std::string error_string;
- llvm::raw_string_ostream error_stream(error_string);
- error_stream << m_value.Str().GetString() << "\n";
-
- if (!bt_error_state.IsError())
- {
- // If we were able to read the backtrace, just append it.
- error_stream << backtrace << "\n";
- }
- else
- {
- // Otherwise, append some information about why we were unable to
- // obtain the backtrace.
- PythonString bt_error = bt_error_state.GetValue().Str();
- error_stream << "An error occurred while retrieving the backtrace: " << bt_error.GetString() << "\n";
- }
- return error_stream.str();
-}
-
-std::string
-PythonExceptionState::ReadBacktrace() const
-{
- std::string retval("backtrace unavailable");
+bool PythonExceptionState::HasErrorOccurred() { return PyErr_Occurred(); }
+
+bool PythonExceptionState::IsError() const {
+ return m_type.IsValid() || m_value.IsValid() || m_traceback.IsValid();
+}
+
+PythonObject PythonExceptionState::GetType() const { return m_type; }
+
+PythonObject PythonExceptionState::GetValue() const { return m_value; }
+
+PythonObject PythonExceptionState::GetTraceback() const { return m_traceback; }
+
+std::string PythonExceptionState::Format() const {
+ // Don't allow this function to modify the error state.
+ PythonExceptionState state(true);
+
+ std::string backtrace = ReadBacktrace();
+ if (!IsError())
+ return std::string();
+
+ // It's possible that ReadPythonBacktrace generated another exception.
+ // If this happens we have to clear the exception, because otherwise
+ // PyObject_Str() will assert below. That's why we needed to do the
+ // save / restore at the beginning of this function.
+ PythonExceptionState bt_error_state(false);
+
+ std::string error_string;
+ llvm::raw_string_ostream error_stream(error_string);
+ error_stream << m_value.Str().GetString() << "\n";
+
+ if (!bt_error_state.IsError()) {
+ // If we were able to read the backtrace, just append it.
+ error_stream << backtrace << "\n";
+ } else {
+ // Otherwise, append some information about why we were unable to
+ // obtain the backtrace.
+ PythonString bt_error = bt_error_state.GetValue().Str();
+ error_stream << "An error occurred while retrieving the backtrace: "
+ << bt_error.GetString() << "\n";
+ }
+ return error_stream.str();
+}
- auto traceback_module = PythonModule::ImportModule("traceback");
+std::string PythonExceptionState::ReadBacktrace() const {
+ std::string retval("backtrace unavailable");
+
+ auto traceback_module = PythonModule::ImportModule("traceback");
#if PY_MAJOR_VERSION >= 3
- auto stringIO_module = PythonModule::ImportModule("io");
+ auto stringIO_module = PythonModule::ImportModule("io");
#else
- auto stringIO_module = PythonModule::ImportModule("StringIO");
+ auto stringIO_module = PythonModule::ImportModule("StringIO");
#endif
- if (!m_traceback.IsAllocated())
- return retval;
+ if (!m_traceback.IsAllocated())
+ return retval;
- if (!traceback_module.IsAllocated() || !stringIO_module.IsAllocated())
- return retval;
+ if (!traceback_module.IsAllocated() || !stringIO_module.IsAllocated())
+ return retval;
- auto stringIO_builder = stringIO_module.ResolveName<PythonCallable>("StringIO");
- if (!stringIO_builder.IsAllocated())
- return retval;
-
- auto stringIO_buffer = stringIO_builder();
- if (!stringIO_buffer.IsAllocated())
- return retval;
-
- auto printTB = traceback_module.ResolveName<PythonCallable>("print_tb");
- if (!printTB.IsAllocated())
- return retval;
-
- auto printTB_result = printTB(m_traceback.get(), Py_None, stringIO_buffer.get());
- auto stringIO_getvalue = stringIO_buffer.ResolveName<PythonCallable>("getvalue");
- if (!stringIO_getvalue.IsAllocated())
- return retval;
-
- auto printTB_string = stringIO_getvalue().AsType<PythonString>();
- if (!printTB_string.IsAllocated())
- return retval;
+ auto stringIO_builder =
+ stringIO_module.ResolveName<PythonCallable>("StringIO");
+ if (!stringIO_builder.IsAllocated())
+ return retval;
- llvm::StringRef string_data(printTB_string.GetString());
- retval.assign(string_data.data(), string_data.size());
+ auto stringIO_buffer = stringIO_builder();
+ if (!stringIO_buffer.IsAllocated())
+ return retval;
+ auto printTB = traceback_module.ResolveName<PythonCallable>("print_tb");
+ if (!printTB.IsAllocated())
return retval;
+
+ auto printTB_result =
+ printTB(m_traceback.get(), Py_None, stringIO_buffer.get());
+ auto stringIO_getvalue =
+ stringIO_buffer.ResolveName<PythonCallable>("getvalue");
+ if (!stringIO_getvalue.IsAllocated())
+ return retval;
+
+ auto printTB_string = stringIO_getvalue().AsType<PythonString>();
+ if (!printTB_string.IsAllocated())
+ return retval;
+
+ llvm::StringRef string_data(printTB_string.GetString());
+ retval.assign(string_data.data(), string_data.size());
+
+ return retval;
}
#endif
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h Tue Sep 6 15:57:50 2016
@@ -14,54 +14,41 @@
#include "PythonDataObjects.h"
-namespace lldb_private
-{
+namespace lldb_private {
-class PythonExceptionState
-{
- public:
- explicit PythonExceptionState(bool restore_on_exit);
- ~PythonExceptionState();
+class PythonExceptionState {
+public:
+ explicit PythonExceptionState(bool restore_on_exit);
+ ~PythonExceptionState();
- void
- Acquire(bool restore_on_exit);
+ void Acquire(bool restore_on_exit);
- void
- Restore();
+ void Restore();
- void
- Discard();
+ void Discard();
- void
- Reset();
+ void Reset();
- static bool
- HasErrorOccurred();
+ static bool HasErrorOccurred();
- bool
- IsError() const;
+ bool IsError() const;
- PythonObject
- GetType() const;
+ PythonObject GetType() const;
- PythonObject
- GetValue() const;
+ PythonObject GetValue() const;
- PythonObject
- GetTraceback() const;
+ PythonObject GetTraceback() const;
- std::string
- Format() const;
+ std::string Format() const;
- private:
- std::string
- ReadBacktrace() const;
+private:
+ std::string ReadBacktrace() const;
- bool m_restore_on_exit;
+ bool m_restore_on_exit;
- PythonObject m_type;
- PythonObject m_value;
- PythonObject m_traceback;
+ PythonObject m_type;
+ PythonObject m_value;
+ PythonObject m_traceback;
};
}
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp Tue Sep 6 15:57:50 2016
@@ -16,12 +16,12 @@
// LLDB Python header must be included first
#include "lldb-python.h"
-#include "ScriptInterpreterPython.h"
#include "PythonDataObjects.h"
#include "PythonExceptionState.h"
+#include "ScriptInterpreterPython.h"
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <mutex>
#include <string>
@@ -49,1574 +49,1536 @@
#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
#endif
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
using namespace lldb;
using namespace lldb_private;
static ScriptInterpreterPython::SWIGInitCallback g_swig_init_callback = nullptr;
-static ScriptInterpreterPython::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = nullptr;
-static ScriptInterpreterPython::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = nullptr;
-static ScriptInterpreterPython::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = nullptr;
-static ScriptInterpreterPython::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = nullptr;
-static ScriptInterpreterPython::SWIGPythonCreateCommandObject g_swig_create_cmd = nullptr;
-static ScriptInterpreterPython::SWIGPythonCalculateNumChildren g_swig_calc_children = nullptr;
-static ScriptInterpreterPython::SWIGPythonGetChildAtIndex g_swig_get_child_index = nullptr;
-static ScriptInterpreterPython::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = nullptr;
-static ScriptInterpreterPython::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = nullptr;
-static ScriptInterpreterPython::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr;
-static ScriptInterpreterPython::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr;
-static ScriptInterpreterPython::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr;
-static ScriptInterpreterPython::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr;
-static ScriptInterpreterPython::SWIGPythonCallCommand g_swig_call_command = nullptr;
-static ScriptInterpreterPython::SWIGPythonCallCommandObject g_swig_call_command_object = nullptr;
-static ScriptInterpreterPython::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr;
-static ScriptInterpreterPython::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr;
-static ScriptInterpreterPython::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = nullptr;
-static ScriptInterpreterPython::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr;
-static ScriptInterpreterPython::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr;
-static ScriptInterpreterPython::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr;
-static ScriptInterpreterPython::SWIGPythonScriptKeyword_Value g_swig_run_script_keyword_value = nullptr;
-static ScriptInterpreterPython::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr;
-static ScriptInterpreterPython::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr;
-static ScriptInterpreterPython::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr;
+static ScriptInterpreterPython::SWIGBreakpointCallbackFunction
+ g_swig_breakpoint_callback = nullptr;
+static ScriptInterpreterPython::SWIGWatchpointCallbackFunction
+ g_swig_watchpoint_callback = nullptr;
+static ScriptInterpreterPython::SWIGPythonTypeScriptCallbackFunction
+ g_swig_typescript_callback = nullptr;
+static ScriptInterpreterPython::SWIGPythonCreateSyntheticProvider
+ g_swig_synthetic_script = nullptr;
+static ScriptInterpreterPython::SWIGPythonCreateCommandObject
+ g_swig_create_cmd = nullptr;
+static ScriptInterpreterPython::SWIGPythonCalculateNumChildren
+ g_swig_calc_children = nullptr;
+static ScriptInterpreterPython::SWIGPythonGetChildAtIndex
+ g_swig_get_child_index = nullptr;
+static ScriptInterpreterPython::SWIGPythonGetIndexOfChildWithName
+ g_swig_get_index_child = nullptr;
+static ScriptInterpreterPython::SWIGPythonCastPyObjectToSBValue
+ g_swig_cast_to_sbvalue = nullptr;
+static ScriptInterpreterPython::SWIGPythonGetValueObjectSPFromSBValue
+ g_swig_get_valobj_sp_from_sbvalue = nullptr;
+static ScriptInterpreterPython::SWIGPythonUpdateSynthProviderInstance
+ g_swig_update_provider = nullptr;
+static ScriptInterpreterPython::SWIGPythonMightHaveChildrenSynthProviderInstance
+ g_swig_mighthavechildren_provider = nullptr;
+static ScriptInterpreterPython::SWIGPythonGetValueSynthProviderInstance
+ g_swig_getvalue_provider = nullptr;
+static ScriptInterpreterPython::SWIGPythonCallCommand g_swig_call_command =
+ nullptr;
+static ScriptInterpreterPython::SWIGPythonCallCommandObject
+ g_swig_call_command_object = nullptr;
+static ScriptInterpreterPython::SWIGPythonCallModuleInit
+ g_swig_call_module_init = nullptr;
+static ScriptInterpreterPython::SWIGPythonCreateOSPlugin
+ g_swig_create_os_plugin = nullptr;
+static ScriptInterpreterPython::SWIGPythonScriptKeyword_Process
+ g_swig_run_script_keyword_process = nullptr;
+static ScriptInterpreterPython::SWIGPythonScriptKeyword_Thread
+ g_swig_run_script_keyword_thread = nullptr;
+static ScriptInterpreterPython::SWIGPythonScriptKeyword_Target
+ g_swig_run_script_keyword_target = nullptr;
+static ScriptInterpreterPython::SWIGPythonScriptKeyword_Frame
+ g_swig_run_script_keyword_frame = nullptr;
+static ScriptInterpreterPython::SWIGPythonScriptKeyword_Value
+ g_swig_run_script_keyword_value = nullptr;
+static ScriptInterpreterPython::SWIGPython_GetDynamicSetting g_swig_plugin_get =
+ nullptr;
+static ScriptInterpreterPython::SWIGPythonCreateScriptedThreadPlan
+ g_swig_thread_plan_script = nullptr;
+static ScriptInterpreterPython::SWIGPythonCallThreadPlan
+ g_swig_call_thread_plan = nullptr;
static bool g_initialized = false;
-namespace
-{
+namespace {
// Initializing Python is not a straightforward process. We cannot control what
// external code may have done before getting to this point in LLDB, including
// potentially having already initialized Python, so we need to do a lot of work
// to ensure that the existing state of the system is maintained across our
-// initialization. We do this by using an RAII pattern where we save off initial
-// state at the beginning, and restore it at the end
-struct InitializePythonRAII
-{
+// initialization. We do this by using an RAII pattern where we save off
+// initial
+// state at the beginning, and restore it at the end
+struct InitializePythonRAII {
public:
- InitializePythonRAII() :
- m_gil_state(PyGILState_UNLOCKED),
- m_was_already_initialized(false)
- {
- // Python will muck with STDIN terminal state, so save off any current TTY
- // settings so we can restore them.
- m_stdin_tty_state.Save(STDIN_FILENO, false);
-
- InitializePythonHome();
-
- // Python < 3.2 and Python >= 3.2 reversed the ordering requirements for
- // calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you
- // call `PyEval_InitThreads` first, and >= 3.2 requires that you call it last.
+ InitializePythonRAII()
+ : m_gil_state(PyGILState_UNLOCKED), m_was_already_initialized(false) {
+ // Python will muck with STDIN terminal state, so save off any current TTY
+ // settings so we can restore them.
+ m_stdin_tty_state.Save(STDIN_FILENO, false);
+
+ InitializePythonHome();
+
+// Python < 3.2 and Python >= 3.2 reversed the ordering requirements for
+// calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you
+// call `PyEval_InitThreads` first, and >= 3.2 requires that you call it last.
#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2) || (PY_MAJOR_VERSION > 3)
- Py_InitializeEx(0);
- InitializeThreadsPrivate();
+ Py_InitializeEx(0);
+ InitializeThreadsPrivate();
#else
- InitializeThreadsPrivate();
- Py_InitializeEx(0);
+ InitializeThreadsPrivate();
+ Py_InitializeEx(0);
#endif
- }
-
- ~InitializePythonRAII()
- {
- if (m_was_already_initialized)
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
-
- if (log)
- {
- log->Printf("Releasing PyGILState. Returning to state = %slocked\n",
- m_was_already_initialized == PyGILState_UNLOCKED ? "un" : "");
- }
- PyGILState_Release(m_gil_state);
- }
- else
- {
- // We initialized the threads in this function, just unlock the GIL.
- PyEval_SaveThread();
- }
+ }
- m_stdin_tty_state.Restore();
+ ~InitializePythonRAII() {
+ if (m_was_already_initialized) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT |
+ LIBLLDB_LOG_VERBOSE));
+
+ if (log) {
+ log->Printf("Releasing PyGILState. Returning to state = %slocked\n",
+ m_was_already_initialized == PyGILState_UNLOCKED ? "un"
+ : "");
+ }
+ PyGILState_Release(m_gil_state);
+ } else {
+ // We initialized the threads in this function, just unlock the GIL.
+ PyEval_SaveThread();
}
+ m_stdin_tty_state.Restore();
+ }
+
private:
- void InitializePythonHome()
- {
+ void InitializePythonHome() {
#if defined(LLDB_PYTHON_HOME)
#if PY_MAJOR_VERSION >= 3
- size_t size = 0;
- static wchar_t *g_python_home = Py_DecodeLocale(LLDB_PYTHON_HOME, &size);
+ size_t size = 0;
+ static wchar_t *g_python_home = Py_DecodeLocale(LLDB_PYTHON_HOME, &size);
#else
- static char g_python_home[] = LLDB_PYTHON_HOME;
+ static char g_python_home[] = LLDB_PYTHON_HOME;
#endif
- Py_SetPythonHome(g_python_home);
+ Py_SetPythonHome(g_python_home);
#endif
- }
-
- void InitializeThreadsPrivate()
- {
- if (PyEval_ThreadsInitialized())
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+ }
- m_was_already_initialized = true;
- m_gil_state = PyGILState_Ensure();
- if (log)
- {
- log->Printf("Ensured PyGILState. Previous state = %slocked\n",
+ void InitializeThreadsPrivate() {
+ if (PyEval_ThreadsInitialized()) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT |
+ LIBLLDB_LOG_VERBOSE));
+
+ m_was_already_initialized = true;
+ m_gil_state = PyGILState_Ensure();
+ if (log) {
+ log->Printf("Ensured PyGILState. Previous state = %slocked\n",
m_gil_state == PyGILState_UNLOCKED ? "un" : "");
- }
- return;
- }
-
- // InitThreads acquires the GIL if it hasn't been called before.
- PyEval_InitThreads();
+ }
+ return;
}
- TerminalState m_stdin_tty_state;
- PyGILState_STATE m_gil_state;
- bool m_was_already_initialized;
+ // InitThreads acquires the GIL if it hasn't been called before.
+ PyEval_InitThreads();
+ }
+
+ TerminalState m_stdin_tty_state;
+ PyGILState_STATE m_gil_state;
+ bool m_was_already_initialized;
};
+}
+ScriptInterpreterPython::Locker::Locker(ScriptInterpreterPython *py_interpreter,
+ uint16_t on_entry, uint16_t on_leave,
+ FILE *in, FILE *out, FILE *err)
+ : ScriptInterpreterLocker(),
+ m_teardown_session((on_leave & TearDownSession) == TearDownSession),
+ m_python_interpreter(py_interpreter) {
+ DoAcquireLock();
+ if ((on_entry & InitSession) == InitSession) {
+ if (DoInitSession(on_entry, in, out, err) == false) {
+ // Don't teardown the session if we didn't init it.
+ m_teardown_session = false;
+ }
+ }
+}
+
+bool ScriptInterpreterPython::Locker::DoAcquireLock() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT |
+ LIBLLDB_LOG_VERBOSE));
+ m_GILState = PyGILState_Ensure();
+ if (log)
+ log->Printf("Ensured PyGILState. Previous state = %slocked\n",
+ m_GILState == PyGILState_UNLOCKED ? "un" : "");
+
+ // we need to save the thread state when we first start the command
+ // because we might decide to interrupt it while some action is taking
+ // place outside of Python (e.g. printing to screen, waiting for the network,
+ // ...)
+ // in that case, _PyThreadState_Current will be NULL - and we would be unable
+ // to set the asynchronous exception - not a desirable situation
+ m_python_interpreter->SetThreadState(PyThreadState_Get());
+ m_python_interpreter->IncrementLockCount();
+ return true;
+}
+
+bool ScriptInterpreterPython::Locker::DoInitSession(uint16_t on_entry_flags,
+ FILE *in, FILE *out,
+ FILE *err) {
+ if (!m_python_interpreter)
+ return false;
+ return m_python_interpreter->EnterSession(on_entry_flags, in, out, err);
}
-ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter,
- uint16_t on_entry,
- uint16_t on_leave,
- FILE *in,
- FILE *out,
- FILE *err) :
- ScriptInterpreterLocker (),
- m_teardown_session( (on_leave & TearDownSession) == TearDownSession ),
- m_python_interpreter(py_interpreter)
-{
- DoAcquireLock();
- if ((on_entry & InitSession) == InitSession)
- {
- if (DoInitSession(on_entry, in, out, err) == false)
- {
- // Don't teardown the session if we didn't init it.
- m_teardown_session = false;
- }
- }
+bool ScriptInterpreterPython::Locker::DoFreeLock() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT |
+ LIBLLDB_LOG_VERBOSE));
+ if (log)
+ log->Printf("Releasing PyGILState. Returning to state = %slocked\n",
+ m_GILState == PyGILState_UNLOCKED ? "un" : "");
+ PyGILState_Release(m_GILState);
+ m_python_interpreter->DecrementLockCount();
+ return true;
}
-bool
-ScriptInterpreterPython::Locker::DoAcquireLock()
-{
- Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
- m_GILState = PyGILState_Ensure();
- if (log)
- log->Printf("Ensured PyGILState. Previous state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : "");
+bool ScriptInterpreterPython::Locker::DoTearDownSession() {
+ if (!m_python_interpreter)
+ return false;
+ m_python_interpreter->LeaveSession();
+ return true;
+}
- // we need to save the thread state when we first start the command
- // because we might decide to interrupt it while some action is taking
- // place outside of Python (e.g. printing to screen, waiting for the network, ...)
- // in that case, _PyThreadState_Current will be NULL - and we would be unable
- // to set the asynchronous exception - not a desirable situation
- m_python_interpreter->SetThreadState(PyThreadState_Get());
- m_python_interpreter->IncrementLockCount();
- return true;
+ScriptInterpreterPython::Locker::~Locker() {
+ if (m_teardown_session)
+ DoTearDownSession();
+ DoFreeLock();
+}
+
+ScriptInterpreterPython::ScriptInterpreterPython(
+ CommandInterpreter &interpreter)
+ : ScriptInterpreter(interpreter, eScriptLanguagePython),
+ IOHandlerDelegateMultiline("DONE"), m_saved_stdin(), m_saved_stdout(),
+ m_saved_stderr(), m_main_module(), m_lldb_module(),
+ m_session_dict(PyInitialValue::Invalid),
+ m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(),
+ m_run_one_line_str_global(),
+ m_dictionary_name(
+ interpreter.GetDebugger().GetInstanceName().AsCString()),
+ m_terminal_state(), m_active_io_handler(eIOHandlerNone),
+ m_session_is_active(false), m_pty_slave_is_open(false),
+ m_valid_session(true), m_lock_count(0), m_command_thread_state(nullptr) {
+ InitializePrivate();
+
+ m_dictionary_name.append("_dict");
+ StreamString run_string;
+ run_string.Printf("%s = dict()", m_dictionary_name.c_str());
+
+ Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+ PyRun_SimpleString(run_string.GetData());
+
+ run_string.Clear();
+ run_string.Printf(
+ "run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')",
+ m_dictionary_name.c_str());
+ PyRun_SimpleString(run_string.GetData());
+
+ // Reloading modules requires a different syntax in Python 2 and Python 3.
+ // This provides
+ // a consistent syntax no matter what version of Python.
+ run_string.Clear();
+ run_string.Printf("run_one_line (%s, 'from six.moves import reload_module')",
+ m_dictionary_name.c_str());
+ PyRun_SimpleString(run_string.GetData());
+
+ // WARNING: temporary code that loads Cocoa formatters - this should be done
+ // on a per-platform basis rather than loading the whole set
+ // and letting the individual formatter classes exploit APIs to check whether
+ // they can/cannot do their task
+ run_string.Clear();
+ run_string.Printf(
+ "run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')",
+ m_dictionary_name.c_str());
+ PyRun_SimpleString(run_string.GetData());
+ run_string.Clear();
+
+ run_string.Printf("run_one_line (%s, 'import lldb.embedded_interpreter; from "
+ "lldb.embedded_interpreter import run_python_interpreter; "
+ "from lldb.embedded_interpreter import run_one_line')",
+ m_dictionary_name.c_str());
+ PyRun_SimpleString(run_string.GetData());
+ run_string.Clear();
+
+ run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64
+ "; pydoc.pager = pydoc.plainpager')",
+ m_dictionary_name.c_str(),
+ interpreter.GetDebugger().GetID());
+ PyRun_SimpleString(run_string.GetData());
+}
+
+ScriptInterpreterPython::~ScriptInterpreterPython() {
+ // the session dictionary may hold objects with complex state
+ // which means that they may need to be torn down with some level of smarts
+ // and that, in turn, requires a valid thread state
+ // force Python to procure itself such a thread state, nuke the session
+ // dictionary
+ // and then release it for others to use and proceed with the rest of the
+ // shutdown
+ auto gil_state = PyGILState_Ensure();
+ m_session_dict.Reset();
+ PyGILState_Release(gil_state);
+}
+
+void ScriptInterpreterPython::Initialize() {
+ static std::once_flag g_once_flag;
+
+ std::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ lldb::eScriptLanguagePython, CreateInstance);
+ });
}
-bool
-ScriptInterpreterPython::Locker::DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err)
-{
- if (!m_python_interpreter)
- return false;
- return m_python_interpreter->EnterSession (on_entry_flags, in, out, err);
+void ScriptInterpreterPython::Terminate() {}
+
+lldb::ScriptInterpreterSP
+ScriptInterpreterPython::CreateInstance(CommandInterpreter &interpreter) {
+ return std::make_shared<ScriptInterpreterPython>(interpreter);
}
-bool
-ScriptInterpreterPython::Locker::DoFreeLock()
-{
- Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
- if (log)
- log->Printf("Releasing PyGILState. Returning to state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : "");
- PyGILState_Release(m_GILState);
- m_python_interpreter->DecrementLockCount();
- return true;
+lldb_private::ConstString ScriptInterpreterPython::GetPluginNameStatic() {
+ static ConstString g_name("script-python");
+ return g_name;
}
-bool
-ScriptInterpreterPython::Locker::DoTearDownSession()
-{
- if (!m_python_interpreter)
- return false;
- m_python_interpreter->LeaveSession ();
- return true;
+const char *ScriptInterpreterPython::GetPluginDescriptionStatic() {
+ return "Embedded Python interpreter";
}
-ScriptInterpreterPython::Locker::~Locker()
-{
- if (m_teardown_session)
- DoTearDownSession();
- DoFreeLock();
-}
-
-ScriptInterpreterPython::ScriptInterpreterPython(CommandInterpreter &interpreter) :
- ScriptInterpreter(interpreter, eScriptLanguagePython),
- IOHandlerDelegateMultiline("DONE"),
- m_saved_stdin(),
- m_saved_stdout(),
- m_saved_stderr(),
- m_main_module(),
- m_lldb_module(),
- m_session_dict(PyInitialValue::Invalid),
- m_sys_module_dict(PyInitialValue::Invalid),
- m_run_one_line_function(),
- m_run_one_line_str_global(),
- m_dictionary_name(interpreter.GetDebugger().GetInstanceName().AsCString()),
- m_terminal_state(),
- m_active_io_handler(eIOHandlerNone),
- m_session_is_active(false),
- m_pty_slave_is_open(false),
- m_valid_session(true),
- m_lock_count(0),
- m_command_thread_state(nullptr)
-{
- InitializePrivate();
-
- m_dictionary_name.append("_dict");
- StreamString run_string;
- run_string.Printf ("%s = dict()", m_dictionary_name.c_str());
-
- Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock,
- ScriptInterpreterPython::Locker::FreeAcquiredLock);
- PyRun_SimpleString (run_string.GetData());
-
- run_string.Clear();
- run_string.Printf ("run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')", m_dictionary_name.c_str());
- PyRun_SimpleString (run_string.GetData());
-
- // Reloading modules requires a different syntax in Python 2 and Python 3. This provides
- // a consistent syntax no matter what version of Python.
- run_string.Clear();
- run_string.Printf("run_one_line (%s, 'from six.moves import reload_module')", m_dictionary_name.c_str());
- PyRun_SimpleString(run_string.GetData());
-
- // WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set
- // and letting the individual formatter classes exploit APIs to check whether they can/cannot do their task
- run_string.Clear();
- run_string.Printf ("run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str());
- PyRun_SimpleString (run_string.GetData());
- run_string.Clear();
-
- run_string.Printf ("run_one_line (%s, 'import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line')", m_dictionary_name.c_str());
- PyRun_SimpleString (run_string.GetData());
- run_string.Clear();
-
- run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64 "; pydoc.pager = pydoc.plainpager')", m_dictionary_name.c_str(),
- interpreter.GetDebugger().GetID());
- PyRun_SimpleString (run_string.GetData());
-}
-
-ScriptInterpreterPython::~ScriptInterpreterPython ()
-{
- // the session dictionary may hold objects with complex state
- // which means that they may need to be torn down with some level of smarts
- // and that, in turn, requires a valid thread state
- // force Python to procure itself such a thread state, nuke the session dictionary
- // and then release it for others to use and proceed with the rest of the shutdown
- auto gil_state = PyGILState_Ensure();
- m_session_dict.Reset();
- PyGILState_Release(gil_state);
-}
-
-void
-ScriptInterpreterPython::Initialize()
-{
- static std::once_flag g_once_flag;
+lldb_private::ConstString ScriptInterpreterPython::GetPluginName() {
+ return GetPluginNameStatic();
+}
- std::call_once(g_once_flag, []()
- {
- PluginManager::RegisterPlugin(GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- lldb::eScriptLanguagePython,
- CreateInstance);
- });
-}
-
-void
-ScriptInterpreterPython::Terminate()
-{
+uint32_t ScriptInterpreterPython::GetPluginVersion() { return 1; }
-}
-
-lldb::ScriptInterpreterSP
-ScriptInterpreterPython::CreateInstance(CommandInterpreter &interpreter)
-{
- return std::make_shared<ScriptInterpreterPython>(interpreter);
-}
-
-lldb_private::ConstString
-ScriptInterpreterPython::GetPluginNameStatic()
-{
- static ConstString g_name("script-python");
- return g_name;
-}
-
-const char *
-ScriptInterpreterPython::GetPluginDescriptionStatic()
-{
- return "Embedded Python interpreter";
-}
-
-lldb_private::ConstString
-ScriptInterpreterPython::GetPluginName()
-{
- return GetPluginNameStatic();
-}
-
-uint32_t
-ScriptInterpreterPython::GetPluginVersion()
-{
- return 1;
-}
-
-void
-ScriptInterpreterPython::IOHandlerActivated (IOHandler &io_handler)
-{
- const char *instructions = nullptr;
-
- switch (m_active_io_handler)
- {
- case eIOHandlerNone:
- break;
- case eIOHandlerBreakpoint:
- instructions = R"(Enter your Python command(s). Type 'DONE' to end.
+void ScriptInterpreterPython::IOHandlerActivated(IOHandler &io_handler) {
+ const char *instructions = nullptr;
+
+ switch (m_active_io_handler) {
+ case eIOHandlerNone:
+ break;
+ case eIOHandlerBreakpoint:
+ instructions = R"(Enter your Python command(s). Type 'DONE' to end.
def function (frame, bp_loc, internal_dict):
"""frame: the lldb.SBFrame for the location at which you stopped
bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information
internal_dict: an LLDB support object not to be used"""
)";
- break;
- case eIOHandlerWatchpoint:
- instructions = "Enter your Python command(s). Type 'DONE' to end.\n";
- break;
- }
-
- if (instructions)
- {
- StreamFileSP output_sp(io_handler.GetOutputStreamFile());
- if (output_sp)
- {
- output_sp->PutCString(instructions);
- output_sp->Flush();
- }
- }
-}
+ break;
+ case eIOHandlerWatchpoint:
+ instructions = "Enter your Python command(s). Type 'DONE' to end.\n";
+ break;
+ }
+
+ if (instructions) {
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp) {
+ output_sp->PutCString(instructions);
+ output_sp->Flush();
+ }
+ }
+}
+
+void ScriptInterpreterPython::IOHandlerInputComplete(IOHandler &io_handler,
+ std::string &data) {
+ io_handler.SetIsDone(true);
+ bool batch_mode = m_interpreter.GetBatchCommandMode();
+
+ switch (m_active_io_handler) {
+ case eIOHandlerNone:
+ break;
+ case eIOHandlerBreakpoint: {
+ std::vector<BreakpointOptions *> *bp_options_vec =
+ (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
+ for (auto bp_options : *bp_options_vec) {
+ if (!bp_options)
+ continue;
+
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(
+ new BreakpointOptions::CommandData());
+ if (data_ap.get()) {
+ data_ap->user_source.SplitIntoLines(data);
+
+ if (GenerateBreakpointCommandCallbackData(data_ap->user_source,
+ data_ap->script_source)
+ .Success()) {
+ BatonSP baton_sp(
+ new BreakpointOptions::CommandBaton(data_ap.release()));
+ bp_options->SetCallback(
+ ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
+ } else if (!batch_mode) {
+ StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+ if (error_sp) {
+ error_sp->Printf("Warning: No command attached to breakpoint.\n");
+ error_sp->Flush();
+ }
+ }
+ }
+ }
+ m_active_io_handler = eIOHandlerNone;
+ } break;
+ case eIOHandlerWatchpoint: {
+ WatchpointOptions *wp_options =
+ (WatchpointOptions *)io_handler.GetUserData();
+ std::unique_ptr<WatchpointOptions::CommandData> data_ap(
+ new WatchpointOptions::CommandData());
+ if (data_ap.get()) {
+ data_ap->user_source.SplitIntoLines(data);
+
+ if (GenerateWatchpointCommandCallbackData(data_ap->user_source,
+ data_ap->script_source)) {
+ BatonSP baton_sp(
+ new WatchpointOptions::CommandBaton(data_ap.release()));
+ wp_options->SetCallback(
+ ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp);
+ } else if (!batch_mode) {
+ StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+ if (error_sp) {
+ error_sp->Printf("Warning: No command attached to breakpoint.\n");
+ error_sp->Flush();
+ }
+ }
+ }
+ m_active_io_handler = eIOHandlerNone;
+ } break;
+ }
+}
+
+void ScriptInterpreterPython::ResetOutputFileHandle(FILE *fh) {}
+
+void ScriptInterpreterPython::SaveTerminalState(int fd) {
+ // Python mucks with the terminal state of STDIN. If we can possibly avoid
+ // this by setting the file handles up correctly prior to entering the
+ // interpreter we should. For now we save and restore the terminal state
+ // on the input file handle.
+ m_terminal_state.Save(fd, false);
+}
+
+void ScriptInterpreterPython::RestoreTerminalState() {
+ // Python mucks with the terminal state of STDIN. If we can possibly avoid
+ // this by setting the file handles up correctly prior to entering the
+ // interpreter we should. For now we save and restore the terminal state
+ // on the input file handle.
+ m_terminal_state.Restore();
+}
+
+void ScriptInterpreterPython::LeaveSession() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
+ if (log)
+ log->PutCString("ScriptInterpreterPython::LeaveSession()");
+
+ // checking that we have a valid thread state - since we use our own threading
+ // and locking
+ // in some (rare) cases during cleanup Python may end up believing we have no
+ // thread state
+ // and PyImport_AddModule will crash if that is the case - since that seems to
+ // only happen
+ // when destroying the SBDebugger, we can make do without clearing up stdout
+ // and stderr
+
+ // rdar://problem/11292882
+ // When the current thread state is NULL, PyThreadState_Get() issues a fatal
+ // error.
+ if (PyThreadState_GetDict()) {
+ PythonDictionary &sys_module_dict = GetSysModuleDictionary();
+ if (sys_module_dict.IsValid()) {
+ if (m_saved_stdin.IsValid()) {
+ sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);
+ m_saved_stdin.Reset();
+ }
+ if (m_saved_stdout.IsValid()) {
+ sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);
+ m_saved_stdout.Reset();
+ }
+ if (m_saved_stderr.IsValid()) {
+ sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);
+ m_saved_stderr.Reset();
+ }
+ }
+ }
+
+ m_session_is_active = false;
+}
+
+bool ScriptInterpreterPython::SetStdHandle(File &file, const char *py_name,
+ PythonFile &save_file,
+ const char *mode) {
+ if (file.IsValid()) {
+ // Flush the file before giving it to python to avoid interleaved output.
+ file.Flush();
-void
-ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
-{
- io_handler.SetIsDone(true);
- bool batch_mode = m_interpreter.GetBatchCommandMode();
+ PythonDictionary &sys_module_dict = GetSysModuleDictionary();
- switch (m_active_io_handler)
- {
- case eIOHandlerNone:
- break;
- case eIOHandlerBreakpoint:
- {
- std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
- for (auto bp_options : *bp_options_vec)
- {
- if (!bp_options)
- continue;
-
- std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
- if (data_ap.get())
- {
- data_ap->user_source.SplitIntoLines(data);
-
- if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source).Success())
- {
- BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
- bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
- }
- else if (!batch_mode)
- {
- StreamFileSP error_sp = io_handler.GetErrorStreamFile();
- if (error_sp)
- {
- error_sp->Printf ("Warning: No command attached to breakpoint.\n");
- error_sp->Flush();
- }
- }
- }
- }
- m_active_io_handler = eIOHandlerNone;
- }
- break;
- case eIOHandlerWatchpoint:
- {
- WatchpointOptions *wp_options = (WatchpointOptions *)io_handler.GetUserData();
- std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
- if (data_ap.get())
- {
- data_ap->user_source.SplitIntoLines(data);
-
- if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
- {
- BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
- wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp);
- }
- else if (!batch_mode)
- {
- StreamFileSP error_sp = io_handler.GetErrorStreamFile();
- if (error_sp)
- {
- error_sp->Printf ("Warning: No command attached to breakpoint.\n");
- error_sp->Flush();
- }
- }
- }
- m_active_io_handler = eIOHandlerNone;
- }
- break;
- }
-}
+ save_file = sys_module_dict.GetItemForKey(PythonString(py_name))
+ .AsType<PythonFile>();
+ PythonFile new_file(file, mode);
+ sys_module_dict.SetItemForKey(PythonString(py_name), new_file);
+ return true;
+ } else
+ save_file.Reset();
+ return false;
+}
-void
-ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh)
-{
-}
-
-void
-ScriptInterpreterPython::SaveTerminalState (int fd)
-{
- // Python mucks with the terminal state of STDIN. If we can possibly avoid
- // this by setting the file handles up correctly prior to entering the
- // interpreter we should. For now we save and restore the terminal state
- // on the input file handle.
- m_terminal_state.Save (fd, false);
-}
-
-void
-ScriptInterpreterPython::RestoreTerminalState ()
-{
- // Python mucks with the terminal state of STDIN. If we can possibly avoid
- // this by setting the file handles up correctly prior to entering the
- // interpreter we should. For now we save and restore the terminal state
- // on the input file handle.
- m_terminal_state.Restore();
-}
-
-void
-ScriptInterpreterPython::LeaveSession ()
-{
- Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+bool ScriptInterpreterPython::EnterSession(uint16_t on_entry_flags, FILE *in,
+ FILE *out, FILE *err) {
+ // If we have already entered the session, without having officially 'left'
+ // it, then there is no need to
+ // 'enter' it again.
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
+ if (m_session_is_active) {
if (log)
- log->PutCString("ScriptInterpreterPython::LeaveSession()");
-
- // checking that we have a valid thread state - since we use our own threading and locking
- // in some (rare) cases during cleanup Python may end up believing we have no thread state
- // and PyImport_AddModule will crash if that is the case - since that seems to only happen
- // when destroying the SBDebugger, we can make do without clearing up stdout and stderr
-
- // rdar://problem/11292882
- // When the current thread state is NULL, PyThreadState_Get() issues a fatal error.
- if (PyThreadState_GetDict())
- {
- PythonDictionary &sys_module_dict = GetSysModuleDictionary ();
- if (sys_module_dict.IsValid())
- {
- if (m_saved_stdin.IsValid())
- {
- sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);
- m_saved_stdin.Reset ();
- }
- if (m_saved_stdout.IsValid())
- {
- sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);
- m_saved_stdout.Reset ();
- }
- if (m_saved_stderr.IsValid())
- {
- sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);
- m_saved_stderr.Reset ();
- }
- }
- }
+ log->Printf(
+ "ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16
+ ") session is already active, returning without doing anything",
+ on_entry_flags);
+ return false;
+ }
- m_session_is_active = false;
+ if (log)
+ log->Printf(
+ "ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ")",
+ on_entry_flags);
+
+ m_session_is_active = true;
+
+ StreamString run_string;
+
+ if (on_entry_flags & Locker::InitGlobals) {
+ run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
+ m_dictionary_name.c_str(),
+ GetCommandInterpreter().GetDebugger().GetID());
+ run_string.Printf(
+ "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
+ GetCommandInterpreter().GetDebugger().GetID());
+ run_string.PutCString("; lldb.target = lldb.debugger.GetSelectedTarget()");
+ run_string.PutCString("; lldb.process = lldb.target.GetProcess()");
+ run_string.PutCString("; lldb.thread = lldb.process.GetSelectedThread ()");
+ run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()");
+ run_string.PutCString("')");
+ } else {
+ // If we aren't initing the globals, we should still always set the debugger
+ // (since that is always unique.)
+ run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
+ m_dictionary_name.c_str(),
+ GetCommandInterpreter().GetDebugger().GetID());
+ run_string.Printf(
+ "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
+ GetCommandInterpreter().GetDebugger().GetID());
+ run_string.PutCString("')");
+ }
+
+ PyRun_SimpleString(run_string.GetData());
+ run_string.Clear();
+
+ PythonDictionary &sys_module_dict = GetSysModuleDictionary();
+ if (sys_module_dict.IsValid()) {
+ File in_file(in, false);
+ File out_file(out, false);
+ File err_file(err, false);
+
+ lldb::StreamFileSP in_sp;
+ lldb::StreamFileSP out_sp;
+ lldb::StreamFileSP err_sp;
+ if (!in_file.IsValid() || !out_file.IsValid() || !err_file.IsValid())
+ m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid(in_sp, out_sp,
+ err_sp);
+
+ if (on_entry_flags & Locker::NoSTDIN) {
+ m_saved_stdin.Reset();
+ } else {
+ if (!SetStdHandle(in_file, "stdin", m_saved_stdin, "r")) {
+ if (in_sp)
+ SetStdHandle(in_sp->GetFile(), "stdin", m_saved_stdin, "r");
+ }
+ }
+
+ if (!SetStdHandle(out_file, "stdout", m_saved_stdout, "w")) {
+ if (out_sp)
+ SetStdHandle(out_sp->GetFile(), "stdout", m_saved_stdout, "w");
+ }
+
+ if (!SetStdHandle(err_file, "stderr", m_saved_stderr, "w")) {
+ if (err_sp)
+ SetStdHandle(err_sp->GetFile(), "stderr", m_saved_stderr, "w");
+ }
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ return true;
+}
+
+PythonObject &ScriptInterpreterPython::GetMainModule() {
+ if (!m_main_module.IsValid())
+ m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__"));
+ return m_main_module;
}
-bool
-ScriptInterpreterPython::SetStdHandle(File &file, const char *py_name, PythonFile &save_file, const char *mode)
-{
- if (file.IsValid())
- {
- // Flush the file before giving it to python to avoid interleaved output.
- file.Flush();
+PythonDictionary &ScriptInterpreterPython::GetSessionDictionary() {
+ if (m_session_dict.IsValid())
+ return m_session_dict;
- PythonDictionary &sys_module_dict = GetSysModuleDictionary();
+ PythonObject &main_module = GetMainModule();
+ if (!main_module.IsValid())
+ return m_session_dict;
- save_file = sys_module_dict.GetItemForKey(PythonString(py_name)).AsType<PythonFile>();
+ PythonDictionary main_dict(PyRefType::Borrowed,
+ PyModule_GetDict(main_module.get()));
+ if (!main_dict.IsValid())
+ return m_session_dict;
- PythonFile new_file(file, mode);
- sys_module_dict.SetItemForKey(PythonString(py_name), new_file);
- return true;
- }
- else
- save_file.Reset();
- return false;
+ PythonObject item = main_dict.GetItemForKey(PythonString(m_dictionary_name));
+ m_session_dict.Reset(PyRefType::Borrowed, item.get());
+ return m_session_dict;
}
-bool
-ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags,
- FILE *in,
- FILE *out,
- FILE *err)
-{
- // If we have already entered the session, without having officially 'left' it, then there is no need to
- // 'enter' it again.
- Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
- if (m_session_is_active)
- {
- if (log)
- log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ") session is already active, returning without doing anything", on_entry_flags);
- return false;
- }
-
- if (log)
- log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ")", on_entry_flags);
-
-
- m_session_is_active = true;
-
- StreamString run_string;
-
- if (on_entry_flags & Locker::InitGlobals)
- {
- run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
- run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID());
- run_string.PutCString ("; lldb.target = lldb.debugger.GetSelectedTarget()");
- run_string.PutCString ("; lldb.process = lldb.target.GetProcess()");
- run_string.PutCString ("; lldb.thread = lldb.process.GetSelectedThread ()");
- run_string.PutCString ("; lldb.frame = lldb.thread.GetSelectedFrame ()");
- run_string.PutCString ("')");
- }
- else
- {
- // If we aren't initing the globals, we should still always set the debugger (since that is always unique.)
- run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
- run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID());
- run_string.PutCString ("')");
- }
-
- PyRun_SimpleString (run_string.GetData());
- run_string.Clear();
-
- PythonDictionary &sys_module_dict = GetSysModuleDictionary ();
- if (sys_module_dict.IsValid())
- {
- File in_file(in, false);
- File out_file(out, false);
- File err_file(err, false);
-
- lldb::StreamFileSP in_sp;
- lldb::StreamFileSP out_sp;
- lldb::StreamFileSP err_sp;
- if (!in_file.IsValid() || !out_file.IsValid() || !err_file.IsValid())
- m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp);
-
-
- if (on_entry_flags & Locker::NoSTDIN)
- {
- m_saved_stdin.Reset();
- }
- else
- {
- if (!SetStdHandle(in_file, "stdin", m_saved_stdin, "r"))
- {
- if (in_sp)
- SetStdHandle(in_sp->GetFile(), "stdin", m_saved_stdin, "r");
- }
- }
-
- if (!SetStdHandle(out_file, "stdout", m_saved_stdout, "w"))
- {
- if (out_sp)
- SetStdHandle(out_sp->GetFile(), "stdout", m_saved_stdout, "w");
- }
-
- if (!SetStdHandle(err_file, "stderr", m_saved_stderr, "w"))
- {
- if (err_sp)
- SetStdHandle(err_sp->GetFile(), "stderr", m_saved_stderr, "w");
- }
- }
+PythonDictionary &ScriptInterpreterPython::GetSysModuleDictionary() {
+ if (m_sys_module_dict.IsValid())
+ return m_sys_module_dict;
- if (PyErr_Occurred())
- PyErr_Clear ();
-
- return true;
+ PythonObject sys_module(PyRefType::Borrowed, PyImport_AddModule("sys"));
+ if (sys_module.IsValid())
+ m_sys_module_dict.Reset(PyRefType::Borrowed,
+ PyModule_GetDict(sys_module.get()));
+ return m_sys_module_dict;
}
-PythonObject &
-ScriptInterpreterPython::GetMainModule()
-{
- if (!m_main_module.IsValid())
- m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__"));
- return m_main_module;
-}
-
-PythonDictionary &
-ScriptInterpreterPython::GetSessionDictionary ()
-{
- if (m_session_dict.IsValid())
- return m_session_dict;
-
- PythonObject &main_module = GetMainModule();
- if (!main_module.IsValid())
- return m_session_dict;
-
- PythonDictionary main_dict(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
- if (!main_dict.IsValid())
- return m_session_dict;
+static std::string GenerateUniqueName(const char *base_name_wanted,
+ uint32_t &functions_counter,
+ const void *name_token = nullptr) {
+ StreamString sstr;
- PythonObject item = main_dict.GetItemForKey(PythonString(m_dictionary_name));
- m_session_dict.Reset(PyRefType::Borrowed, item.get());
- return m_session_dict;
-}
+ if (!base_name_wanted)
+ return std::string();
-PythonDictionary &
-ScriptInterpreterPython::GetSysModuleDictionary ()
-{
- if (m_sys_module_dict.IsValid())
- return m_sys_module_dict;
-
- PythonObject sys_module(PyRefType::Borrowed, PyImport_AddModule("sys"));
- if (sys_module.IsValid())
- m_sys_module_dict.Reset(PyRefType::Borrowed, PyModule_GetDict(sys_module.get()));
- return m_sys_module_dict;
-}
+ if (!name_token)
+ sstr.Printf("%s_%d", base_name_wanted, functions_counter++);
+ else
+ sstr.Printf("%s_%p", base_name_wanted, name_token);
-static std::string
-GenerateUniqueName (const char* base_name_wanted,
- uint32_t& functions_counter,
- const void* name_token = nullptr)
-{
- StreamString sstr;
-
- if (!base_name_wanted)
- return std::string();
-
- if (!name_token)
- sstr.Printf ("%s_%d", base_name_wanted, functions_counter++);
- else
- sstr.Printf ("%s_%p", base_name_wanted, name_token);
-
- return sstr.GetString();
-}
-
-bool
-ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects ()
-{
- if (m_run_one_line_function.IsValid())
- return true;
+ return sstr.GetString();
+}
- PythonObject module(PyRefType::Borrowed, PyImport_AddModule ("lldb.embedded_interpreter"));
- if (!module.IsValid())
- return false;
+bool ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects() {
+ if (m_run_one_line_function.IsValid())
+ return true;
- PythonDictionary module_dict(PyRefType::Borrowed, PyModule_GetDict(module.get()));
- if (!module_dict.IsValid())
- return false;
+ PythonObject module(PyRefType::Borrowed,
+ PyImport_AddModule("lldb.embedded_interpreter"));
+ if (!module.IsValid())
+ return false;
- m_run_one_line_function = module_dict.GetItemForKey(PythonString("run_one_line"));
- m_run_one_line_str_global = module_dict.GetItemForKey(PythonString("g_run_one_line_str"));
- return m_run_one_line_function.IsValid();
-}
+ PythonDictionary module_dict(PyRefType::Borrowed,
+ PyModule_GetDict(module.get()));
+ if (!module_dict.IsValid())
+ return false;
-static void
-ReadThreadBytesReceived(void *baton, const void *src, size_t src_len)
-{
- if (src && src_len)
- {
- Stream *strm = (Stream *)baton;
- strm->Write(src, src_len);
- strm->Flush();
- }
-}
+ m_run_one_line_function =
+ module_dict.GetItemForKey(PythonString("run_one_line"));
+ m_run_one_line_str_global =
+ module_dict.GetItemForKey(PythonString("g_run_one_line_str"));
+ return m_run_one_line_function.IsValid();
+}
+
+static void ReadThreadBytesReceived(void *baton, const void *src,
+ size_t src_len) {
+ if (src && src_len) {
+ Stream *strm = (Stream *)baton;
+ strm->Write(src, src_len);
+ strm->Flush();
+ }
+}
+
+bool ScriptInterpreterPython::ExecuteOneLine(
+ const char *command, CommandReturnObject *result,
+ const ExecuteScriptOptions &options) {
+ if (!m_valid_session)
+ return false;
-bool
-ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options)
-{
- if (!m_valid_session)
- return false;
-
- if (command && command[0])
- {
- // We want to call run_one_line, passing in the dictionary and the command string. We cannot do this through
- // PyRun_SimpleString here because the command string may contain escaped characters, and putting it inside
- // another string to pass to PyRun_SimpleString messes up the escaping. So we use the following more complicated
- // method to pass the command string directly down to Python.
- Debugger &debugger = m_interpreter.GetDebugger();
-
- StreamFileSP input_file_sp;
- StreamFileSP output_file_sp;
- StreamFileSP error_file_sp;
- Communication output_comm ("lldb.ScriptInterpreterPython.ExecuteOneLine.comm");
- bool join_read_thread = false;
- if (options.GetEnableIO())
- {
- if (result)
- {
- input_file_sp = debugger.GetInputFile();
- // Set output to a temporary file so we can forward the results on to the result object
-
- Pipe pipe;
- Error pipe_result = pipe.CreateNew(false);
- if (pipe_result.Success())
- {
+ if (command && command[0]) {
+ // We want to call run_one_line, passing in the dictionary and the command
+ // string. We cannot do this through
+ // PyRun_SimpleString here because the command string may contain escaped
+ // characters, and putting it inside
+ // another string to pass to PyRun_SimpleString messes up the escaping. So
+ // we use the following more complicated
+ // method to pass the command string directly down to Python.
+ Debugger &debugger = m_interpreter.GetDebugger();
+
+ StreamFileSP input_file_sp;
+ StreamFileSP output_file_sp;
+ StreamFileSP error_file_sp;
+ Communication output_comm(
+ "lldb.ScriptInterpreterPython.ExecuteOneLine.comm");
+ bool join_read_thread = false;
+ if (options.GetEnableIO()) {
+ if (result) {
+ input_file_sp = debugger.GetInputFile();
+ // Set output to a temporary file so we can forward the results on to
+ // the result object
+
+ Pipe pipe;
+ Error pipe_result = pipe.CreateNew(false);
+ if (pipe_result.Success()) {
#if defined(_WIN32)
- lldb::file_t read_file = pipe.GetReadNativeHandle();
- pipe.ReleaseReadFileDescriptor();
- std::unique_ptr<ConnectionGenericFile> conn_ap(new ConnectionGenericFile(read_file, true));
+ lldb::file_t read_file = pipe.GetReadNativeHandle();
+ pipe.ReleaseReadFileDescriptor();
+ std::unique_ptr<ConnectionGenericFile> conn_ap(
+ new ConnectionGenericFile(read_file, true));
#else
- std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true));
+ std::unique_ptr<ConnectionFileDescriptor> conn_ap(
+ new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(),
+ true));
#endif
- if (conn_ap->IsConnected())
- {
- output_comm.SetConnection(conn_ap.release());
- output_comm.SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived, &result->GetOutputStream());
- output_comm.StartReadThread();
- join_read_thread = true;
- FILE *outfile_handle = fdopen (pipe.ReleaseWriteFileDescriptor(), "w");
- output_file_sp.reset(new StreamFile(outfile_handle, true));
- error_file_sp = output_file_sp;
- if (outfile_handle)
- ::setbuf (outfile_handle, nullptr);
-
- result->SetImmediateOutputFile(debugger.GetOutputFile()->GetFile().GetStream());
- result->SetImmediateErrorFile(debugger.GetErrorFile()->GetFile().GetStream());
- }
- }
- }
- if (!input_file_sp || !output_file_sp || !error_file_sp)
- debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp, error_file_sp);
- }
- else
- {
- input_file_sp.reset (new StreamFile ());
- input_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionRead);
- output_file_sp.reset (new StreamFile ());
- output_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionWrite);
+ if (conn_ap->IsConnected()) {
+ output_comm.SetConnection(conn_ap.release());
+ output_comm.SetReadThreadBytesReceivedCallback(
+ ReadThreadBytesReceived, &result->GetOutputStream());
+ output_comm.StartReadThread();
+ join_read_thread = true;
+ FILE *outfile_handle =
+ fdopen(pipe.ReleaseWriteFileDescriptor(), "w");
+ output_file_sp.reset(new StreamFile(outfile_handle, true));
error_file_sp = output_file_sp;
- }
+ if (outfile_handle)
+ ::setbuf(outfile_handle, nullptr);
- FILE *in_file = input_file_sp->GetFile().GetStream();
- FILE *out_file = output_file_sp->GetFile().GetStream();
- FILE *err_file = error_file_sp->GetFile().GetStream();
- bool success = false;
- {
- // WARNING! It's imperative that this RAII scope be as tight as possible. In particular, the
- // scope must end *before* we try to join the read thread. The reason for this is that a
- // pre-requisite for joining the read thread is that we close the write handle (to break the
- // pipe and cause it to wake up and exit). But acquiring the GIL as below will redirect Python's
- // stdio to use this same handle. If we close the handle while Python is still using it, bad
- // things will happen.
- Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock |
- ScriptInterpreterPython::Locker::InitSession |
- (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) |
- ((result && result->GetInteractive()) ? 0: Locker::NoSTDIN),
- ScriptInterpreterPython::Locker::FreeAcquiredLock |
- ScriptInterpreterPython::Locker::TearDownSession,
- in_file,
- out_file,
- err_file);
-
- // Find the correct script interpreter dictionary in the main module.
- PythonDictionary &session_dict = GetSessionDictionary ();
- if (session_dict.IsValid())
- {
- if (GetEmbeddedInterpreterModuleObjects ())
- {
- if (PyCallable_Check(m_run_one_line_function.get()))
- {
- PythonObject pargs(PyRefType::Owned, Py_BuildValue("(Os)", session_dict.get(), command));
- if (pargs.IsValid())
- {
- PythonObject return_value(PyRefType::Owned,
- PyObject_CallObject(m_run_one_line_function.get(), pargs.get()));
- if (return_value.IsValid())
- success = true;
- else if (options.GetMaskoutErrors() && PyErr_Occurred ())
- {
- PyErr_Print();
- PyErr_Clear();
- }
- }
- }
- }
+ result->SetImmediateOutputFile(
+ debugger.GetOutputFile()->GetFile().GetStream());
+ result->SetImmediateErrorFile(
+ debugger.GetErrorFile()->GetFile().GetStream());
+ }
+ }
+ }
+ if (!input_file_sp || !output_file_sp || !error_file_sp)
+ debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp,
+ error_file_sp);
+ } else {
+ input_file_sp.reset(new StreamFile());
+ input_file_sp->GetFile().Open(FileSystem::DEV_NULL,
+ File::eOpenOptionRead);
+ output_file_sp.reset(new StreamFile());
+ output_file_sp->GetFile().Open(FileSystem::DEV_NULL,
+ File::eOpenOptionWrite);
+ error_file_sp = output_file_sp;
+ }
+
+ FILE *in_file = input_file_sp->GetFile().GetStream();
+ FILE *out_file = output_file_sp->GetFile().GetStream();
+ FILE *err_file = error_file_sp->GetFile().GetStream();
+ bool success = false;
+ {
+ // WARNING! It's imperative that this RAII scope be as tight as possible.
+ // In particular, the
+ // scope must end *before* we try to join the read thread. The reason for
+ // this is that a
+ // pre-requisite for joining the read thread is that we close the write
+ // handle (to break the
+ // pipe and cause it to wake up and exit). But acquiring the GIL as below
+ // will redirect Python's
+ // stdio to use this same handle. If we close the handle while Python is
+ // still using it, bad
+ // things will happen.
+ Locker locker(
+ this,
+ ScriptInterpreterPython::Locker::AcquireLock |
+ ScriptInterpreterPython::Locker::InitSession |
+ (options.GetSetLLDBGlobals()
+ ? ScriptInterpreterPython::Locker::InitGlobals
+ : 0) |
+ ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN),
+ ScriptInterpreterPython::Locker::FreeAcquiredLock |
+ ScriptInterpreterPython::Locker::TearDownSession,
+ in_file, out_file, err_file);
+
+ // Find the correct script interpreter dictionary in the main module.
+ PythonDictionary &session_dict = GetSessionDictionary();
+ if (session_dict.IsValid()) {
+ if (GetEmbeddedInterpreterModuleObjects()) {
+ if (PyCallable_Check(m_run_one_line_function.get())) {
+ PythonObject pargs(
+ PyRefType::Owned,
+ Py_BuildValue("(Os)", session_dict.get(), command));
+ if (pargs.IsValid()) {
+ PythonObject return_value(
+ PyRefType::Owned,
+ PyObject_CallObject(m_run_one_line_function.get(),
+ pargs.get()));
+ if (return_value.IsValid())
+ success = true;
+ else if (options.GetMaskoutErrors() && PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
}
-
- // Flush our output and error file handles
- ::fflush (out_file);
- if (out_file != err_file)
- ::fflush (err_file);
- }
-
- if (join_read_thread)
- {
- // Close the write end of the pipe since we are done with our
- // one line script. This should cause the read thread that
- // output_comm is using to exit
- output_file_sp->GetFile().Close();
- // The close above should cause this thread to exit when it gets
- // to the end of file, so let it get all its data
- output_comm.JoinReadThread();
- // Now we can close the read end of the pipe
- output_comm.Disconnect();
+ }
}
-
-
- if (success)
- return true;
-
- // The one-liner failed. Append the error message.
- if (result)
- result->AppendErrorWithFormat ("python failed attempting to evaluate '%s'\n", command);
- return false;
+ }
+
+ // Flush our output and error file handles
+ ::fflush(out_file);
+ if (out_file != err_file)
+ ::fflush(err_file);
+ }
+
+ if (join_read_thread) {
+ // Close the write end of the pipe since we are done with our
+ // one line script. This should cause the read thread that
+ // output_comm is using to exit
+ output_file_sp->GetFile().Close();
+ // The close above should cause this thread to exit when it gets
+ // to the end of file, so let it get all its data
+ output_comm.JoinReadThread();
+ // Now we can close the read end of the pipe
+ output_comm.Disconnect();
}
+ if (success)
+ return true;
+
+ // The one-liner failed. Append the error message.
if (result)
- result->AppendError ("empty command passed to python\n");
+ result->AppendErrorWithFormat(
+ "python failed attempting to evaluate '%s'\n", command);
return false;
-}
+ }
+ if (result)
+ result->AppendError("empty command passed to python\n");
+ return false;
+}
-class IOHandlerPythonInterpreter :
- public IOHandler
-{
+class IOHandlerPythonInterpreter : public IOHandler {
public:
-
- IOHandlerPythonInterpreter (Debugger &debugger,
- ScriptInterpreterPython *python) :
- IOHandler (debugger, IOHandler::Type::PythonInterpreter),
- m_python(python)
- {
-
- }
-
- ~IOHandlerPythonInterpreter() override
- {
-
- }
-
- ConstString
- GetControlSequence (char ch) override
- {
- if (ch == 'd')
- return ConstString("quit()\n");
- return ConstString();
- }
-
- void
- Run () override
- {
- if (m_python)
- {
- int stdin_fd = GetInputFD();
- if (stdin_fd >= 0)
- {
- Terminal terminal(stdin_fd);
- TerminalState terminal_state;
- const bool is_a_tty = terminal.IsATerminal();
-
- if (is_a_tty)
- {
- terminal_state.Save (stdin_fd, false);
- terminal.SetCanonical(false);
- terminal.SetEcho(true);
- }
-
- ScriptInterpreterPython::Locker locker (m_python,
- ScriptInterpreterPython::Locker::AcquireLock |
- ScriptInterpreterPython::Locker::InitSession |
- ScriptInterpreterPython::Locker::InitGlobals,
- ScriptInterpreterPython::Locker::FreeAcquiredLock |
- ScriptInterpreterPython::Locker::TearDownSession);
-
- // The following call drops into the embedded interpreter loop and stays there until the
- // user chooses to exit from the Python interpreter.
- // This embedded interpreter will, as any Python code that performs I/O, unlock the GIL before
- // a system call that can hang, and lock it when the syscall has returned.
-
- // We need to surround the call to the embedded interpreter with calls to PyGILState_Ensure and
- // PyGILState_Release (using the Locker above). This is because Python has a global lock which must be held whenever we want
- // to touch any Python objects. Otherwise, if the user calls Python code, the interpreter state will be off,
- // and things could hang (it's happened before).
-
- StreamString run_string;
- run_string.Printf ("run_python_interpreter (%s)", m_python->GetDictionaryName ());
- PyRun_SimpleString (run_string.GetData());
-
- if (is_a_tty)
- terminal_state.Restore();
- }
+ IOHandlerPythonInterpreter(Debugger &debugger,
+ ScriptInterpreterPython *python)
+ : IOHandler(debugger, IOHandler::Type::PythonInterpreter),
+ m_python(python) {}
+
+ ~IOHandlerPythonInterpreter() override {}
+
+ ConstString GetControlSequence(char ch) override {
+ if (ch == 'd')
+ return ConstString("quit()\n");
+ return ConstString();
+ }
+
+ void Run() override {
+ if (m_python) {
+ int stdin_fd = GetInputFD();
+ if (stdin_fd >= 0) {
+ Terminal terminal(stdin_fd);
+ TerminalState terminal_state;
+ const bool is_a_tty = terminal.IsATerminal();
+
+ if (is_a_tty) {
+ terminal_state.Save(stdin_fd, false);
+ terminal.SetCanonical(false);
+ terminal.SetEcho(true);
}
- SetIsDone(true);
- }
- void
- Cancel () override
- {
-
+ ScriptInterpreterPython::Locker locker(
+ m_python, ScriptInterpreterPython::Locker::AcquireLock |
+ ScriptInterpreterPython::Locker::InitSession |
+ ScriptInterpreterPython::Locker::InitGlobals,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock |
+ ScriptInterpreterPython::Locker::TearDownSession);
+
+ // The following call drops into the embedded interpreter loop and stays
+ // there until the
+ // user chooses to exit from the Python interpreter.
+ // This embedded interpreter will, as any Python code that performs I/O,
+ // unlock the GIL before
+ // a system call that can hang, and lock it when the syscall has
+ // returned.
+
+ // We need to surround the call to the embedded interpreter with calls
+ // to PyGILState_Ensure and
+ // PyGILState_Release (using the Locker above). This is because Python
+ // has a global lock which must be held whenever we want
+ // to touch any Python objects. Otherwise, if the user calls Python
+ // code, the interpreter state will be off,
+ // and things could hang (it's happened before).
+
+ StreamString run_string;
+ run_string.Printf("run_python_interpreter (%s)",
+ m_python->GetDictionaryName());
+ PyRun_SimpleString(run_string.GetData());
+
+ if (is_a_tty)
+ terminal_state.Restore();
+ }
}
+ SetIsDone(true);
+ }
- bool
- Interrupt () override
- {
- return m_python->Interrupt();
- }
-
- void
- GotEOF() override
- {
-
- }
-protected:
- ScriptInterpreterPython *m_python;
-};
+ void Cancel() override {}
+ bool Interrupt() override { return m_python->Interrupt(); }
-void
-ScriptInterpreterPython::ExecuteInterpreterLoop ()
-{
- Timer scoped_timer (LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
-
- Debugger &debugger = GetCommandInterpreter().GetDebugger();
-
- // At the moment, the only time the debugger does not have an input file handle is when this is called
- // directly from Python, in which case it is both dangerous and unnecessary (not to mention confusing) to
- // try to embed a running interpreter loop inside the already running Python interpreter loop, so we won't
- // do it.
+ void GotEOF() override {}
- if (!debugger.GetInputFile()->GetFile().IsValid())
- return;
+protected:
+ ScriptInterpreterPython *m_python;
+};
- IOHandlerSP io_handler_sp (new IOHandlerPythonInterpreter (debugger, this));
- if (io_handler_sp)
- {
- debugger.PushIOHandler(io_handler_sp);
- }
-}
+void ScriptInterpreterPython::ExecuteInterpreterLoop() {
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
-bool
-ScriptInterpreterPython::Interrupt()
-{
- Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+ Debugger &debugger = GetCommandInterpreter().GetDebugger();
- if (IsExecutingPython())
- {
- PyThreadState *state = PyThreadState_GET();
- if (!state)
- state = GetThreadState();
- if (state)
- {
- long tid = state->thread_id;
- PyThreadState_Swap(state);
- int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
- if (log)
- log->Printf("ScriptInterpreterPython::Interrupt() sending PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid, num_threads);
- return true;
- }
- }
- if (log)
- log->Printf("ScriptInterpreterPython::Interrupt() python code not running, can't interrupt");
- return false;
+ // At the moment, the only time the debugger does not have an input file
+ // handle is when this is called
+ // directly from Python, in which case it is both dangerous and unnecessary
+ // (not to mention confusing) to
+ // try to embed a running interpreter loop inside the already running Python
+ // interpreter loop, so we won't
+ // do it.
-}
-bool
-ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
- ScriptInterpreter::ScriptReturnType return_type,
- void *ret_value,
- const ExecuteScriptOptions &options)
-{
-
- Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN,
- ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
-
- PythonObject py_return;
- PythonObject &main_module = GetMainModule();
- PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
- PythonObject py_error;
- bool ret_success = false;
- int success;
-
- PythonDictionary locals = GetSessionDictionary ();
-
- if (!locals.IsValid())
- {
- locals.Reset(PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
- }
-
- if (!locals.IsValid())
- locals = globals;
-
- py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
- if (py_error.IsValid())
- PyErr_Clear();
-
- if (in_string != nullptr)
- {
- { // scope for PythonInputReaderManager
- //PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
- py_return.Reset(PyRefType::Owned, PyRun_String(in_string, Py_eval_input, globals.get(), locals.get()));
- if (!py_return.IsValid())
- {
- py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
- if (py_error.IsValid())
- PyErr_Clear();
+ if (!debugger.GetInputFile()->GetFile().IsValid())
+ return;
- py_return.Reset(PyRefType::Owned, PyRun_String(in_string, Py_single_input, globals.get(), locals.get()));
- }
- }
+ IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this));
+ if (io_handler_sp) {
+ debugger.PushIOHandler(io_handler_sp);
+ }
+}
+
+bool ScriptInterpreterPython::Interrupt() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
+
+ if (IsExecutingPython()) {
+ PyThreadState *state = PyThreadState_GET();
+ if (!state)
+ state = GetThreadState();
+ if (state) {
+ long tid = state->thread_id;
+ PyThreadState_Swap(state);
+ int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
+ if (log)
+ log->Printf("ScriptInterpreterPython::Interrupt() sending "
+ "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...",
+ tid, num_threads);
+ return true;
+ }
+ }
+ if (log)
+ log->Printf("ScriptInterpreterPython::Interrupt() python code not running, "
+ "can't interrupt");
+ return false;
+}
+bool ScriptInterpreterPython::ExecuteOneLineWithReturn(
+ const char *in_string, ScriptInterpreter::ScriptReturnType return_type,
+ void *ret_value, const ExecuteScriptOptions &options) {
- if (py_return.IsValid())
- {
- switch (return_type)
- {
- case eScriptReturnTypeCharPtr: // "char *"
- {
- const char format[3] = "s#";
- success = PyArg_Parse (py_return.get(), format, (char **) ret_value);
- break;
- }
- case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == Py_None
- {
- const char format[3] = "z";
- success = PyArg_Parse (py_return.get(), format, (char **) ret_value);
- break;
- }
- case eScriptReturnTypeBool:
- {
- const char format[2] = "b";
- success = PyArg_Parse (py_return.get(), format, (bool *) ret_value);
- break;
- }
- case eScriptReturnTypeShortInt:
- {
- const char format[2] = "h";
- success = PyArg_Parse (py_return.get(), format, (short *) ret_value);
- break;
- }
- case eScriptReturnTypeShortIntUnsigned:
- {
- const char format[2] = "H";
- success = PyArg_Parse (py_return.get(), format, (unsigned short *) ret_value);
- break;
- }
- case eScriptReturnTypeInt:
- {
- const char format[2] = "i";
- success = PyArg_Parse (py_return.get(), format, (int *) ret_value);
- break;
- }
- case eScriptReturnTypeIntUnsigned:
- {
- const char format[2] = "I";
- success = PyArg_Parse (py_return.get(), format, (unsigned int *) ret_value);
- break;
- }
- case eScriptReturnTypeLongInt:
- {
- const char format[2] = "l";
- success = PyArg_Parse (py_return.get(), format, (long *) ret_value);
- break;
- }
- case eScriptReturnTypeLongIntUnsigned:
- {
- const char format[2] = "k";
- success = PyArg_Parse (py_return.get(), format, (unsigned long *) ret_value);
- break;
- }
- case eScriptReturnTypeLongLong:
- {
- const char format[2] = "L";
- success = PyArg_Parse (py_return.get(), format, (long long *) ret_value);
- break;
- }
- case eScriptReturnTypeLongLongUnsigned:
- {
- const char format[2] = "K";
- success = PyArg_Parse (py_return.get(), format, (unsigned long long *) ret_value);
- break;
- }
- case eScriptReturnTypeFloat:
- {
- const char format[2] = "f";
- success = PyArg_Parse (py_return.get(), format, (float *) ret_value);
- break;
- }
- case eScriptReturnTypeDouble:
- {
- const char format[2] = "d";
- success = PyArg_Parse (py_return.get(), format, (double *) ret_value);
- break;
- }
- case eScriptReturnTypeChar:
- {
- const char format[2] = "c";
- success = PyArg_Parse (py_return.get(), format, (char *) ret_value);
- break;
- }
- case eScriptReturnTypeOpaqueObject:
- {
- success = true;
- PyObject *saved_value = py_return.get();
- Py_XINCREF(saved_value);
- *((PyObject **)ret_value) = saved_value;
- break;
- }
- }
+ Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock |
+ ScriptInterpreterPython::Locker::InitSession |
+ (options.GetSetLLDBGlobals()
+ ? ScriptInterpreterPython::Locker::InitGlobals
+ : 0) |
+ Locker::NoSTDIN,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock |
+ ScriptInterpreterPython::Locker::TearDownSession);
+
+ PythonObject py_return;
+ PythonObject &main_module = GetMainModule();
+ PythonDictionary globals(PyRefType::Borrowed,
+ PyModule_GetDict(main_module.get()));
+ PythonObject py_error;
+ bool ret_success = false;
+ int success;
+
+ PythonDictionary locals = GetSessionDictionary();
+
+ if (!locals.IsValid()) {
+ locals.Reset(
+ PyRefType::Owned,
+ PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
+ }
+
+ if (!locals.IsValid())
+ locals = globals;
+
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
+ PyErr_Clear();
+
+ if (in_string != nullptr) {
+ { // scope for PythonInputReaderManager
+ // PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
+ py_return.Reset(
+ PyRefType::Owned,
+ PyRun_String(in_string, Py_eval_input, globals.get(), locals.get()));
+ if (!py_return.IsValid()) {
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
+ PyErr_Clear();
+
+ py_return.Reset(PyRefType::Owned,
+ PyRun_String(in_string, Py_single_input, globals.get(),
+ locals.get()));
+ }
+ }
+
+ if (py_return.IsValid()) {
+ switch (return_type) {
+ case eScriptReturnTypeCharPtr: // "char *"
+ {
+ const char format[3] = "s#";
+ success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
+ break;
+ }
+ case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
+ // Py_None
+ {
+ const char format[3] = "z";
+ success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
+ break;
+ }
+ case eScriptReturnTypeBool: {
+ const char format[2] = "b";
+ success = PyArg_Parse(py_return.get(), format, (bool *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeShortInt: {
+ const char format[2] = "h";
+ success = PyArg_Parse(py_return.get(), format, (short *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeShortIntUnsigned: {
+ const char format[2] = "H";
+ success =
+ PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeInt: {
+ const char format[2] = "i";
+ success = PyArg_Parse(py_return.get(), format, (int *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeIntUnsigned: {
+ const char format[2] = "I";
+ success =
+ PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongInt: {
+ const char format[2] = "l";
+ success = PyArg_Parse(py_return.get(), format, (long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongIntUnsigned: {
+ const char format[2] = "k";
+ success =
+ PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongLong: {
+ const char format[2] = "L";
+ success = PyArg_Parse(py_return.get(), format, (long long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongLongUnsigned: {
+ const char format[2] = "K";
+ success = PyArg_Parse(py_return.get(), format,
+ (unsigned long long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeFloat: {
+ const char format[2] = "f";
+ success = PyArg_Parse(py_return.get(), format, (float *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeDouble: {
+ const char format[2] = "d";
+ success = PyArg_Parse(py_return.get(), format, (double *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeChar: {
+ const char format[2] = "c";
+ success = PyArg_Parse(py_return.get(), format, (char *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeOpaqueObject: {
+ success = true;
+ PyObject *saved_value = py_return.get();
+ Py_XINCREF(saved_value);
+ *((PyObject **)ret_value) = saved_value;
+ break;
+ }
+ }
- if (success)
- ret_success = true;
- else
- ret_success = false;
- }
+ if (success)
+ ret_success = true;
+ else
+ ret_success = false;
}
+ }
- py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
- if (py_error.IsValid())
- {
- ret_success = false;
- if (options.GetMaskoutErrors())
- {
- if (PyErr_GivenExceptionMatches (py_error.get(), PyExc_SyntaxError))
- PyErr_Print ();
- PyErr_Clear();
- }
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid()) {
+ ret_success = false;
+ if (options.GetMaskoutErrors()) {
+ if (PyErr_GivenExceptionMatches(py_error.get(), PyExc_SyntaxError))
+ PyErr_Print();
+ PyErr_Clear();
}
+ }
- return ret_success;
+ return ret_success;
}
-Error
-ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const ExecuteScriptOptions &options)
-{
- Error error;
-
- Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN,
- ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
-
- PythonObject return_value;
- PythonObject &main_module = GetMainModule();
- PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
- PythonObject py_error;
-
- PythonDictionary locals = GetSessionDictionary();
-
- if (!locals.IsValid())
- locals.Reset(PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
-
- if (!locals.IsValid())
- locals = globals;
-
- py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
- if (py_error.IsValid())
- PyErr_Clear();
-
- if (in_string != nullptr)
- {
- PythonObject code_object;
- code_object.Reset(PyRefType::Owned, Py_CompileString(in_string, "temp.py", Py_file_input));
+Error ScriptInterpreterPython::ExecuteMultipleLines(
+ const char *in_string, const ExecuteScriptOptions &options) {
+ Error error;
- if (code_object.IsValid())
- {
- // In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it takes
- // a PyObject. They are convertible (hence the function PyCode_Check(PyObject*), so
- // we have to do the cast for Python 2.x
+ Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock |
+ ScriptInterpreterPython::Locker::InitSession |
+ (options.GetSetLLDBGlobals()
+ ? ScriptInterpreterPython::Locker::InitGlobals
+ : 0) |
+ Locker::NoSTDIN,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock |
+ ScriptInterpreterPython::Locker::TearDownSession);
+
+ PythonObject return_value;
+ PythonObject &main_module = GetMainModule();
+ PythonDictionary globals(PyRefType::Borrowed,
+ PyModule_GetDict(main_module.get()));
+ PythonObject py_error;
+
+ PythonDictionary locals = GetSessionDictionary();
+
+ if (!locals.IsValid())
+ locals.Reset(
+ PyRefType::Owned,
+ PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
+
+ if (!locals.IsValid())
+ locals = globals;
+
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
+ PyErr_Clear();
+
+ if (in_string != nullptr) {
+ PythonObject code_object;
+ code_object.Reset(PyRefType::Owned,
+ Py_CompileString(in_string, "temp.py", Py_file_input));
+
+ if (code_object.IsValid()) {
+// In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it
+// takes
+// a PyObject. They are convertible (hence the function
+// PyCode_Check(PyObject*), so
+// we have to do the cast for Python 2.x
#if PY_MAJOR_VERSION >= 3
- PyObject *py_code_obj = code_object.get();
+ PyObject *py_code_obj = code_object.get();
#else
- PyCodeObject *py_code_obj = reinterpret_cast<PyCodeObject *>(code_object.get());
+ PyCodeObject *py_code_obj =
+ reinterpret_cast<PyCodeObject *>(code_object.get());
#endif
- return_value.Reset(PyRefType::Owned, PyEval_EvalCode(py_code_obj, globals.get(), locals.get()));
- }
+ return_value.Reset(
+ PyRefType::Owned,
+ PyEval_EvalCode(py_code_obj, globals.get(), locals.get()));
}
+ }
- PythonExceptionState exception_state(!options.GetMaskoutErrors());
- if (exception_state.IsError())
- error.SetErrorString(exception_state.Format().c_str());
+ PythonExceptionState exception_state(!options.GetMaskoutErrors());
+ if (exception_state.IsError())
+ error.SetErrorString(exception_state.Format().c_str());
- return error;
+ return error;
+}
+
+void ScriptInterpreterPython::CollectDataForBreakpointCommandCallback(
+ std::vector<BreakpointOptions *> &bp_options_vec,
+ CommandReturnObject &result) {
+ m_active_io_handler = eIOHandlerBreakpoint;
+ m_interpreter.GetPythonCommandsFromIOHandler(" ", *this, true,
+ &bp_options_vec);
}
+void ScriptInterpreterPython::CollectDataForWatchpointCommandCallback(
+ WatchpointOptions *wp_options, CommandReturnObject &result) {
+ m_active_io_handler = eIOHandlerWatchpoint;
+ m_interpreter.GetPythonCommandsFromIOHandler(" ", *this, true, wp_options);
+}
-void
-ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
- CommandReturnObject &result)
-{
- m_active_io_handler = eIOHandlerBreakpoint;
- m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, &bp_options_vec);
-}
-
-void
-ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
- CommandReturnObject &result)
-{
- m_active_io_handler = eIOHandlerWatchpoint;
- m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, wp_options);
-}
-
-void
-ScriptInterpreterPython::SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options,
- const char *function_name)
-{
- // For now just cons up a oneliner that calls the provided function.
- std::string oneliner("return ");
- oneliner += function_name;
- oneliner += "(frame, bp_loc, internal_dict)";
- m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
- oneliner.c_str());
+void ScriptInterpreterPython::SetBreakpointCommandCallbackFunction(
+ BreakpointOptions *bp_options, const char *function_name) {
+ // For now just cons up a oneliner that calls the provided function.
+ std::string oneliner("return ");
+ oneliner += function_name;
+ oneliner += "(frame, bp_loc, internal_dict)";
+ m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback(
+ bp_options, oneliner.c_str());
}
// Set a Python one-liner as the callback for the breakpoint.
-Error
-ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
- const char *command_body_text)
-{
- std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
-
- // Split the command_body_text into lines, and pass that to GenerateBreakpointCommandCallbackData. That will
- // wrap the body in an auto-generated function, and return the function name in script_source. That is what
- // the callback will actually invoke.
-
- data_ap->user_source.SplitIntoLines(command_body_text);
- Error error = GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source);
- if (error.Success())
- {
- BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
- bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
- return error;
- }
- else
- return error;
+Error ScriptInterpreterPython::SetBreakpointCommandCallback(
+ BreakpointOptions *bp_options, const char *command_body_text) {
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(
+ new BreakpointOptions::CommandData());
+
+ // Split the command_body_text into lines, and pass that to
+ // GenerateBreakpointCommandCallbackData. That will
+ // wrap the body in an auto-generated function, and return the function name
+ // in script_source. That is what
+ // the callback will actually invoke.
+
+ data_ap->user_source.SplitIntoLines(command_body_text);
+ Error error = GenerateBreakpointCommandCallbackData(data_ap->user_source,
+ data_ap->script_source);
+ if (error.Success()) {
+ BatonSP baton_sp(new BreakpointOptions::CommandBaton(data_ap.release()));
+ bp_options->SetCallback(ScriptInterpreterPython::BreakpointCallbackFunction,
+ baton_sp);
+ return error;
+ } else
+ return error;
}
// Set a Python one-liner as the callback for the watchpoint.
-void
-ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_options,
- const char *oneliner)
-{
- std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
-
- // It's necessary to set both user_source and script_source to the oneliner.
- // The former is used to generate callback description (as in watchpoint command list)
- // while the latter is used for Python to interpret during the actual callback.
+void ScriptInterpreterPython::SetWatchpointCommandCallback(
+ WatchpointOptions *wp_options, const char *oneliner) {
+ std::unique_ptr<WatchpointOptions::CommandData> data_ap(
+ new WatchpointOptions::CommandData());
+
+ // It's necessary to set both user_source and script_source to the oneliner.
+ // The former is used to generate callback description (as in watchpoint
+ // command list)
+ // while the latter is used for Python to interpret during the actual
+ // callback.
+
+ data_ap->user_source.AppendString(oneliner);
+ data_ap->script_source.assign(oneliner);
+
+ if (GenerateWatchpointCommandCallbackData(data_ap->user_source,
+ data_ap->script_source)) {
+ BatonSP baton_sp(new WatchpointOptions::CommandBaton(data_ap.release()));
+ wp_options->SetCallback(ScriptInterpreterPython::WatchpointCallbackFunction,
+ baton_sp);
+ }
+
+ return;
+}
+
+Error ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter(
+ StringList &function_def) {
+ // Convert StringList to one long, newline delimited, const char *.
+ std::string function_def_string(function_def.CopyList());
+
+ Error error = ExecuteMultipleLines(
+ function_def_string.c_str(),
+ ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
+ return error;
+}
+
+Error ScriptInterpreterPython::GenerateFunction(const char *signature,
+ const StringList &input) {
+ Error error;
+ int num_lines = input.GetSize();
+ if (num_lines == 0) {
+ error.SetErrorString("No input data.");
+ return error;
+ }
- data_ap->user_source.AppendString (oneliner);
- data_ap->script_source.assign (oneliner);
+ if (!signature || *signature == 0) {
+ error.SetErrorString("No output function name.");
+ return error;
+ }
- if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
- {
- BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
- wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp);
- }
-
- return;
-}
+ StreamString sstr;
+ StringList auto_generated_function;
+ auto_generated_function.AppendString(signature);
+ auto_generated_function.AppendString(
+ " global_dict = globals()"); // Grab the global dictionary
+ auto_generated_function.AppendString(
+ " new_keys = internal_dict.keys()"); // Make a list of keys in the
+ // session dict
+ auto_generated_function.AppendString(
+ " old_keys = global_dict.keys()"); // Save list of keys in global dict
+ auto_generated_function.AppendString(
+ " global_dict.update (internal_dict)"); // Add the session dictionary
+ // to the
+ // global dictionary.
+
+ // Wrap everything up inside the function, increasing the indentation.
+
+ auto_generated_function.AppendString(" if True:");
+ for (int i = 0; i < num_lines; ++i) {
+ sstr.Clear();
+ sstr.Printf(" %s", input.GetStringAtIndex(i));
+ auto_generated_function.AppendString(sstr.GetData());
+ }
+ auto_generated_function.AppendString(
+ " for key in new_keys:"); // Iterate over all the keys from session
+ // dict
+ auto_generated_function.AppendString(
+ " internal_dict[key] = global_dict[key]"); // Update session dict
+ // values
+ auto_generated_function.AppendString(
+ " if key not in old_keys:"); // If key was not originally in
+ // global dict
+ auto_generated_function.AppendString(
+ " del global_dict[key]"); // ...then remove key/value from
+ // global dict
+
+ // Verify that the results are valid Python.
+
+ error = ExportFunctionDefinitionToInterpreter(auto_generated_function);
+
+ return error;
+}
+
+bool ScriptInterpreterPython::GenerateTypeScriptFunction(
+ StringList &user_input, std::string &output, const void *name_token) {
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines();
+ StreamString sstr;
-Error
-ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def)
-{
- // Convert StringList to one long, newline delimited, const char *.
- std::string function_def_string(function_def.CopyList());
+ // Check to see if we have any data; if not, just return.
+ if (user_input.GetSize() == 0)
+ return false;
- Error error = ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
- return error;
-}
+ // Take what the user wrote, wrap it all up inside one big auto-generated
+ // Python function, passing in the
+ // ValueObject as parameter to the function.
+
+ std::string auto_generated_function_name(
+ GenerateUniqueName("lldb_autogen_python_type_print_func",
+ num_created_functions, name_token));
+ sstr.Printf("def %s (valobj, internal_dict):",
+ auto_generated_function_name.c_str());
-Error
-ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input)
-{
- Error error;
- int num_lines = input.GetSize ();
- if (num_lines == 0)
- {
- error.SetErrorString ("No input data.");
- return error;
- }
-
- if (!signature || *signature == 0)
- {
- error.SetErrorString("No output function name.");
- return error;
- }
+ if (!GenerateFunction(sstr.GetData(), user_input).Success())
+ return false;
- StreamString sstr;
- StringList auto_generated_function;
- auto_generated_function.AppendString (signature);
- auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary
- auto_generated_function.AppendString (" new_keys = internal_dict.keys()"); // Make a list of keys in the session dict
- auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict
- auto_generated_function.AppendString (" global_dict.update (internal_dict)"); // Add the session dictionary to the
- // global dictionary.
-
- // Wrap everything up inside the function, increasing the indentation.
-
- auto_generated_function.AppendString(" if True:");
- for (int i = 0; i < num_lines; ++i)
- {
- sstr.Clear ();
- sstr.Printf (" %s", input.GetStringAtIndex (i));
- auto_generated_function.AppendString (sstr.GetData());
- }
- auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict
- auto_generated_function.AppendString (" internal_dict[key] = global_dict[key]"); // Update session dict values
- auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict
- auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict
-
- // Verify that the results are valid Python.
-
- error = ExportFunctionDefinitionToInterpreter (auto_generated_function);
-
- return error;
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return true;
}
-bool
-ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std::string& output, const void* name_token)
-{
- static uint32_t num_created_functions = 0;
- user_input.RemoveBlankLines ();
- StreamString sstr;
-
- // Check to see if we have any data; if not, just return.
- if (user_input.GetSize() == 0)
- return false;
-
- // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the
- // ValueObject as parameter to the function.
-
- std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_type_print_func", num_created_functions, name_token));
- sstr.Printf ("def %s (valobj, internal_dict):", auto_generated_function_name.c_str());
-
- if (!GenerateFunction(sstr.GetData(), user_input).Success())
- return false;
+bool ScriptInterpreterPython::GenerateScriptAliasFunction(
+ StringList &user_input, std::string &output) {
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines();
+ StreamString sstr;
- // Store the name of the auto-generated function to be called.
- output.assign(auto_generated_function_name);
- return true;
-}
+ // Check to see if we have any data; if not, just return.
+ if (user_input.GetSize() == 0)
+ return false;
-bool
-ScriptInterpreterPython::GenerateScriptAliasFunction (StringList &user_input, std::string &output)
-{
- static uint32_t num_created_functions = 0;
- user_input.RemoveBlankLines ();
- StreamString sstr;
-
- // Check to see if we have any data; if not, just return.
- if (user_input.GetSize() == 0)
- return false;
-
- std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_cmd_alias_func", num_created_functions));
+ std::string auto_generated_function_name(GenerateUniqueName(
+ "lldb_autogen_python_cmd_alias_func", num_created_functions));
- sstr.Printf ("def %s (debugger, args, result, internal_dict):", auto_generated_function_name.c_str());
-
- if (!GenerateFunction(sstr.GetData(),user_input).Success())
- return false;
-
- // Store the name of the auto-generated function to be called.
- output.assign(auto_generated_function_name);
- return true;
-}
+ sstr.Printf("def %s (debugger, args, result, internal_dict):",
+ auto_generated_function_name.c_str());
+ if (!GenerateFunction(sstr.GetData(), user_input).Success())
+ return false;
-bool
-ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::string &output, const void* name_token)
-{
- static uint32_t num_created_classes = 0;
- user_input.RemoveBlankLines ();
- int num_lines = user_input.GetSize ();
- StreamString sstr;
-
- // Check to see if we have any data; if not, just return.
- if (user_input.GetSize() == 0)
- return false;
-
- // Wrap all user input into a Python class
-
- std::string auto_generated_class_name(GenerateUniqueName("lldb_autogen_python_type_synth_class",num_created_classes,name_token));
-
- StringList auto_generated_class;
-
- // Create the function name & definition string.
-
- sstr.Printf ("class %s:", auto_generated_class_name.c_str());
- auto_generated_class.AppendString (sstr.GetData());
-
- // Wrap everything up inside the class, increasing the indentation.
- // we don't need to play any fancy indentation tricks here because there is no
- // surrounding code whose indentation we need to honor
- for (int i = 0; i < num_lines; ++i)
- {
- sstr.Clear ();
- sstr.Printf (" %s", user_input.GetStringAtIndex (i));
- auto_generated_class.AppendString (sstr.GetData());
- }
-
-
- // Verify that the results are valid Python.
- // (even though the method is ExportFunctionDefinitionToInterpreter, a class will actually be exported)
- // (TODO: rename that method to ExportDefinitionToInterpreter)
- if (!ExportFunctionDefinitionToInterpreter (auto_generated_class).Success())
- return false;
-
- // Store the name of the auto-generated class
-
- output.assign(auto_generated_class_name);
- return true;
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return true;
}
-StructuredData::GenericSP
-ScriptInterpreterPython::OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp)
-{
- if (class_name == nullptr || class_name[0] == '\0')
- return StructuredData::GenericSP();
+bool ScriptInterpreterPython::GenerateTypeSynthClass(StringList &user_input,
+ std::string &output,
+ const void *name_token) {
+ static uint32_t num_created_classes = 0;
+ user_input.RemoveBlankLines();
+ int num_lines = user_input.GetSize();
+ StreamString sstr;
- if (!process_sp)
- return StructuredData::GenericSP();
+ // Check to see if we have any data; if not, just return.
+ if (user_input.GetSize() == 0)
+ return false;
- void* ret_val;
-
- {
- Locker py_lock (this,
- Locker::AcquireLock | Locker::NoSTDIN,
- Locker::FreeLock);
- ret_val = g_swig_create_os_plugin (class_name,
- m_dictionary_name.c_str(),
- process_sp);
- }
+ // Wrap all user input into a Python class
+
+ std::string auto_generated_class_name(GenerateUniqueName(
+ "lldb_autogen_python_type_synth_class", num_created_classes, name_token));
+
+ StringList auto_generated_class;
+
+ // Create the function name & definition string.
+
+ sstr.Printf("class %s:", auto_generated_class_name.c_str());
+ auto_generated_class.AppendString(sstr.GetData());
+
+ // Wrap everything up inside the class, increasing the indentation.
+ // we don't need to play any fancy indentation tricks here because there is no
+ // surrounding code whose indentation we need to honor
+ for (int i = 0; i < num_lines; ++i) {
+ sstr.Clear();
+ sstr.Printf(" %s", user_input.GetStringAtIndex(i));
+ auto_generated_class.AppendString(sstr.GetData());
+ }
+
+ // Verify that the results are valid Python.
+ // (even though the method is ExportFunctionDefinitionToInterpreter, a class
+ // will actually be exported)
+ // (TODO: rename that method to ExportDefinitionToInterpreter)
+ if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success())
+ return false;
+
+ // Store the name of the auto-generated class
- return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
+ output.assign(auto_generated_class_name);
+ return true;
}
-StructuredData::DictionarySP
-ScriptInterpreterPython::OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp)
-{
- Locker py_lock(this,
- Locker::AcquireLock | Locker::NoSTDIN,
+StructuredData::GenericSP ScriptInterpreterPython::OSPlugin_CreatePluginObject(
+ const char *class_name, lldb::ProcessSP process_sp) {
+ if (class_name == nullptr || class_name[0] == '\0')
+ return StructuredData::GenericSP();
+
+ if (!process_sp)
+ return StructuredData::GenericSP();
+
+ void *ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,
Locker::FreeLock);
-
- static char callee_name[] = "get_register_info";
-
- if (!os_plugin_object_sp)
- return StructuredData::DictionarySP();
-
- StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
- if (!generic)
- return nullptr;
+ ret_val = g_swig_create_os_plugin(class_name, m_dictionary_name.c_str(),
+ process_sp);
+ }
- PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
+ return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
+}
- if (!implementor.IsAllocated())
- return StructuredData::DictionarySP();
+StructuredData::DictionarySP ScriptInterpreterPython::OSPlugin_RegisterInfo(
+ StructuredData::ObjectSP os_plugin_object_sp) {
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
- PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+ static char callee_name[] = "get_register_info";
- if (PyErr_Occurred())
- PyErr_Clear();
+ if (!os_plugin_object_sp)
+ return StructuredData::DictionarySP();
- if (!pmeth.IsAllocated())
- return StructuredData::DictionarySP();
-
- if (PyCallable_Check(pmeth.get()) == 0)
- {
- if (PyErr_Occurred())
- PyErr_Clear();
-
- return StructuredData::DictionarySP();
- }
-
- if (PyErr_Occurred())
- PyErr_Clear();
-
- // right now we know this function exists and is callable..
- PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+ StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
+ if (!generic)
+ return nullptr;
+
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)generic->GetValue());
+
+ if (!implementor.IsAllocated())
+ return StructuredData::DictionarySP();
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
- // if it fails, print the error but otherwise go on
+ if (!pmeth.IsAllocated())
+ return StructuredData::DictionarySP();
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
if (PyErr_Occurred())
- {
- PyErr_Print();
- PyErr_Clear();
- }
- if (py_return.get())
- {
- PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
- return result_dict.CreateStructuredDictionary();
- }
+ PyErr_Clear();
+
return StructuredData::DictionarySP();
-}
+ }
-StructuredData::ArraySP
-ScriptInterpreterPython::OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp)
-{
- Locker py_lock (this,
- Locker::AcquireLock | Locker::NoSTDIN,
- Locker::FreeLock);
+ if (PyErr_Occurred())
+ PyErr_Clear();
- static char callee_name[] = "get_thread_info";
+ // right now we know this function exists and is callable..
+ PythonObject py_return(
+ PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ if (py_return.get()) {
+ PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
+ return result_dict.CreateStructuredDictionary();
+ }
+ return StructuredData::DictionarySP();
+}
+
+StructuredData::ArraySP ScriptInterpreterPython::OSPlugin_ThreadsInfo(
+ StructuredData::ObjectSP os_plugin_object_sp) {
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
- if (!os_plugin_object_sp)
- return StructuredData::ArraySP();
+ static char callee_name[] = "get_thread_info";
- StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
- if (!generic)
- return nullptr;
+ if (!os_plugin_object_sp)
+ return StructuredData::ArraySP();
- PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
+ StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
+ if (!generic)
+ return nullptr;
- if (!implementor.IsAllocated())
- return StructuredData::ArraySP();
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)generic->GetValue());
- PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+ if (!implementor.IsAllocated())
+ return StructuredData::ArraySP();
- if (PyErr_Occurred())
- PyErr_Clear();
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
- if (!pmeth.IsAllocated())
- return StructuredData::ArraySP();
-
- if (PyCallable_Check(pmeth.get()) == 0)
- {
- if (PyErr_Occurred())
- PyErr_Clear();
-
- return StructuredData::ArraySP();
- }
-
- if (PyErr_Occurred())
- PyErr_Clear();
-
- // right now we know this function exists and is callable..
- PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+ if (PyErr_Occurred())
+ PyErr_Clear();
- // if it fails, print the error but otherwise go on
+ if (!pmeth.IsAllocated())
+ return StructuredData::ArraySP();
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
if (PyErr_Occurred())
- {
- PyErr_Print();
- PyErr_Clear();
- }
+ PyErr_Clear();
- if (py_return.get())
- {
- PythonList result_list(PyRefType::Borrowed, py_return.get());
- return result_list.CreateStructuredArray();
- }
return StructuredData::ArraySP();
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(
+ PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (py_return.get()) {
+ PythonList result_list(PyRefType::Borrowed, py_return.get());
+ return result_list.CreateStructuredArray();
+ }
+ return StructuredData::ArraySP();
}
// GetPythonValueFormatString provides a system independent type safe way to
@@ -1625,1637 +1587,1599 @@ ScriptInterpreterPython::OSPlugin_Thread
// as the underlying typedef for uint* types, size_t, off_t and other values
// change.
-template <typename T>
-const char *GetPythonValueFormatString(T t)
-{
- assert(!"Unhandled type passed to GetPythonValueFormatString(T), make a specialization of GetPythonValueFormatString() to support this type.");
+template <typename T> const char *GetPythonValueFormatString(T t) {
+ assert(!"Unhandled type passed to GetPythonValueFormatString(T), make a "
+ "specialization of GetPythonValueFormatString() to support this "
+ "type.");
+ return nullptr;
+}
+template <> const char *GetPythonValueFormatString(char *) { return "s"; }
+template <> const char *GetPythonValueFormatString(char) { return "b"; }
+template <> const char *GetPythonValueFormatString(unsigned char) {
+ return "B";
+}
+template <> const char *GetPythonValueFormatString(short) { return "h"; }
+template <> const char *GetPythonValueFormatString(unsigned short) {
+ return "H";
+}
+template <> const char *GetPythonValueFormatString(int) { return "i"; }
+template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; }
+template <> const char *GetPythonValueFormatString(long) { return "l"; }
+template <> const char *GetPythonValueFormatString(unsigned long) {
+ return "k";
+}
+template <> const char *GetPythonValueFormatString(long long) { return "L"; }
+template <> const char *GetPythonValueFormatString(unsigned long long) {
+ return "K";
+}
+template <> const char *GetPythonValueFormatString(float t) { return "f"; }
+template <> const char *GetPythonValueFormatString(double t) { return "d"; }
+
+StructuredData::StringSP ScriptInterpreterPython::OSPlugin_RegisterContextData(
+ StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) {
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
+
+ static char callee_name[] = "get_register_data";
+ static char *param_format =
+ const_cast<char *>(GetPythonValueFormatString(tid));
+
+ if (!os_plugin_object_sp)
+ return StructuredData::StringSP();
+
+ StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
+ if (!generic)
return nullptr;
-}
-template <> const char *GetPythonValueFormatString (char *) { return "s"; }
-template <> const char *GetPythonValueFormatString (char) { return "b"; }
-template <> const char *GetPythonValueFormatString (unsigned char) { return "B"; }
-template <> const char *GetPythonValueFormatString (short) { return "h"; }
-template <> const char *GetPythonValueFormatString (unsigned short) { return "H"; }
-template <> const char *GetPythonValueFormatString (int) { return "i"; }
-template <> const char *GetPythonValueFormatString (unsigned int) { return "I"; }
-template <> const char *GetPythonValueFormatString (long) { return "l"; }
-template <> const char *GetPythonValueFormatString (unsigned long) { return "k"; }
-template <> const char *GetPythonValueFormatString (long long) { return "L"; }
-template <> const char *GetPythonValueFormatString (unsigned long long) { return "K"; }
-template <> const char *GetPythonValueFormatString (float t) { return "f"; }
-template <> const char *GetPythonValueFormatString (double t) { return "d"; }
-
-StructuredData::StringSP
-ScriptInterpreterPython::OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid)
-{
- Locker py_lock (this,
- Locker::AcquireLock | Locker::NoSTDIN,
- Locker::FreeLock);
-
- static char callee_name[] = "get_register_data";
- static char *param_format = const_cast<char *>(GetPythonValueFormatString(tid));
-
- if (!os_plugin_object_sp)
- return StructuredData::StringSP();
-
- StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
- if (!generic)
- return nullptr;
- PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)generic->GetValue());
- if (!implementor.IsAllocated())
- return StructuredData::StringSP();
+ if (!implementor.IsAllocated())
+ return StructuredData::StringSP();
- PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
- if (PyErr_Occurred())
- PyErr_Clear();
+ if (PyErr_Occurred())
+ PyErr_Clear();
- if (!pmeth.IsAllocated())
- return StructuredData::StringSP();
-
- if (PyCallable_Check(pmeth.get()) == 0)
- {
- if (PyErr_Occurred())
- PyErr_Clear();
- return StructuredData::StringSP();
- }
-
- if (PyErr_Occurred())
- PyErr_Clear();
-
- // right now we know this function exists and is callable..
- PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, param_format, tid));
+ if (!pmeth.IsAllocated())
+ return StructuredData::StringSP();
- // if it fails, print the error but otherwise go on
+ if (PyCallable_Check(pmeth.get()) == 0) {
if (PyErr_Occurred())
- {
- PyErr_Print();
- PyErr_Clear();
- }
-
- if (py_return.get())
- {
- PythonBytes result(PyRefType::Borrowed, py_return.get());
- return result.CreateStructuredString();
- }
+ PyErr_Clear();
return StructuredData::StringSP();
-}
+ }
-StructuredData::DictionarySP
-ScriptInterpreterPython::OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, lldb::addr_t context)
-{
- Locker py_lock(this,
- Locker::AcquireLock | Locker::NoSTDIN,
- Locker::FreeLock);
-
- static char callee_name[] = "create_thread";
- std::string param_format;
- param_format += GetPythonValueFormatString(tid);
- param_format += GetPythonValueFormatString(context);
-
- if (!os_plugin_object_sp)
- return StructuredData::DictionarySP();
-
- StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
- if (!generic)
- return nullptr;
+ if (PyErr_Occurred())
+ PyErr_Clear();
- PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
+ // right now we know this function exists and is callable..
+ PythonObject py_return(
+ PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name, param_format, tid));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (py_return.get()) {
+ PythonBytes result(PyRefType::Borrowed, py_return.get());
+ return result.CreateStructuredString();
+ }
+ return StructuredData::StringSP();
+}
+
+StructuredData::DictionarySP ScriptInterpreterPython::OSPlugin_CreateThread(
+ StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid,
+ lldb::addr_t context) {
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
+
+ static char callee_name[] = "create_thread";
+ std::string param_format;
+ param_format += GetPythonValueFormatString(tid);
+ param_format += GetPythonValueFormatString(context);
- if (!implementor.IsAllocated())
- return StructuredData::DictionarySP();
+ if (!os_plugin_object_sp)
+ return StructuredData::DictionarySP();
- PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+ StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
+ if (!generic)
+ return nullptr;
- if (PyErr_Occurred())
- PyErr_Clear();
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)generic->GetValue());
- if (!pmeth.IsAllocated())
- return StructuredData::DictionarySP();
-
- if (PyCallable_Check(pmeth.get()) == 0)
- {
- if (PyErr_Occurred())
- PyErr_Clear();
- return StructuredData::DictionarySP();
- }
-
- if (PyErr_Occurred())
- PyErr_Clear();
-
- // right now we know this function exists and is callable..
- PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, ¶m_format[0], tid, context));
+ if (!implementor.IsAllocated())
+ return StructuredData::DictionarySP();
- // if it fails, print the error but otherwise go on
- if (PyErr_Occurred())
- {
- PyErr_Print();
- PyErr_Clear();
- }
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
- if (py_return.get())
- {
- PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
- return result_dict.CreateStructuredDictionary();
- }
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
return StructuredData::DictionarySP();
-}
-StructuredData::ObjectSP
-ScriptInterpreterPython::CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan_sp)
-{
- if (class_name == nullptr || class_name[0] == '\0')
- return StructuredData::ObjectSP();
-
- if (!thread_plan_sp.get())
- return StructuredData::ObjectSP();
-
- Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger();
- ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
- ScriptInterpreterPython *python_interpreter = static_cast<ScriptInterpreterPython *>(script_interpreter);
-
- if (!script_interpreter)
- return StructuredData::ObjectSP();
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return StructuredData::DictionarySP();
+ }
- void* ret_val;
+ if (PyErr_Occurred())
+ PyErr_Clear();
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-
- ret_val = g_swig_thread_plan_script (class_name,
- python_interpreter->m_dictionary_name.c_str(),
- thread_plan_sp);
- }
-
- return StructuredData::ObjectSP(new StructuredPythonObject(ret_val));
-}
-
-bool
-ScriptInterpreterPython::ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error)
-{
- bool explains_stop = true;
- StructuredData::Generic *generic = nullptr;
- if (implementor_sp)
- generic = implementor_sp->GetAsGeneric();
- if (generic)
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- explains_stop = g_swig_call_thread_plan(generic->GetValue(), "explains_stop", event, script_error);
- if (script_error)
- return true;
- }
- return explains_stop;
-}
+ // right now we know this function exists and is callable..
+ PythonObject py_return(PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name,
+ ¶m_format[0], tid, context));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (py_return.get()) {
+ PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
+ return result_dict.CreateStructuredDictionary();
+ }
+ return StructuredData::DictionarySP();
+}
+
+StructuredData::ObjectSP ScriptInterpreterPython::CreateScriptedThreadPlan(
+ const char *class_name, lldb::ThreadPlanSP thread_plan_sp) {
+ if (class_name == nullptr || class_name[0] == '\0')
+ return StructuredData::ObjectSP();
-bool
-ScriptInterpreterPython::ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error)
-{
- bool should_stop = true;
- StructuredData::Generic *generic = nullptr;
- if (implementor_sp)
- generic = implementor_sp->GetAsGeneric();
- if (generic)
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- should_stop = g_swig_call_thread_plan(generic->GetValue(), "should_stop", event, script_error);
- if (script_error)
- return true;
- }
- return should_stop;
-}
+ if (!thread_plan_sp.get())
+ return StructuredData::ObjectSP();
-bool
-ScriptInterpreterPython::ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp, bool &script_error)
-{
- bool is_stale = true;
- StructuredData::Generic *generic = nullptr;
- if (implementor_sp)
- generic = implementor_sp->GetAsGeneric();
- if (generic)
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- is_stale = g_swig_call_thread_plan(generic->GetValue(), "is_stale", nullptr, script_error);
- if (script_error)
- return true;
- }
- return is_stale;
-}
+ Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger();
+ ScriptInterpreter *script_interpreter =
+ debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter =
+ static_cast<ScriptInterpreterPython *>(script_interpreter);
-lldb::StateType
-ScriptInterpreterPython::ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error)
-{
- bool should_step = false;
- StructuredData::Generic *generic = nullptr;
- if (implementor_sp)
- generic = implementor_sp->GetAsGeneric();
- if (generic)
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- should_step = g_swig_call_thread_plan(generic->GetValue(), "should_step", NULL, script_error);
- if (script_error)
- should_step = true;
- }
- if (should_step)
- return lldb::eStateStepping;
- else
- return lldb::eStateRunning;
+ if (!script_interpreter)
+ return StructuredData::ObjectSP();
+
+ void *ret_val;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+
+ ret_val = g_swig_thread_plan_script(
+ class_name, python_interpreter->m_dictionary_name.c_str(),
+ thread_plan_sp);
+ }
+
+ return StructuredData::ObjectSP(new StructuredPythonObject(ret_val));
+}
+
+bool ScriptInterpreterPython::ScriptedThreadPlanExplainsStop(
+ StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) {
+ bool explains_stop = true;
+ StructuredData::Generic *generic = nullptr;
+ if (implementor_sp)
+ generic = implementor_sp->GetAsGeneric();
+ if (generic) {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ explains_stop = g_swig_call_thread_plan(
+ generic->GetValue(), "explains_stop", event, script_error);
+ if (script_error)
+ return true;
+ }
+ return explains_stop;
+}
+
+bool ScriptInterpreterPython::ScriptedThreadPlanShouldStop(
+ StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) {
+ bool should_stop = true;
+ StructuredData::Generic *generic = nullptr;
+ if (implementor_sp)
+ generic = implementor_sp->GetAsGeneric();
+ if (generic) {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ should_stop = g_swig_call_thread_plan(generic->GetValue(), "should_stop",
+ event, script_error);
+ if (script_error)
+ return true;
+ }
+ return should_stop;
+}
+
+bool ScriptInterpreterPython::ScriptedThreadPlanIsStale(
+ StructuredData::ObjectSP implementor_sp, bool &script_error) {
+ bool is_stale = true;
+ StructuredData::Generic *generic = nullptr;
+ if (implementor_sp)
+ generic = implementor_sp->GetAsGeneric();
+ if (generic) {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ is_stale = g_swig_call_thread_plan(generic->GetValue(), "is_stale", nullptr,
+ script_error);
+ if (script_error)
+ return true;
+ }
+ return is_stale;
+}
+
+lldb::StateType ScriptInterpreterPython::ScriptedThreadPlanGetRunState(
+ StructuredData::ObjectSP implementor_sp, bool &script_error) {
+ bool should_step = false;
+ StructuredData::Generic *generic = nullptr;
+ if (implementor_sp)
+ generic = implementor_sp->GetAsGeneric();
+ if (generic) {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ should_step = g_swig_call_thread_plan(generic->GetValue(), "should_step",
+ NULL, script_error);
+ if (script_error)
+ should_step = true;
+ }
+ if (should_step)
+ return lldb::eStateStepping;
+ else
+ return lldb::eStateRunning;
}
StructuredData::ObjectSP
-ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error)
-{
- if (!file_spec.Exists())
- {
- error.SetErrorString("no such file");
- return StructuredData::ObjectSP();
- }
+ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec,
+ lldb_private::Error &error) {
+ if (!file_spec.Exists()) {
+ error.SetErrorString("no such file");
+ return StructuredData::ObjectSP();
+ }
- StructuredData::ObjectSP module_sp;
+ StructuredData::ObjectSP module_sp;
- if (LoadScriptingModule(file_spec.GetPath().c_str(),true,true,error,&module_sp))
- return module_sp;
+ if (LoadScriptingModule(file_spec.GetPath().c_str(), true, true, error,
+ &module_sp))
+ return module_sp;
- return StructuredData::ObjectSP();
+ return StructuredData::ObjectSP();
}
-StructuredData::DictionarySP
-ScriptInterpreterPython::GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name,
- lldb_private::Error &error)
-{
- if (!plugin_module_sp || !target || !setting_name || !setting_name[0] || !g_swig_plugin_get)
- return StructuredData::DictionarySP();
- StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric();
- if (!generic)
- return StructuredData::DictionarySP();
+StructuredData::DictionarySP ScriptInterpreterPython::GetDynamicSettings(
+ StructuredData::ObjectSP plugin_module_sp, Target *target,
+ const char *setting_name, lldb_private::Error &error) {
+ if (!plugin_module_sp || !target || !setting_name || !setting_name[0] ||
+ !g_swig_plugin_get)
+ return StructuredData::DictionarySP();
+ StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric();
+ if (!generic)
+ return StructuredData::DictionarySP();
- PythonObject reply_pyobj;
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- TargetSP target_sp(target->shared_from_this());
- reply_pyobj.Reset(PyRefType::Owned,
- (PyObject *)g_swig_plugin_get(generic->GetValue(), setting_name, target_sp));
- }
+ PythonObject reply_pyobj;
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ TargetSP target_sp(target->shared_from_this());
+ reply_pyobj.Reset(PyRefType::Owned,
+ (PyObject *)g_swig_plugin_get(generic->GetValue(),
+ setting_name, target_sp));
+ }
- PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get());
- return py_dict.CreateStructuredDictionary();
+ PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get());
+ return py_dict.CreateStructuredDictionary();
}
StructuredData::ObjectSP
-ScriptInterpreterPython::CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj)
-{
- if (class_name == nullptr || class_name[0] == '\0')
- return StructuredData::ObjectSP();
-
- if (!valobj.get())
- return StructuredData::ObjectSP();
-
- ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
- Target *target = exe_ctx.GetTargetPtr();
-
- if (!target)
- return StructuredData::ObjectSP();
-
- Debugger &debugger = target->GetDebugger();
- ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
- ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
-
- if (!script_interpreter)
- return StructuredData::ObjectSP();
+ScriptInterpreterPython::CreateSyntheticScriptedProvider(
+ const char *class_name, lldb::ValueObjectSP valobj) {
+ if (class_name == nullptr || class_name[0] == '\0')
+ return StructuredData::ObjectSP();
+
+ if (!valobj.get())
+ return StructuredData::ObjectSP();
- void *ret_val = nullptr;
+ ExecutionContext exe_ctx(valobj->GetExecutionContextRef());
+ Target *target = exe_ctx.GetTargetPtr();
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_synthetic_script (class_name,
- python_interpreter->m_dictionary_name.c_str(),
- valobj);
- }
+ if (!target)
+ return StructuredData::ObjectSP();
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreter *script_interpreter =
+ debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter =
+ (ScriptInterpreterPython *)script_interpreter;
+
+ if (!script_interpreter)
+ return StructuredData::ObjectSP();
+
+ void *ret_val = nullptr;
- return StructuredData::ObjectSP(new StructuredPythonObject(ret_val));
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_synthetic_script(
+ class_name, python_interpreter->m_dictionary_name.c_str(), valobj);
+ }
+
+ return StructuredData::ObjectSP(new StructuredPythonObject(ret_val));
}
StructuredData::GenericSP
-ScriptInterpreterPython::CreateScriptCommandObject (const char *class_name)
-{
- DebuggerSP debugger_sp(GetCommandInterpreter().GetDebugger().shared_from_this());
-
- if (class_name == nullptr || class_name[0] == '\0')
- return StructuredData::GenericSP();
-
- if (!debugger_sp.get())
- return StructuredData::GenericSP();
-
- void* ret_val;
-
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_create_cmd (class_name,
- m_dictionary_name.c_str(),
- debugger_sp);
- }
-
- return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
-}
-
-bool
-ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token)
-{
- StringList input;
- input.SplitIntoLines(oneliner, strlen(oneliner));
- return GenerateTypeScriptFunction(input, output, name_token);
-}
-
-bool
-ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token)
-{
- StringList input;
- input.SplitIntoLines(oneliner, strlen(oneliner));
- return GenerateTypeSynthClass(input, output, name_token);
-}
+ScriptInterpreterPython::CreateScriptCommandObject(const char *class_name) {
+ DebuggerSP debugger_sp(
+ GetCommandInterpreter().GetDebugger().shared_from_this());
+ if (class_name == nullptr || class_name[0] == '\0')
+ return StructuredData::GenericSP();
-Error
-ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, std::string& output)
-{
- static uint32_t num_created_functions = 0;
- user_input.RemoveBlankLines ();
- StreamString sstr;
- Error error;
- if (user_input.GetSize() == 0)
- {
- error.SetErrorString("No input data.");
- return error;
- }
+ if (!debugger_sp.get())
+ return StructuredData::GenericSP();
+
+ void *ret_val;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val =
+ g_swig_create_cmd(class_name, m_dictionary_name.c_str(), debugger_sp);
+ }
+
+ return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
+}
+
+bool ScriptInterpreterPython::GenerateTypeScriptFunction(
+ const char *oneliner, std::string &output, const void *name_token) {
+ StringList input;
+ input.SplitIntoLines(oneliner, strlen(oneliner));
+ return GenerateTypeScriptFunction(input, output, name_token);
+}
+
+bool ScriptInterpreterPython::GenerateTypeSynthClass(const char *oneliner,
+ std::string &output,
+ const void *name_token) {
+ StringList input;
+ input.SplitIntoLines(oneliner, strlen(oneliner));
+ return GenerateTypeSynthClass(input, output, name_token);
+}
+
+Error ScriptInterpreterPython::GenerateBreakpointCommandCallbackData(
+ StringList &user_input, std::string &output) {
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines();
+ StreamString sstr;
+ Error error;
+ if (user_input.GetSize() == 0) {
+ error.SetErrorString("No input data.");
+ return error;
+ }
- std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_bp_callback_func_",num_created_functions));
- sstr.Printf ("def %s (frame, bp_loc, internal_dict):", auto_generated_function_name.c_str());
-
- error = GenerateFunction(sstr.GetData(), user_input);
- if (!error.Success())
- return error;
-
- // Store the name of the auto-generated function to be called.
- output.assign(auto_generated_function_name);
+ std::string auto_generated_function_name(GenerateUniqueName(
+ "lldb_autogen_python_bp_callback_func_", num_created_functions));
+ sstr.Printf("def %s (frame, bp_loc, internal_dict):",
+ auto_generated_function_name.c_str());
+
+ error = GenerateFunction(sstr.GetData(), user_input);
+ if (!error.Success())
return error;
+
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return error;
}
-bool
-ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user_input, std::string& output)
-{
- static uint32_t num_created_functions = 0;
- user_input.RemoveBlankLines ();
- StreamString sstr;
+bool ScriptInterpreterPython::GenerateWatchpointCommandCallbackData(
+ StringList &user_input, std::string &output) {
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines();
+ StreamString sstr;
- if (user_input.GetSize() == 0)
- return false;
+ if (user_input.GetSize() == 0)
+ return false;
- std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_wp_callback_func_",num_created_functions));
- sstr.Printf ("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str());
-
- if (!GenerateFunction(sstr.GetData(), user_input).Success())
- return false;
-
- // Store the name of the auto-generated function to be called.
- output.assign(auto_generated_function_name);
- return true;
+ std::string auto_generated_function_name(GenerateUniqueName(
+ "lldb_autogen_python_wp_callback_func_", num_created_functions));
+ sstr.Printf("def %s (frame, wp, internal_dict):",
+ auto_generated_function_name.c_str());
+
+ if (!GenerateFunction(sstr.GetData(), user_input).Success())
+ return false;
+
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return true;
}
-bool
-ScriptInterpreterPython::GetScriptedSummary(const char *python_function_name, lldb::ValueObjectSP valobj,
- StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options,
- std::string &retval)
-{
-
- Timer scoped_timer (LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
-
- if (!valobj.get())
- {
- retval.assign("<no object>");
- return false;
- }
+bool ScriptInterpreterPython::GetScriptedSummary(
+ const char *python_function_name, lldb::ValueObjectSP valobj,
+ StructuredData::ObjectSP &callee_wrapper_sp,
+ const TypeSummaryOptions &options, std::string &retval) {
- void *old_callee = nullptr;
- StructuredData::Generic *generic = nullptr;
- if (callee_wrapper_sp)
- {
- generic = callee_wrapper_sp->GetAsGeneric();
- if (generic)
- old_callee = generic->GetValue();
- }
- void* new_callee = old_callee;
-
- bool ret_val;
- if (python_function_name && *python_function_name)
- {
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- {
- TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options));
-
- Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback");
- ret_val = g_swig_typescript_callback (python_function_name,
- GetSessionDictionary().get(),
- valobj,
- &new_callee,
- options_sp,
- retval);
- }
- }
- }
- else
- {
- retval.assign("<no function name>");
- return false;
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+
+ if (!valobj.get()) {
+ retval.assign("<no object>");
+ return false;
+ }
+
+ void *old_callee = nullptr;
+ StructuredData::Generic *generic = nullptr;
+ if (callee_wrapper_sp) {
+ generic = callee_wrapper_sp->GetAsGeneric();
+ if (generic)
+ old_callee = generic->GetValue();
+ }
+ void *new_callee = old_callee;
+
+ bool ret_val;
+ if (python_function_name && *python_function_name) {
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession |
+ Locker::NoSTDIN);
+ {
+ TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options));
+
+ Timer scoped_timer("g_swig_typescript_callback",
+ "g_swig_typescript_callback");
+ ret_val = g_swig_typescript_callback(
+ python_function_name, GetSessionDictionary().get(), valobj,
+ &new_callee, options_sp, retval);
+ }
}
-
- if (new_callee && old_callee != new_callee)
- callee_wrapper_sp.reset(new StructuredPythonObject(new_callee));
+ } else {
+ retval.assign("<no function name>");
+ return false;
+ }
- return ret_val;
+ if (new_callee && old_callee != new_callee)
+ callee_wrapper_sp.reset(new StructuredPythonObject(new_callee));
+
+ return ret_val;
}
-void
-ScriptInterpreterPython::Clear ()
-{
- // Release any global variables that might have strong references to
- // LLDB objects when clearing the python script interpreter.
- Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock,
- ScriptInterpreterPython::Locker::FreeAcquiredLock);
-
- // This may be called as part of Py_Finalize. In that case the modules are destroyed in random
- // order and we can't guarantee that we can access these.
- if (Py_IsInitialized())
- PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process = None; lldb.thread = None; lldb.frame = None");
-}
-
-bool
-ScriptInterpreterPython::BreakpointCallbackFunction
-(
- void *baton,
- StoppointCallbackContext *context,
- user_id_t break_id,
- user_id_t break_loc_id
-)
-{
- BreakpointOptions::CommandData *bp_option_data = (BreakpointOptions::CommandData *) baton;
- const char *python_function_name = bp_option_data->script_source.c_str();
-
- if (!context)
- return true;
-
- ExecutionContext exe_ctx (context->exe_ctx_ref);
- Target *target = exe_ctx.GetTargetPtr();
-
- if (!target)
- return true;
-
- Debugger &debugger = target->GetDebugger();
- ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
- ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
-
- if (!script_interpreter)
- return true;
-
- if (python_function_name && python_function_name[0])
- {
- const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP());
- BreakpointSP breakpoint_sp = target->GetBreakpointByID (break_id);
- if (breakpoint_sp)
- {
- const BreakpointLocationSP bp_loc_sp (breakpoint_sp->FindLocationByID (break_loc_id));
+void ScriptInterpreterPython::Clear() {
+ // Release any global variables that might have strong references to
+ // LLDB objects when clearing the python script interpreter.
+ Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
- if (stop_frame_sp && bp_loc_sp)
- {
- bool ret_val = true;
- {
- Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_breakpoint_callback (python_function_name,
- python_interpreter->m_dictionary_name.c_str(),
- stop_frame_sp,
- bp_loc_sp);
- }
- return ret_val;
- }
- }
- }
- // We currently always true so we stop in case anything goes wrong when
- // trying to call the script function
- return true;
+ // This may be called as part of Py_Finalize. In that case the modules are
+ // destroyed in random
+ // order and we can't guarantee that we can access these.
+ if (Py_IsInitialized())
+ PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process "
+ "= None; lldb.thread = None; lldb.frame = None");
}
-bool
-ScriptInterpreterPython::WatchpointCallbackFunction
-(
- void *baton,
- StoppointCallbackContext *context,
- user_id_t watch_id
-)
-{
- WatchpointOptions::CommandData *wp_option_data = (WatchpointOptions::CommandData *) baton;
- const char *python_function_name = wp_option_data->script_source.c_str();
-
- if (!context)
- return true;
-
- ExecutionContext exe_ctx (context->exe_ctx_ref);
- Target *target = exe_ctx.GetTargetPtr();
-
- if (!target)
- return true;
-
- Debugger &debugger = target->GetDebugger();
- ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
- ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
-
- if (!script_interpreter)
- return true;
-
- if (python_function_name && python_function_name[0])
- {
- const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP());
- WatchpointSP wp_sp = target->GetWatchpointList().FindByID (watch_id);
- if (wp_sp)
- {
- if (stop_frame_sp && wp_sp)
- {
- bool ret_val = true;
- {
- Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_watchpoint_callback (python_function_name,
- python_interpreter->m_dictionary_name.c_str(),
- stop_frame_sp,
- wp_sp);
- }
- return ret_val;
- }
- }
- }
- // We currently always true so we stop in case anything goes wrong when
- // trying to call the script function
+bool ScriptInterpreterPython::BreakpointCallbackFunction(
+ void *baton, StoppointCallbackContext *context, user_id_t break_id,
+ user_id_t break_loc_id) {
+ BreakpointOptions::CommandData *bp_option_data =
+ (BreakpointOptions::CommandData *)baton;
+ const char *python_function_name = bp_option_data->script_source.c_str();
+
+ if (!context)
return true;
-}
-size_t
-ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &implementor_sp, uint32_t max)
-{
- if (!implementor_sp)
- return 0;
- StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
- if (!generic)
- return 0;
- void *implementor = generic->GetValue();
- if (!implementor)
- return 0;
-
- if (!g_swig_calc_children)
- return 0;
+ ExecutionContext exe_ctx(context->exe_ctx_ref);
+ Target *target = exe_ctx.GetTargetPtr();
- size_t ret_val = 0;
-
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_calc_children (implementor, max);
+ if (!target)
+ return true;
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreter *script_interpreter =
+ debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter =
+ (ScriptInterpreterPython *)script_interpreter;
+
+ if (!script_interpreter)
+ return true;
+
+ if (python_function_name && python_function_name[0]) {
+ const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
+ BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id);
+ if (breakpoint_sp) {
+ const BreakpointLocationSP bp_loc_sp(
+ breakpoint_sp->FindLocationByID(break_loc_id));
+
+ if (stop_frame_sp && bp_loc_sp) {
+ bool ret_val = true;
+ {
+ Locker py_lock(python_interpreter, Locker::AcquireLock |
+ Locker::InitSession |
+ Locker::NoSTDIN);
+ ret_val = g_swig_breakpoint_callback(
+ python_function_name,
+ python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
+ bp_loc_sp);
+ }
+ return ret_val;
+ }
}
-
- return ret_val;
+ }
+ // We currently always true so we stop in case anything goes wrong when
+ // trying to call the script function
+ return true;
}
-lldb::ValueObjectSP
-ScriptInterpreterPython::GetChildAtIndex(const StructuredData::ObjectSP &implementor_sp, uint32_t idx)
-{
- if (!implementor_sp)
- return lldb::ValueObjectSP();
-
- StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
- if (!generic)
- return lldb::ValueObjectSP();
- void *implementor = generic->GetValue();
- if (!implementor)
- return lldb::ValueObjectSP();
-
- if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue)
- return lldb::ValueObjectSP();
-
- lldb::ValueObjectSP ret_val;
-
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- void* child_ptr = g_swig_get_child_index (implementor,idx);
- if (child_ptr != nullptr && child_ptr != Py_None)
- {
- lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
- if (sb_value_ptr == nullptr)
- Py_XDECREF(child_ptr);
- else
- ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr);
- }
- else
- {
- Py_XDECREF(child_ptr);
+bool ScriptInterpreterPython::WatchpointCallbackFunction(
+ void *baton, StoppointCallbackContext *context, user_id_t watch_id) {
+ WatchpointOptions::CommandData *wp_option_data =
+ (WatchpointOptions::CommandData *)baton;
+ const char *python_function_name = wp_option_data->script_source.c_str();
+
+ if (!context)
+ return true;
+
+ ExecutionContext exe_ctx(context->exe_ctx_ref);
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (!target)
+ return true;
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreter *script_interpreter =
+ debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter =
+ (ScriptInterpreterPython *)script_interpreter;
+
+ if (!script_interpreter)
+ return true;
+
+ if (python_function_name && python_function_name[0]) {
+ const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
+ WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id);
+ if (wp_sp) {
+ if (stop_frame_sp && wp_sp) {
+ bool ret_val = true;
+ {
+ Locker py_lock(python_interpreter, Locker::AcquireLock |
+ Locker::InitSession |
+ Locker::NoSTDIN);
+ ret_val = g_swig_watchpoint_callback(
+ python_function_name,
+ python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
+ wp_sp);
}
+ return ret_val;
+ }
}
-
- return ret_val;
+ }
+ // We currently always true so we stop in case anything goes wrong when
+ // trying to call the script function
+ return true;
+}
+
+size_t ScriptInterpreterPython::CalculateNumChildren(
+ const StructuredData::ObjectSP &implementor_sp, uint32_t max) {
+ if (!implementor_sp)
+ return 0;
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return 0;
+ void *implementor = generic->GetValue();
+ if (!implementor)
+ return 0;
+
+ if (!g_swig_calc_children)
+ return 0;
+
+ size_t ret_val = 0;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_calc_children(implementor, max);
+ }
+
+ return ret_val;
}
-int
-ScriptInterpreterPython::GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor_sp, const char *child_name)
-{
- if (!implementor_sp)
- return UINT32_MAX;
-
- StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
- if (!generic)
- return UINT32_MAX;
- void *implementor = generic->GetValue();
- if (!implementor)
- return UINT32_MAX;
-
- if (!g_swig_get_index_child)
- return UINT32_MAX;
-
- int ret_val = UINT32_MAX;
-
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_get_index_child (implementor, child_name);
- }
-
- return ret_val;
+lldb::ValueObjectSP ScriptInterpreterPython::GetChildAtIndex(
+ const StructuredData::ObjectSP &implementor_sp, uint32_t idx) {
+ if (!implementor_sp)
+ return lldb::ValueObjectSP();
+
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return lldb::ValueObjectSP();
+ void *implementor = generic->GetValue();
+ if (!implementor)
+ return lldb::ValueObjectSP();
+
+ if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue)
+ return lldb::ValueObjectSP();
+
+ lldb::ValueObjectSP ret_val;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ void *child_ptr = g_swig_get_child_index(implementor, idx);
+ if (child_ptr != nullptr && child_ptr != Py_None) {
+ lldb::SBValue *sb_value_ptr =
+ (lldb::SBValue *)g_swig_cast_to_sbvalue(child_ptr);
+ if (sb_value_ptr == nullptr)
+ Py_XDECREF(child_ptr);
+ else
+ ret_val = g_swig_get_valobj_sp_from_sbvalue(sb_value_ptr);
+ } else {
+ Py_XDECREF(child_ptr);
+ }
+ }
+
+ return ret_val;
+}
+
+int ScriptInterpreterPython::GetIndexOfChildWithName(
+ const StructuredData::ObjectSP &implementor_sp, const char *child_name) {
+ if (!implementor_sp)
+ return UINT32_MAX;
+
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return UINT32_MAX;
+ void *implementor = generic->GetValue();
+ if (!implementor)
+ return UINT32_MAX;
+
+ if (!g_swig_get_index_child)
+ return UINT32_MAX;
+
+ int ret_val = UINT32_MAX;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_get_index_child(implementor, child_name);
+ }
+
+ return ret_val;
}
-bool
-ScriptInterpreterPython::UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp)
-{
- bool ret_val = false;
-
- if (!implementor_sp)
- return ret_val;
+bool ScriptInterpreterPython::UpdateSynthProviderInstance(
+ const StructuredData::ObjectSP &implementor_sp) {
+ bool ret_val = false;
- StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
- if (!generic)
- return ret_val;
- void *implementor = generic->GetValue();
- if (!implementor)
- return ret_val;
-
- if (!g_swig_update_provider)
- return ret_val;
-
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_update_provider (implementor);
- }
-
+ if (!implementor_sp)
return ret_val;
-}
-bool
-ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp)
-{
- bool ret_val = false;
-
- if (!implementor_sp)
- return ret_val;
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return ret_val;
+ void *implementor = generic->GetValue();
+ if (!implementor)
+ return ret_val;
- StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
- if (!generic)
- return ret_val;
- void *implementor = generic->GetValue();
- if (!implementor)
- return ret_val;
-
- if (!g_swig_mighthavechildren_provider)
- return ret_val;
-
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_mighthavechildren_provider (implementor);
- }
-
+ if (!g_swig_update_provider)
return ret_val;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_update_provider(implementor);
+ }
+
+ return ret_val;
}
-lldb::ValueObjectSP
-ScriptInterpreterPython::GetSyntheticValue(const StructuredData::ObjectSP &implementor_sp)
-{
- lldb::ValueObjectSP ret_val(nullptr);
-
- if (!implementor_sp)
- return ret_val;
+bool ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance(
+ const StructuredData::ObjectSP &implementor_sp) {
+ bool ret_val = false;
- StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
- if (!generic)
- return ret_val;
- void *implementor = generic->GetValue();
- if (!implementor)
- return ret_val;
-
- if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue || !g_swig_get_valobj_sp_from_sbvalue)
- return ret_val;
-
- {
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- void* child_ptr = g_swig_getvalue_provider (implementor);
- if (child_ptr != nullptr && child_ptr != Py_None)
- {
- lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
- if (sb_value_ptr == nullptr)
- Py_XDECREF(child_ptr);
- else
- ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr);
- }
- else
- {
- Py_XDECREF(child_ptr);
- }
- }
-
+ if (!implementor_sp)
return ret_val;
+
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return ret_val;
+ void *implementor = generic->GetValue();
+ if (!implementor)
+ return ret_val;
+
+ if (!g_swig_mighthavechildren_provider)
+ return ret_val;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_mighthavechildren_provider(implementor);
+ }
+
+ return ret_val;
}
-ConstString
-ScriptInterpreterPython::GetSyntheticTypeName (const StructuredData::ObjectSP &implementor_sp)
-{
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-
- static char callee_name[] = "get_type_name";
-
- ConstString ret_val;
- bool got_string = false;
- std::string buffer;
+lldb::ValueObjectSP ScriptInterpreterPython::GetSyntheticValue(
+ const StructuredData::ObjectSP &implementor_sp) {
+ lldb::ValueObjectSP ret_val(nullptr);
- if (!implementor_sp)
- return ret_val;
-
- StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
- if (!generic)
- return ret_val;
- PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
- if (!implementor.IsAllocated())
- return ret_val;
-
- PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
-
- if (PyErr_Occurred())
- PyErr_Clear();
-
- if (!pmeth.IsAllocated())
- return ret_val;
-
- if (PyCallable_Check(pmeth.get()) == 0)
- {
- if (PyErr_Occurred())
- PyErr_Clear();
- return ret_val;
- }
-
- if (PyErr_Occurred())
- PyErr_Clear();
-
- // right now we know this function exists and is callable..
- PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
-
- // if it fails, print the error but otherwise go on
- if (PyErr_Occurred())
- {
- PyErr_Print();
- PyErr_Clear();
- }
-
- if (py_return.IsAllocated() && PythonString::Check(py_return.get()))
- {
- PythonString py_string(PyRefType::Borrowed, py_return.get());
- llvm::StringRef return_data(py_string.GetString());
- if (!return_data.empty())
- {
- buffer.assign(return_data.data(), return_data.size());
- got_string = true;
- }
- }
-
- if (got_string)
- ret_val.SetCStringWithLength(buffer.c_str(), buffer.size());
-
+ if (!implementor_sp)
return ret_val;
-}
-bool
-ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
- Process* process,
- std::string& output,
- Error& error)
-{
- bool ret_val;
- if (!process)
- {
- error.SetErrorString("no process");
- return false;
- }
- if (!impl_function || !impl_function[0])
- {
- error.SetErrorString("no function to execute");
- return false;
- }
- if (!g_swig_run_script_keyword_process)
- {
- error.SetErrorString("internal helper function missing");
- return false;
- }
- {
- ProcessSP process_sp(process->shared_from_this());
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_run_script_keyword_process (impl_function, m_dictionary_name.c_str(), process_sp, output);
- if (!ret_val)
- error.SetErrorString("python script evaluation failed");
- }
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return ret_val;
+ void *implementor = generic->GetValue();
+ if (!implementor)
return ret_val;
-}
-bool
-ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
- Thread* thread,
- std::string& output,
- Error& error)
-{
- bool ret_val;
- if (!thread)
- {
- error.SetErrorString("no thread");
- return false;
- }
- if (!impl_function || !impl_function[0])
- {
- error.SetErrorString("no function to execute");
- return false;
- }
- if (!g_swig_run_script_keyword_thread)
- {
- error.SetErrorString("internal helper function missing");
- return false;
- }
- {
- ThreadSP thread_sp(thread->shared_from_this());
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_run_script_keyword_thread (impl_function, m_dictionary_name.c_str(), thread_sp, output);
- if (!ret_val)
- error.SetErrorString("python script evaluation failed");
- }
+ if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue ||
+ !g_swig_get_valobj_sp_from_sbvalue)
return ret_val;
-}
-bool
-ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
- Target* target,
- std::string& output,
- Error& error)
-{
- bool ret_val;
- if (!target)
- {
- error.SetErrorString("no thread");
- return false;
- }
- if (!impl_function || !impl_function[0])
- {
- error.SetErrorString("no function to execute");
- return false;
- }
- if (!g_swig_run_script_keyword_target)
- {
- error.SetErrorString("internal helper function missing");
- return false;
- }
- {
- TargetSP target_sp(target->shared_from_this());
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_run_script_keyword_target (impl_function, m_dictionary_name.c_str(), target_sp, output);
- if (!ret_val)
- error.SetErrorString("python script evaluation failed");
- }
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ void *child_ptr = g_swig_getvalue_provider(implementor);
+ if (child_ptr != nullptr && child_ptr != Py_None) {
+ lldb::SBValue *sb_value_ptr =
+ (lldb::SBValue *)g_swig_cast_to_sbvalue(child_ptr);
+ if (sb_value_ptr == nullptr)
+ Py_XDECREF(child_ptr);
+ else
+ ret_val = g_swig_get_valobj_sp_from_sbvalue(sb_value_ptr);
+ } else {
+ Py_XDECREF(child_ptr);
+ }
+ }
+
+ return ret_val;
+}
+
+ConstString ScriptInterpreterPython::GetSyntheticTypeName(
+ const StructuredData::ObjectSP &implementor_sp) {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+
+ static char callee_name[] = "get_type_name";
+
+ ConstString ret_val;
+ bool got_string = false;
+ std::string buffer;
+
+ if (!implementor_sp)
return ret_val;
-}
-bool
-ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
- StackFrame* frame,
- std::string& output,
- Error& error)
-{
- bool ret_val;
- if (!frame)
- {
- error.SetErrorString("no frame");
- return false;
- }
- if (!impl_function || !impl_function[0])
- {
- error.SetErrorString("no function to execute");
- return false;
- }
- if (!g_swig_run_script_keyword_frame)
- {
- error.SetErrorString("internal helper function missing");
- return false;
- }
- {
- StackFrameSP frame_sp(frame->shared_from_this());
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_run_script_keyword_frame (impl_function, m_dictionary_name.c_str(), frame_sp, output);
- if (!ret_val)
- error.SetErrorString("python script evaluation failed");
- }
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
return ret_val;
-}
-
-bool
-ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
- ValueObject *value,
- std::string& output,
- Error& error)
-{
- bool ret_val;
- if (!value)
- {
- error.SetErrorString("no value");
- return false;
- }
- if (!impl_function || !impl_function[0])
- {
- error.SetErrorString("no function to execute");
- return false;
- }
- if (!g_swig_run_script_keyword_value)
- {
- error.SetErrorString("internal helper function missing");
- return false;
- }
- {
- ValueObjectSP value_sp(value->GetSP());
- Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_run_script_keyword_value (impl_function, m_dictionary_name.c_str(), value_sp, output);
- if (!ret_val)
- error.SetErrorString("python script evaluation failed");
- }
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)generic->GetValue());
+ if (!implementor.IsAllocated())
+ return ret_val;
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return ret_val;
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
return ret_val;
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(
+ PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (py_return.IsAllocated() && PythonString::Check(py_return.get())) {
+ PythonString py_string(PyRefType::Borrowed, py_return.get());
+ llvm::StringRef return_data(py_string.GetString());
+ if (!return_data.empty()) {
+ buffer.assign(return_data.data(), return_data.size());
+ got_string = true;
+ }
+ }
+
+ if (got_string)
+ ret_val.SetCStringWithLength(buffer.c_str(), buffer.size());
+
+ return ret_val;
+}
+
+bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function,
+ Process *process,
+ std::string &output,
+ Error &error) {
+ bool ret_val;
+ if (!process) {
+ error.SetErrorString("no process");
+ return false;
+ }
+ if (!impl_function || !impl_function[0]) {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_process) {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ ProcessSP process_sp(process->shared_from_this());
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_run_script_keyword_process(
+ impl_function, m_dictionary_name.c_str(), process_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
}
-uint64_t replace_all(std::string& str, const std::string& oldStr, const std::string& newStr)
-{
- size_t pos = 0;
- uint64_t matches = 0;
- while((pos = str.find(oldStr, pos)) != std::string::npos)
- {
- matches++;
- str.replace(pos, oldStr.length(), newStr);
- pos += newStr.length();
- }
- return matches;
+bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function,
+ Thread *thread,
+ std::string &output,
+ Error &error) {
+ bool ret_val;
+ if (!thread) {
+ error.SetErrorString("no thread");
+ return false;
+ }
+ if (!impl_function || !impl_function[0]) {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_thread) {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ ThreadSP thread_sp(thread->shared_from_this());
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_run_script_keyword_thread(
+ impl_function, m_dictionary_name.c_str(), thread_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
}
-bool
-ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_reload, bool init_session, lldb_private::Error &error,
- StructuredData::ObjectSP *module_sp)
-{
- if (!pathname || !pathname[0])
- {
+bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function,
+ Target *target,
+ std::string &output,
+ Error &error) {
+ bool ret_val;
+ if (!target) {
+ error.SetErrorString("no thread");
+ return false;
+ }
+ if (!impl_function || !impl_function[0]) {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_target) {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ TargetSP target_sp(target->shared_from_this());
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_run_script_keyword_target(
+ impl_function, m_dictionary_name.c_str(), target_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function,
+ StackFrame *frame,
+ std::string &output,
+ Error &error) {
+ bool ret_val;
+ if (!frame) {
+ error.SetErrorString("no frame");
+ return false;
+ }
+ if (!impl_function || !impl_function[0]) {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_frame) {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ StackFrameSP frame_sp(frame->shared_from_this());
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_run_script_keyword_frame(
+ impl_function, m_dictionary_name.c_str(), frame_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function,
+ ValueObject *value,
+ std::string &output,
+ Error &error) {
+ bool ret_val;
+ if (!value) {
+ error.SetErrorString("no value");
+ return false;
+ }
+ if (!impl_function || !impl_function[0]) {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_value) {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ ValueObjectSP value_sp(value->GetSP());
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_run_script_keyword_value(
+ impl_function, m_dictionary_name.c_str(), value_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+uint64_t replace_all(std::string &str, const std::string &oldStr,
+ const std::string &newStr) {
+ size_t pos = 0;
+ uint64_t matches = 0;
+ while ((pos = str.find(oldStr, pos)) != std::string::npos) {
+ matches++;
+ str.replace(pos, oldStr.length(), newStr);
+ pos += newStr.length();
+ }
+ return matches;
+}
+
+bool ScriptInterpreterPython::LoadScriptingModule(
+ const char *pathname, bool can_reload, bool init_session,
+ lldb_private::Error &error, StructuredData::ObjectSP *module_sp) {
+ if (!pathname || !pathname[0]) {
+ error.SetErrorString("invalid pathname");
+ return false;
+ }
+
+ if (!g_swig_call_module_init) {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+
+ lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
+
+ {
+ FileSpec target_file(pathname, true);
+ std::string basename(target_file.GetFilename().GetCString());
+
+ StreamString command_stream;
+
+ // Before executing Python code, lock the GIL.
+ Locker py_lock(this, Locker::AcquireLock |
+ (init_session ? Locker::InitSession : 0) |
+ Locker::NoSTDIN,
+ Locker::FreeAcquiredLock |
+ (init_session ? Locker::TearDownSession : 0));
+
+ if (target_file.GetFileType() == FileSpec::eFileTypeInvalid ||
+ target_file.GetFileType() == FileSpec::eFileTypeUnknown) {
+ // if not a valid file of any sort, check if it might be a filename still
+ // dot can't be used but / and \ can, and if either is found, reject
+ if (strchr(pathname, '\\') || strchr(pathname, '/')) {
error.SetErrorString("invalid pathname");
return false;
+ }
+ basename = pathname; // not a filename, probably a package of some sort,
+ // let it go through
+ } else if (target_file.GetFileType() == FileSpec::eFileTypeDirectory ||
+ target_file.GetFileType() == FileSpec::eFileTypeRegular ||
+ target_file.GetFileType() == FileSpec::eFileTypeSymbolicLink) {
+ std::string directory = target_file.GetDirectory().GetCString();
+ replace_all(directory, "\\", "\\\\");
+ replace_all(directory, "'", "\\'");
+
+ // now make sure that Python has "directory" in the search path
+ StreamString command_stream;
+ command_stream.Printf("if not (sys.path.__contains__('%s')):\n "
+ "sys.path.insert(1,'%s');\n\n",
+ directory.c_str(), directory.c_str());
+ bool syspath_retval =
+ ExecuteMultipleLines(command_stream.GetData(),
+ ScriptInterpreter::ExecuteScriptOptions()
+ .SetEnableIO(false)
+ .SetSetLLDBGlobals(false))
+ .Success();
+ if (!syspath_retval) {
+ error.SetErrorString("Python sys.path handling failed");
+ return false;
+ }
+
+ // strip .py or .pyc extension
+ ConstString extension = target_file.GetFileNameExtension();
+ if (extension) {
+ if (::strcmp(extension.GetCString(), "py") == 0)
+ basename.resize(basename.length() - 3);
+ else if (::strcmp(extension.GetCString(), "pyc") == 0)
+ basename.resize(basename.length() - 4);
+ }
+ } else {
+ error.SetErrorString("no known way to import this module specification");
+ return false;
+ }
+
+ // check if the module is already import-ed
+ command_stream.Clear();
+ command_stream.Printf("sys.modules.__contains__('%s')", basename.c_str());
+ bool does_contain = false;
+ // this call will succeed if the module was ever imported in any Debugger in
+ // the lifetime of the process
+ // in which this LLDB framework is living
+ bool was_imported_globally =
+ (ExecuteOneLineWithReturn(
+ command_stream.GetData(),
+ ScriptInterpreterPython::eScriptReturnTypeBool, &does_contain,
+ ScriptInterpreter::ExecuteScriptOptions()
+ .SetEnableIO(false)
+ .SetSetLLDBGlobals(false)) &&
+ does_contain);
+ // this call will fail if the module was not imported in this Debugger
+ // before
+ command_stream.Clear();
+ command_stream.Printf("sys.getrefcount(%s)", basename.c_str());
+ bool was_imported_locally = GetSessionDictionary()
+ .GetItemForKey(PythonString(basename))
+ .IsAllocated();
+
+ bool was_imported = (was_imported_globally || was_imported_locally);
+
+ if (was_imported == true && can_reload == false) {
+ error.SetErrorString("module already imported");
+ return false;
+ }
+
+ // now actually do the import
+ command_stream.Clear();
+
+ if (was_imported) {
+ if (!was_imported_locally)
+ command_stream.Printf("import %s ; reload_module(%s)", basename.c_str(),
+ basename.c_str());
+ else
+ command_stream.Printf("reload_module(%s)", basename.c_str());
+ } else
+ command_stream.Printf("import %s", basename.c_str());
+
+ error = ExecuteMultipleLines(command_stream.GetData(),
+ ScriptInterpreter::ExecuteScriptOptions()
+ .SetEnableIO(false)
+ .SetSetLLDBGlobals(false));
+ if (error.Fail())
+ return false;
+
+ // if we are here, everything worked
+ // call __lldb_init_module(debugger,dict)
+ if (!g_swig_call_module_init(basename.c_str(), m_dictionary_name.c_str(),
+ debugger_sp)) {
+ error.SetErrorString("calling __lldb_init_module failed");
+ return false;
+ }
+
+ if (module_sp) {
+ // everything went just great, now set the module object
+ command_stream.Clear();
+ command_stream.Printf("%s", basename.c_str());
+ void *module_pyobj = nullptr;
+ if (ExecuteOneLineWithReturn(
+ command_stream.GetData(),
+ ScriptInterpreter::eScriptReturnTypeOpaqueObject,
+ &module_pyobj) &&
+ module_pyobj)
+ module_sp->reset(new StructuredPythonObject(module_pyobj));
}
-
- if (!g_swig_call_module_init)
- {
- error.SetErrorString("internal helper function missing");
- return false;
- }
-
- lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
- {
- FileSpec target_file(pathname, true);
- std::string basename(target_file.GetFilename().GetCString());
-
- StreamString command_stream;
-
- // Before executing Python code, lock the GIL.
- Locker py_lock (this,
- Locker::AcquireLock | (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN,
- Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0));
-
- if (target_file.GetFileType() == FileSpec::eFileTypeInvalid ||
- target_file.GetFileType() == FileSpec::eFileTypeUnknown)
- {
- // if not a valid file of any sort, check if it might be a filename still
- // dot can't be used but / and \ can, and if either is found, reject
- if (strchr(pathname,'\\') || strchr(pathname,'/'))
- {
- error.SetErrorString("invalid pathname");
- return false;
- }
- basename = pathname; // not a filename, probably a package of some sort, let it go through
- }
- else if (target_file.GetFileType() == FileSpec::eFileTypeDirectory ||
- target_file.GetFileType() == FileSpec::eFileTypeRegular ||
- target_file.GetFileType() == FileSpec::eFileTypeSymbolicLink)
- {
- std::string directory = target_file.GetDirectory().GetCString();
- replace_all(directory, "\\", "\\\\");
- replace_all(directory, "'", "\\'");
-
- // now make sure that Python has "directory" in the search path
- StreamString command_stream;
- command_stream.Printf("if not (sys.path.__contains__('%s')):\n sys.path.insert(1,'%s');\n\n",
- directory.c_str(),
- directory.c_str());
- bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)).Success();
- if (!syspath_retval)
- {
- error.SetErrorString("Python sys.path handling failed");
- return false;
- }
+ return true;
+ }
+}
- // strip .py or .pyc extension
- ConstString extension = target_file.GetFileNameExtension();
- if (extension)
- {
- if (::strcmp(extension.GetCString(), "py") == 0)
- basename.resize(basename.length()-3);
- else if(::strcmp(extension.GetCString(), "pyc") == 0)
- basename.resize(basename.length()-4);
- }
- }
- else
- {
- error.SetErrorString("no known way to import this module specification");
- return false;
- }
-
- // check if the module is already import-ed
- command_stream.Clear();
- command_stream.Printf("sys.modules.__contains__('%s')",basename.c_str());
- bool does_contain = false;
- // this call will succeed if the module was ever imported in any Debugger in the lifetime of the process
- // in which this LLDB framework is living
- bool was_imported_globally = (ExecuteOneLineWithReturn(command_stream.GetData(),
- ScriptInterpreterPython::eScriptReturnTypeBool,
- &does_contain,
- ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && does_contain);
- // this call will fail if the module was not imported in this Debugger before
- command_stream.Clear();
- command_stream.Printf("sys.getrefcount(%s)",basename.c_str());
- bool was_imported_locally = GetSessionDictionary().GetItemForKey(PythonString(basename)).IsAllocated();
-
- bool was_imported = (was_imported_globally || was_imported_locally);
-
- if (was_imported == true && can_reload == false)
- {
- error.SetErrorString("module already imported");
- return false;
- }
+bool ScriptInterpreterPython::IsReservedWord(const char *word) {
+ if (!word || !word[0])
+ return false;
- // now actually do the import
- command_stream.Clear();
-
- if (was_imported)
- {
- if (!was_imported_locally)
- command_stream.Printf("import %s ; reload_module(%s)",basename.c_str(),basename.c_str());
- else
- command_stream.Printf("reload_module(%s)",basename.c_str());
- }
- else
- command_stream.Printf("import %s", basename.c_str());
+ llvm::StringRef word_sr(word);
- error = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false));
- if (error.Fail())
- return false;
-
- // if we are here, everything worked
- // call __lldb_init_module(debugger,dict)
- if (!g_swig_call_module_init (basename.c_str(),
- m_dictionary_name.c_str(),
- debugger_sp))
- {
- error.SetErrorString("calling __lldb_init_module failed");
- return false;
- }
-
- if (module_sp)
- {
- // everything went just great, now set the module object
- command_stream.Clear();
- command_stream.Printf("%s",basename.c_str());
- void* module_pyobj = nullptr;
- if (ExecuteOneLineWithReturn(command_stream.GetData(),ScriptInterpreter::eScriptReturnTypeOpaqueObject,&module_pyobj) && module_pyobj)
- module_sp->reset(new StructuredPythonObject(module_pyobj));
- }
-
- return true;
- }
+ // filter out a few characters that would just confuse us
+ // and that are clearly not keyword material anyway
+ if (word_sr.find_first_of("'\"") != llvm::StringRef::npos)
+ return false;
+
+ StreamString command_stream;
+ command_stream.Printf("keyword.iskeyword('%s')", word);
+ bool result;
+ ExecuteScriptOptions options;
+ options.SetEnableIO(false);
+ options.SetMaskoutErrors(true);
+ options.SetSetLLDBGlobals(false);
+ if (ExecuteOneLineWithReturn(command_stream.GetData(),
+ ScriptInterpreter::eScriptReturnTypeBool,
+ &result, options))
+ return result;
+ return false;
}
-bool
-ScriptInterpreterPython::IsReservedWord (const char* word)
-{
- if (!word || !word[0])
- return false;
-
- llvm::StringRef word_sr(word);
+ScriptInterpreterPython::SynchronicityHandler::SynchronicityHandler(
+ lldb::DebuggerSP debugger_sp, ScriptedCommandSynchronicity synchro)
+ : m_debugger_sp(debugger_sp), m_synch_wanted(synchro),
+ m_old_asynch(debugger_sp->GetAsyncExecution()) {
+ if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous)
+ m_debugger_sp->SetAsyncExecution(false);
+ else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous)
+ m_debugger_sp->SetAsyncExecution(true);
+}
+
+ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler() {
+ if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)
+ m_debugger_sp->SetAsyncExecution(m_old_asynch);
+}
+
+bool ScriptInterpreterPython::RunScriptBasedCommand(
+ const char *impl_function, const char *args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject &cmd_retobj, Error &error,
+ const lldb_private::ExecutionContext &exe_ctx) {
+ if (!impl_function) {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
- // filter out a few characters that would just confuse us
- // and that are clearly not keyword material anyway
- if (word_sr.find_first_of("'\"") != llvm::StringRef::npos)
- return false;
-
- StreamString command_stream;
- command_stream.Printf("keyword.iskeyword('%s')", word);
- bool result;
- ExecuteScriptOptions options;
- options.SetEnableIO(false);
- options.SetMaskoutErrors(true);
- options.SetSetLLDBGlobals(false);
- if (ExecuteOneLineWithReturn(command_stream.GetData(), ScriptInterpreter::eScriptReturnTypeBool, &result, options))
- return result;
+ if (!g_swig_call_command) {
+ error.SetErrorString("no helper function to run scripted commands");
return false;
-}
+ }
-ScriptInterpreterPython::SynchronicityHandler::SynchronicityHandler (lldb::DebuggerSP debugger_sp,
- ScriptedCommandSynchronicity synchro) :
- m_debugger_sp(debugger_sp),
- m_synch_wanted(synchro),
- m_old_asynch(debugger_sp->GetAsyncExecution())
-{
- if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous)
- m_debugger_sp->SetAsyncExecution(false);
- else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous)
- m_debugger_sp->SetAsyncExecution(true);
-}
-
-ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler()
-{
- if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)
- m_debugger_sp->SetAsyncExecution(m_old_asynch);
-}
-
-bool
-ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function,
- const char* args,
- ScriptedCommandSynchronicity synchronicity,
- lldb_private::CommandReturnObject& cmd_retobj,
- Error& error,
- const lldb_private::ExecutionContext& exe_ctx)
-{
- if (!impl_function)
- {
- error.SetErrorString("no function to execute");
- return false;
- }
-
- if (!g_swig_call_command)
- {
- error.SetErrorString("no helper function to run scripted commands");
- return false;
- }
-
- lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
- lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));
-
- if (!debugger_sp.get())
- {
- error.SetErrorString("invalid Debugger pointer");
- return false;
- }
-
- bool ret_val = false;
-
- std::string err_msg;
+ lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));
- {
- Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
- Locker::FreeLock | Locker::TearDownSession);
-
- SynchronicityHandler synch_handler(debugger_sp,
- synchronicity);
-
- ret_val = g_swig_call_command (impl_function,
- m_dictionary_name.c_str(),
- debugger_sp,
- args,
- cmd_retobj,
- exe_ctx_ref_sp);
- }
-
- if (!ret_val)
- error.SetErrorString("unable to execute script function");
- else
- error.Clear();
-
- return ret_val;
-}
+ if (!debugger_sp.get()) {
+ error.SetErrorString("invalid Debugger pointer");
+ return false;
+ }
-bool
-ScriptInterpreterPython::RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp,
- const char* args,
- ScriptedCommandSynchronicity synchronicity,
- lldb_private::CommandReturnObject& cmd_retobj,
- Error& error,
- const lldb_private::ExecutionContext& exe_ctx)
-{
- if (!impl_obj_sp || !impl_obj_sp->IsValid())
- {
- error.SetErrorString("no function to execute");
- return false;
- }
-
- if (!g_swig_call_command_object)
- {
- error.SetErrorString("no helper function to run scripted commands");
- return false;
- }
-
- lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
- lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));
-
- if (!debugger_sp.get())
- {
- error.SetErrorString("invalid Debugger pointer");
- return false;
- }
-
- bool ret_val = false;
-
- std::string err_msg;
-
- {
- Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
- Locker::FreeLock | Locker::TearDownSession);
-
- SynchronicityHandler synch_handler(debugger_sp,
- synchronicity);
-
- ret_val = g_swig_call_command_object (impl_obj_sp->GetValue(),
- debugger_sp,
- args,
- cmd_retobj,
- exe_ctx_ref_sp);
- }
-
- if (!ret_val)
- error.SetErrorString("unable to execute script function");
- else
- error.Clear();
+ bool ret_val = false;
- return ret_val;
+ std::string err_msg;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession |
+ (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
+ Locker::FreeLock | Locker::TearDownSession);
+
+ SynchronicityHandler synch_handler(debugger_sp, synchronicity);
+
+ ret_val =
+ g_swig_call_command(impl_function, m_dictionary_name.c_str(),
+ debugger_sp, args, cmd_retobj, exe_ctx_ref_sp);
+ }
+
+ if (!ret_val)
+ error.SetErrorString("unable to execute script function");
+ else
+ error.Clear();
+
+ return ret_val;
+}
+
+bool ScriptInterpreterPython::RunScriptBasedCommand(
+ StructuredData::GenericSP impl_obj_sp, const char *args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject &cmd_retobj, Error &error,
+ const lldb_private::ExecutionContext &exe_ctx) {
+ if (!impl_obj_sp || !impl_obj_sp->IsValid()) {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+
+ if (!g_swig_call_command_object) {
+ error.SetErrorString("no helper function to run scripted commands");
+ return false;
+ }
+
+ lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));
+
+ if (!debugger_sp.get()) {
+ error.SetErrorString("invalid Debugger pointer");
+ return false;
+ }
+
+ bool ret_val = false;
+
+ std::string err_msg;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession |
+ (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
+ Locker::FreeLock | Locker::TearDownSession);
+
+ SynchronicityHandler synch_handler(debugger_sp, synchronicity);
+
+ ret_val = g_swig_call_command_object(impl_obj_sp->GetValue(), debugger_sp,
+ args, cmd_retobj, exe_ctx_ref_sp);
+ }
+
+ if (!ret_val)
+ error.SetErrorString("unable to execute script function");
+ else
+ error.Clear();
+
+ return ret_val;
}
// in Python, a special attribute __doc__ contains the docstring
// for an object (function, method, class, ...) if any is defined
// Otherwise, the attribute's value is None
-bool
-ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& dest)
-{
- dest.clear();
- if (!item || !*item)
- return false;
- std::string command(item);
- command += ".__doc__";
-
- char* result_ptr = nullptr; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully
-
- if (ExecuteOneLineWithReturn (command.c_str(),
- ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
- &result_ptr,
- ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)))
- {
- if (result_ptr)
- dest.assign(result_ptr);
- return true;
- }
- else
- {
- StreamString str_stream;
- str_stream.Printf("Function %s was not found. Containing module might be missing.",item);
- dest.assign(str_stream.GetData());
- return false;
- }
+bool ScriptInterpreterPython::GetDocumentationForItem(const char *item,
+ std::string &dest) {
+ dest.clear();
+ if (!item || !*item)
+ return false;
+ std::string command(item);
+ command += ".__doc__";
+
+ char *result_ptr = nullptr; // Python is going to point this to valid data if
+ // ExecuteOneLineWithReturn returns successfully
+
+ if (ExecuteOneLineWithReturn(
+ command.c_str(), ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
+ &result_ptr,
+ ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false))) {
+ if (result_ptr)
+ dest.assign(result_ptr);
+ return true;
+ } else {
+ StreamString str_stream;
+ str_stream.Printf(
+ "Function %s was not found. Containing module might be missing.", item);
+ dest.assign(str_stream.GetData());
+ return false;
+ }
}
-bool
-ScriptInterpreterPython::GetShortHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp,
- std::string& dest)
-{
- bool got_string = false;
- dest.clear();
-
- Locker py_lock (this,
- Locker::AcquireLock | Locker::NoSTDIN,
- Locker::FreeLock);
-
- static char callee_name[] = "get_short_help";
-
- if (!cmd_obj_sp)
- return false;
+bool ScriptInterpreterPython::GetShortHelpForCommandObject(
+ StructuredData::GenericSP cmd_obj_sp, std::string &dest) {
+ bool got_string = false;
+ dest.clear();
- PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
- if (!implementor.IsAllocated())
- return false;
+ static char callee_name[] = "get_short_help";
- PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+ if (!cmd_obj_sp)
+ return false;
- if (PyErr_Occurred())
- PyErr_Clear();
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)cmd_obj_sp->GetValue());
- if (!pmeth.IsAllocated())
- return false;
-
- if (PyCallable_Check(pmeth.get()) == 0)
- {
- if (PyErr_Occurred())
- PyErr_Clear();
- return false;
- }
-
- if (PyErr_Occurred())
- PyErr_Clear();
-
- // right now we know this function exists and is callable..
- PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+ if (!implementor.IsAllocated())
+ return false;
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
- // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return false;
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
if (PyErr_Occurred())
- {
- PyErr_Print();
- PyErr_Clear();
- }
+ PyErr_Clear();
+ return false;
+ }
- if (py_return.IsAllocated() && PythonString::Check(py_return.get()))
- {
- PythonString py_string(PyRefType::Borrowed, py_return.get());
- llvm::StringRef return_data(py_string.GetString());
- dest.assign(return_data.data(), return_data.size());
- got_string = true;
- }
- return got_string;
-}
-
-uint32_t
-ScriptInterpreterPython::GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp)
-{
- uint32_t result = 0;
-
- Locker py_lock (this,
- Locker::AcquireLock | Locker::NoSTDIN,
- Locker::FreeLock);
-
- static char callee_name[] = "get_flags";
-
- if (!cmd_obj_sp)
- return result;
+ if (PyErr_Occurred())
+ PyErr_Clear();
- PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
+ // right now we know this function exists and is callable..
+ PythonObject py_return(
+ PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name, nullptr));
- if (!implementor.IsAllocated())
- return result;
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
- PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+ if (py_return.IsAllocated() && PythonString::Check(py_return.get())) {
+ PythonString py_string(PyRefType::Borrowed, py_return.get());
+ llvm::StringRef return_data(py_string.GetString());
+ dest.assign(return_data.data(), return_data.size());
+ got_string = true;
+ }
+ return got_string;
+}
- if (PyErr_Occurred())
- PyErr_Clear();
+uint32_t ScriptInterpreterPython::GetFlagsForCommandObject(
+ StructuredData::GenericSP cmd_obj_sp) {
+ uint32_t result = 0;
- if (!pmeth.IsAllocated())
- return result;
-
- if (PyCallable_Check(pmeth.get()) == 0)
- {
- if (PyErr_Occurred())
- PyErr_Clear();
- return result;
- }
-
- if (PyErr_Occurred())
- PyErr_Clear();
-
- // right now we know this function exists and is callable..
- PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
- // if it fails, print the error but otherwise go on
- if (PyErr_Occurred())
- {
- PyErr_Print();
- PyErr_Clear();
- }
+ static char callee_name[] = "get_flags";
- if (py_return.IsAllocated() && PythonInteger::Check(py_return.get()))
- {
- PythonInteger int_value(PyRefType::Borrowed, py_return.get());
- result = int_value.GetInteger();
- }
-
+ if (!cmd_obj_sp)
return result;
-}
-bool
-ScriptInterpreterPython::GetLongHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp,
- std::string& dest)
-{
- bool got_string = false;
- dest.clear();
-
- Locker py_lock (this,
- Locker::AcquireLock | Locker::NoSTDIN,
- Locker::FreeLock);
-
- static char callee_name[] = "get_long_help";
-
- if (!cmd_obj_sp)
- return false;
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return result;
- PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
- if (!implementor.IsAllocated())
- return false;
+ if (PyErr_Occurred())
+ PyErr_Clear();
- PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+ if (!pmeth.IsAllocated())
+ return result;
+ if (PyCallable_Check(pmeth.get()) == 0) {
if (PyErr_Occurred())
- PyErr_Clear();
+ PyErr_Clear();
+ return result;
+ }
- if (!pmeth.IsAllocated())
- return false;
-
- if (PyCallable_Check(pmeth.get()) == 0)
- {
- if (PyErr_Occurred())
- PyErr_Clear();
-
- return false;
- }
-
- if (PyErr_Occurred())
- PyErr_Clear();
-
- // right now we know this function exists and is callable..
- PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+ if (PyErr_Occurred())
+ PyErr_Clear();
- // if it fails, print the error but otherwise go on
+ // right now we know this function exists and is callable..
+ PythonObject py_return(
+ PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (py_return.IsAllocated() && PythonInteger::Check(py_return.get())) {
+ PythonInteger int_value(PyRefType::Borrowed, py_return.get());
+ result = int_value.GetInteger();
+ }
+
+ return result;
+}
+
+bool ScriptInterpreterPython::GetLongHelpForCommandObject(
+ StructuredData::GenericSP cmd_obj_sp, std::string &dest) {
+ bool got_string = false;
+ dest.clear();
+
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
+
+ static char callee_name[] = "get_long_help";
+
+ if (!cmd_obj_sp)
+ return false;
+
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return false;
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return false;
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
if (PyErr_Occurred())
- {
- PyErr_Print();
- PyErr_Clear();
- }
+ PyErr_Clear();
- if (py_return.IsAllocated() && PythonString::Check(py_return.get()))
- {
- PythonString str(PyRefType::Borrowed, py_return.get());
- llvm::StringRef str_data(str.GetString());
- dest.assign(str_data.data(), str_data.size());
- got_string = true;
- }
-
- return got_string;
+ return false;
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(
+ PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (py_return.IsAllocated() && PythonString::Check(py_return.get())) {
+ PythonString str(PyRefType::Borrowed, py_return.get());
+ llvm::StringRef str_data(str.GetString());
+ dest.assign(str_data.data(), str_data.size());
+ got_string = true;
+ }
+
+ return got_string;
}
std::unique_ptr<ScriptInterpreterLocker>
-ScriptInterpreterPython::AcquireInterpreterLock ()
-{
- std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(this,
- Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
- Locker::FreeLock | Locker::TearDownSession));
- return py_lock;
-}
-
-void
-ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callback,
- SWIGBreakpointCallbackFunction swig_breakpoint_callback,
- SWIGWatchpointCallbackFunction swig_watchpoint_callback,
- SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
- SWIGPythonCreateSyntheticProvider swig_synthetic_script,
- SWIGPythonCreateCommandObject swig_create_cmd,
- SWIGPythonCalculateNumChildren swig_calc_children,
- SWIGPythonGetChildAtIndex swig_get_child_index,
- SWIGPythonGetIndexOfChildWithName swig_get_index_child,
- SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue ,
- SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
- SWIGPythonUpdateSynthProviderInstance swig_update_provider,
- SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
- SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
- SWIGPythonCallCommand swig_call_command,
- SWIGPythonCallCommandObject swig_call_command_object,
- SWIGPythonCallModuleInit swig_call_module_init,
- SWIGPythonCreateOSPlugin swig_create_os_plugin,
- SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
- SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
- SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
- SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
- SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
- SWIGPython_GetDynamicSetting swig_plugin_get,
- SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
- SWIGPythonCallThreadPlan swig_call_thread_plan)
-{
- g_swig_init_callback = swig_init_callback;
- g_swig_breakpoint_callback = swig_breakpoint_callback;
- g_swig_watchpoint_callback = swig_watchpoint_callback;
- g_swig_typescript_callback = swig_typescript_callback;
- g_swig_synthetic_script = swig_synthetic_script;
- g_swig_create_cmd = swig_create_cmd;
- g_swig_calc_children = swig_calc_children;
- g_swig_get_child_index = swig_get_child_index;
- g_swig_get_index_child = swig_get_index_child;
- g_swig_cast_to_sbvalue = swig_cast_to_sbvalue;
- g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue;
- g_swig_update_provider = swig_update_provider;
- g_swig_mighthavechildren_provider = swig_mighthavechildren_provider;
- g_swig_getvalue_provider = swig_getvalue_provider;
- g_swig_call_command = swig_call_command;
- g_swig_call_command_object = swig_call_command_object;
- g_swig_call_module_init = swig_call_module_init;
- g_swig_create_os_plugin = swig_create_os_plugin;
- g_swig_run_script_keyword_process = swig_run_script_keyword_process;
- g_swig_run_script_keyword_thread = swig_run_script_keyword_thread;
- g_swig_run_script_keyword_target = swig_run_script_keyword_target;
- g_swig_run_script_keyword_frame = swig_run_script_keyword_frame;
- g_swig_run_script_keyword_value = swig_run_script_keyword_value;
- g_swig_plugin_get = swig_plugin_get;
- g_swig_thread_plan_script = swig_thread_plan_script;
- g_swig_call_thread_plan = swig_call_thread_plan;
-}
-
-void
-ScriptInterpreterPython::InitializePrivate ()
-{
- if (g_initialized)
- return;
-
- g_initialized = true;
-
- Timer scoped_timer (LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
-
- // RAII-based initialization which correctly handles multiple-initialization, version-
- // specific differences among Python 2 and Python 3, and saving and restoring various
- // other pieces of state that can get mucked with during initialization.
- InitializePythonRAII initialize_guard;
-
- if (g_swig_init_callback)
- g_swig_init_callback ();
-
- // Update the path python uses to search for modules to include the current directory.
-
- PyRun_SimpleString ("import sys");
- AddToSysPath(AddLocation::End, ".");
-
- FileSpec file_spec;
- // Don't denormalize paths when calling file_spec.GetPath(). On platforms that use
- // a backslash as the path separator, this will result in executing python code containing
- // paths with unescaped backslashes. But Python also accepts forward slashes, so to make
- // life easier we just use that.
- if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec))
- AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
- if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec))
- AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
-
- PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line");
-}
-
-void
-ScriptInterpreterPython::AddToSysPath(AddLocation location, std::string path)
-{
- std::string path_copy;
-
- std::string statement;
- if (location == AddLocation::Beginning)
- {
- statement.assign("sys.path.insert(0,\"");
- statement.append (path);
- statement.append ("\")");
- }
- else
- {
- statement.assign("sys.path.append(\"");
- statement.append(path);
- statement.append("\")");
- }
- PyRun_SimpleString (statement.c_str());
+ScriptInterpreterPython::AcquireInterpreterLock() {
+ std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(
+ this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
+ Locker::FreeLock | Locker::TearDownSession));
+ return py_lock;
+}
+
+void ScriptInterpreterPython::InitializeInterpreter(
+ SWIGInitCallback swig_init_callback,
+ SWIGBreakpointCallbackFunction swig_breakpoint_callback,
+ SWIGWatchpointCallbackFunction swig_watchpoint_callback,
+ SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
+ SWIGPythonCreateSyntheticProvider swig_synthetic_script,
+ SWIGPythonCreateCommandObject swig_create_cmd,
+ SWIGPythonCalculateNumChildren swig_calc_children,
+ SWIGPythonGetChildAtIndex swig_get_child_index,
+ SWIGPythonGetIndexOfChildWithName swig_get_index_child,
+ SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue,
+ SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
+ SWIGPythonUpdateSynthProviderInstance swig_update_provider,
+ SWIGPythonMightHaveChildrenSynthProviderInstance
+ swig_mighthavechildren_provider,
+ SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
+ SWIGPythonCallCommand swig_call_command,
+ SWIGPythonCallCommandObject swig_call_command_object,
+ SWIGPythonCallModuleInit swig_call_module_init,
+ SWIGPythonCreateOSPlugin swig_create_os_plugin,
+ SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
+ SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
+ SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
+ SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
+ SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
+ SWIGPython_GetDynamicSetting swig_plugin_get,
+ SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+ SWIGPythonCallThreadPlan swig_call_thread_plan) {
+ g_swig_init_callback = swig_init_callback;
+ g_swig_breakpoint_callback = swig_breakpoint_callback;
+ g_swig_watchpoint_callback = swig_watchpoint_callback;
+ g_swig_typescript_callback = swig_typescript_callback;
+ g_swig_synthetic_script = swig_synthetic_script;
+ g_swig_create_cmd = swig_create_cmd;
+ g_swig_calc_children = swig_calc_children;
+ g_swig_get_child_index = swig_get_child_index;
+ g_swig_get_index_child = swig_get_index_child;
+ g_swig_cast_to_sbvalue = swig_cast_to_sbvalue;
+ g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue;
+ g_swig_update_provider = swig_update_provider;
+ g_swig_mighthavechildren_provider = swig_mighthavechildren_provider;
+ g_swig_getvalue_provider = swig_getvalue_provider;
+ g_swig_call_command = swig_call_command;
+ g_swig_call_command_object = swig_call_command_object;
+ g_swig_call_module_init = swig_call_module_init;
+ g_swig_create_os_plugin = swig_create_os_plugin;
+ g_swig_run_script_keyword_process = swig_run_script_keyword_process;
+ g_swig_run_script_keyword_thread = swig_run_script_keyword_thread;
+ g_swig_run_script_keyword_target = swig_run_script_keyword_target;
+ g_swig_run_script_keyword_frame = swig_run_script_keyword_frame;
+ g_swig_run_script_keyword_value = swig_run_script_keyword_value;
+ g_swig_plugin_get = swig_plugin_get;
+ g_swig_thread_plan_script = swig_thread_plan_script;
+ g_swig_call_thread_plan = swig_call_thread_plan;
}
+void ScriptInterpreterPython::InitializePrivate() {
+ if (g_initialized)
+ return;
+
+ g_initialized = true;
+
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+
+ // RAII-based initialization which correctly handles multiple-initialization,
+ // version-
+ // specific differences among Python 2 and Python 3, and saving and restoring
+ // various
+ // other pieces of state that can get mucked with during initialization.
+ InitializePythonRAII initialize_guard;
+
+ if (g_swig_init_callback)
+ g_swig_init_callback();
+
+ // Update the path python uses to search for modules to include the current
+ // directory.
+
+ PyRun_SimpleString("import sys");
+ AddToSysPath(AddLocation::End, ".");
+
+ FileSpec file_spec;
+ // Don't denormalize paths when calling file_spec.GetPath(). On platforms
+ // that use
+ // a backslash as the path separator, this will result in executing python
+ // code containing
+ // paths with unescaped backslashes. But Python also accepts forward slashes,
+ // so to make
+ // life easier we just use that.
+ if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec))
+ AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec))
+ AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
+
+ PyRun_SimpleString("sys.dont_write_bytecode = 1; import "
+ "lldb.embedded_interpreter; from "
+ "lldb.embedded_interpreter import run_python_interpreter; "
+ "from lldb.embedded_interpreter import run_one_line");
+}
+
+void ScriptInterpreterPython::AddToSysPath(AddLocation location,
+ std::string path) {
+ std::string path_copy;
+
+ std::string statement;
+ if (location == AddLocation::Beginning) {
+ statement.assign("sys.path.insert(0,\"");
+ statement.append(path);
+ statement.append("\")");
+ } else {
+ statement.assign("sys.path.append(\"");
+ statement.append(path);
+ statement.append("\")");
+ }
+ PyRun_SimpleString(statement.c_str());
+}
-//void
-//ScriptInterpreterPython::Terminate ()
+// void
+// ScriptInterpreterPython::Terminate ()
//{
-// // We are intentionally NOT calling Py_Finalize here (this would be the logical place to call it). Calling
-// // Py_Finalize here causes test suite runs to seg fault: The test suite runs in Python. It registers
-// // SBDebugger::Terminate to be called 'at_exit'. When the test suite Python harness finishes up, it calls
-// // Py_Finalize, which calls all the 'at_exit' registered functions. SBDebugger::Terminate calls Debugger::Terminate,
-// // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate, which calls
-// // ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we end up with Py_Finalize being called from
+// // We are intentionally NOT calling Py_Finalize here (this would be the
+// logical place to call it). Calling
+// // Py_Finalize here causes test suite runs to seg fault: The test suite
+// runs in Python. It registers
+// // SBDebugger::Terminate to be called 'at_exit'. When the test suite
+// Python harness finishes up, it calls
+// // Py_Finalize, which calls all the 'at_exit' registered functions.
+// SBDebugger::Terminate calls Debugger::Terminate,
+// // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate,
+// which calls
+// // ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we
+// end up with Py_Finalize being called from
// // within Py_Finalize, which results in a seg fault.
// //
-// // Since this function only gets called when lldb is shutting down and going away anyway, the fact that we don't
-// // actually call Py_Finalize should not cause any problems (everything should shut down/go away anyway when the
+// // Since this function only gets called when lldb is shutting down and
+// going away anyway, the fact that we don't
+// // actually call Py_Finalize should not cause any problems (everything
+// should shut down/go away anyway when the
// // process exits).
// //
//// Py_Finalize ();
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h Tue Sep 6 15:57:50 2016
@@ -24,587 +24,530 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
#include "PythonDataObjects.h"
#include "lldb/Core/IOHandler.h"
-#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Host/Terminal.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/lldb-private.h"
class IOHandlerPythonInterpreter;
namespace lldb_private {
-
-class ScriptInterpreterPython :
- public ScriptInterpreter,
- public IOHandlerDelegateMultiline
-{
+
+class ScriptInterpreterPython : public ScriptInterpreter,
+ public IOHandlerDelegateMultiline {
public:
#if PY_MAJOR_VERSION >= 3
- typedef PyObject*(*SWIGInitCallback) (void);
+ typedef PyObject *(*SWIGInitCallback)(void);
#else
- typedef void(*SWIGInitCallback) (void);
+ typedef void (*SWIGInitCallback)(void);
#endif
- typedef bool (*SWIGBreakpointCallbackFunction) (const char *python_function_name,
- const char *session_dictionary_name,
- const lldb::StackFrameSP& frame_sp,
- const lldb::BreakpointLocationSP &bp_loc_sp);
-
- typedef bool (*SWIGWatchpointCallbackFunction) (const char *python_function_name,
- const char *session_dictionary_name,
- const lldb::StackFrameSP& frame_sp,
- const lldb::WatchpointSP &wp_sp);
-
- typedef bool (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name,
- void *session_dictionary,
- const lldb::ValueObjectSP& valobj_sp,
- void** pyfunct_wrapper,
- const lldb::TypeSummaryOptionsSP& options,
- std::string& retval);
-
- typedef void* (*SWIGPythonCreateSyntheticProvider) (const char *python_class_name,
- const char *session_dictionary_name,
- const lldb::ValueObjectSP& valobj_sp);
-
- typedef void* (*SWIGPythonCreateCommandObject) (const char *python_class_name,
- const char *session_dictionary_name,
- const lldb::DebuggerSP debugger_sp);
-
- typedef void* (*SWIGPythonCreateScriptedThreadPlan) (const char *python_class_name,
- const char *session_dictionary_name,
- const lldb::ThreadPlanSP& thread_plan_sp);
-
- typedef bool (*SWIGPythonCallThreadPlan) (void *implementor, const char *method_name, Event *event_sp, bool &got_error);
-
- typedef void* (*SWIGPythonCreateOSPlugin) (const char *python_class_name,
- const char *session_dictionary_name,
- const lldb::ProcessSP& process_sp);
-
- typedef size_t (*SWIGPythonCalculateNumChildren) (void *implementor, uint32_t max);
-
- typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx);
-
- typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name);
-
- typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data);
-
- typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue) (void* data);
-
- typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data);
-
- typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data);
-
- typedef void* (*SWIGPythonGetValueSynthProviderInstance) (void *implementor);
-
- typedef bool (*SWIGPythonCallCommand) (const char *python_function_name,
- const char *session_dictionary_name,
- lldb::DebuggerSP& debugger,
- const char* args,
- lldb_private::CommandReturnObject& cmd_retobj,
- lldb::ExecutionContextRefSP exe_ctx_ref_sp);
-
- typedef bool (*SWIGPythonCallCommandObject) (void *implementor,
- lldb::DebuggerSP& debugger,
- const char* args,
- lldb_private::CommandReturnObject& cmd_retobj,
- lldb::ExecutionContextRefSP exe_ctx_ref_sp);
-
- typedef bool (*SWIGPythonCallModuleInit) (const char *python_module_name,
- const char *session_dictionary_name,
- lldb::DebuggerSP& debugger);
-
- typedef bool (*SWIGPythonScriptKeyword_Process) (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::ProcessSP& process,
- std::string& output);
-
- typedef bool (*SWIGPythonScriptKeyword_Thread) (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::ThreadSP& thread,
- std::string& output);
-
- typedef bool (*SWIGPythonScriptKeyword_Target) (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::TargetSP& target,
- std::string& output);
-
- typedef bool (*SWIGPythonScriptKeyword_Frame) (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::StackFrameSP& frame,
- std::string& output);
-
- typedef bool (*SWIGPythonScriptKeyword_Value) (const char* python_function_name,
- const char* session_dictionary_name,
- lldb::ValueObjectSP& value,
- std::string& output);
-
- typedef void* (*SWIGPython_GetDynamicSetting) (void* module,
- const char* setting,
- const lldb::TargetSP& target_sp);
-
- friend class ::IOHandlerPythonInterpreter;
-
- ScriptInterpreterPython (CommandInterpreter &interpreter);
-
- ~ScriptInterpreterPython() override;
-
- bool
- Interrupt() override;
-
- bool
- ExecuteOneLine (const char *command,
- CommandReturnObject *result,
- const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
-
- void
- ExecuteInterpreterLoop () override;
-
- bool
- ExecuteOneLineWithReturn (const char *in_string,
- ScriptInterpreter::ScriptReturnType return_type,
- void *ret_value,
- const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
-
- lldb_private::Error
- ExecuteMultipleLines (const char *in_string,
- const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
-
- Error
- ExportFunctionDefinitionToInterpreter (StringList &function_def) override;
-
- bool
- GenerateTypeScriptFunction(StringList &input, std::string& output, const void* name_token = nullptr) override;
-
- bool
- GenerateTypeSynthClass(StringList &input, std::string& output, const void* name_token = nullptr) override;
-
- bool
- GenerateTypeSynthClass(const char* oneliner, std::string& output, const void* name_token = nullptr) override;
-
- // use this if the function code is just a one-liner script
- bool
- GenerateTypeScriptFunction(const char* oneliner, std::string& output, const void* name_token = nullptr) override;
-
- bool
- GenerateScriptAliasFunction (StringList &input, std::string& output) override;
-
- StructuredData::ObjectSP CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj) override;
-
- StructuredData::GenericSP CreateScriptCommandObject (const char *class_name) override;
-
- StructuredData::ObjectSP CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan) override;
-
- bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override;
-
- bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override;
-
- bool ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp, bool &script_error) override;
-
- lldb::StateType ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) override;
-
- StructuredData::GenericSP OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp) override;
-
- StructuredData::DictionarySP OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
-
- StructuredData::ArraySP OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
-
- StructuredData::StringSP OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t thread_id) override;
-
- StructuredData::DictionarySP OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid,
- lldb::addr_t context) override;
-
- StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error) override;
-
- StructuredData::DictionarySP GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name,
- lldb_private::Error &error) override;
-
- size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor, uint32_t max) override;
-
- lldb::ValueObjectSP GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) override;
-
- int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor, const char *child_name) override;
-
- bool UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor) override;
-
- bool MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor) override;
-
- lldb::ValueObjectSP GetSyntheticValue(const StructuredData::ObjectSP &implementor) override;
-
- ConstString GetSyntheticTypeName (const StructuredData::ObjectSP &implementor) override;
-
- bool
- RunScriptBasedCommand(const char* impl_function,
- const char* args,
- ScriptedCommandSynchronicity synchronicity,
- lldb_private::CommandReturnObject& cmd_retobj,
- Error& error,
- const lldb_private::ExecutionContext& exe_ctx) override;
-
- bool
- RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp,
- const char* args,
- ScriptedCommandSynchronicity synchronicity,
- lldb_private::CommandReturnObject& cmd_retobj,
- Error& error,
- const lldb_private::ExecutionContext& exe_ctx) override;
-
- Error
- GenerateFunction(const char *signature, const StringList &input) override;
-
- Error
- GenerateBreakpointCommandCallbackData (StringList &input, std::string& output) override;
-
- bool
- GenerateWatchpointCommandCallbackData (StringList &input, std::string& output) override;
-
-// static size_t
-// GenerateBreakpointOptionsCommandCallback (void *baton,
-// InputReader &reader,
-// lldb::InputReaderAction notification,
-// const char *bytes,
-// size_t bytes_len);
-//
-// static size_t
-// GenerateWatchpointOptionsCommandCallback (void *baton,
-// InputReader &reader,
-// lldb::InputReaderAction notification,
-// const char *bytes,
-// size_t bytes_len);
-
- static bool
- BreakpointCallbackFunction (void *baton,
- StoppointCallbackContext *context,
- lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id);
-
- static bool
- WatchpointCallbackFunction (void *baton,
- StoppointCallbackContext *context,
- lldb::user_id_t watch_id);
-
- bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp,
- const TypeSummaryOptions &options, std::string &retval) override;
-
- void
- Clear () override;
-
- bool
- GetDocumentationForItem (const char* item, std::string& dest) override;
-
- bool
- GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, std::string& dest) override;
-
- uint32_t
- GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp) override;
-
- bool
- GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, std::string& dest) override;
-
- bool
- CheckObjectExists (const char* name) override
- {
- if (!name || !name[0])
- return false;
- std::string temp;
- return GetDocumentationForItem (name,temp);
- }
-
- bool
- RunScriptFormatKeyword (const char* impl_function,
- Process* process,
- std::string& output,
- Error& error) override;
-
- bool
- RunScriptFormatKeyword (const char* impl_function,
- Thread* thread,
- std::string& output,
- Error& error) override;
-
- bool
- RunScriptFormatKeyword (const char* impl_function,
- Target* target,
- std::string& output,
- Error& error) override;
-
- bool
- RunScriptFormatKeyword (const char* impl_function,
- StackFrame* frame,
- std::string& output,
- Error& error) override;
-
- bool
- RunScriptFormatKeyword (const char* impl_function,
- ValueObject* value,
- std::string& output,
- Error& error) override;
-
- bool LoadScriptingModule(const char *filename, bool can_reload, bool init_session, lldb_private::Error &error,
- StructuredData::ObjectSP *module_sp = nullptr) override;
-
- bool
- IsReservedWord (const char* word) override;
-
- std::unique_ptr<ScriptInterpreterLocker>
- AcquireInterpreterLock () override;
-
- void
- CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
- CommandReturnObject &result) override;
-
- void
- CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
- CommandReturnObject &result) override;
-
- /// Set the callback body text into the callback for the breakpoint.
- Error
- SetBreakpointCommandCallback (BreakpointOptions *bp_options,
- const char *callback_body) override;
-
- void
- SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options,
- const char *function_name) override;
-
- /// Set a one-liner as the callback for the watchpoint.
- void
- SetWatchpointCommandCallback (WatchpointOptions *wp_options,
- const char *oneliner) override;
-
- StringList
- ReadCommandInputFromUser (FILE *in_file);
-
- void ResetOutputFileHandle(FILE *new_fh) override;
-
- static void
- InitializePrivate ();
-
- static void
- InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
- SWIGBreakpointCallbackFunction swig_breakpoint_callback,
- SWIGWatchpointCallbackFunction swig_watchpoint_callback,
- SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
- SWIGPythonCreateSyntheticProvider swig_synthetic_script,
- SWIGPythonCreateCommandObject swig_create_cmd,
- SWIGPythonCalculateNumChildren swig_calc_children,
- SWIGPythonGetChildAtIndex swig_get_child_index,
- SWIGPythonGetIndexOfChildWithName swig_get_index_child,
- SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue ,
- SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
- SWIGPythonUpdateSynthProviderInstance swig_update_provider,
- SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
- SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
- SWIGPythonCallCommand swig_call_command,
- SWIGPythonCallCommandObject swig_call_command_object,
- SWIGPythonCallModuleInit swig_call_module_init,
- SWIGPythonCreateOSPlugin swig_create_os_plugin,
- SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
- SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
- SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
- SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
- SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
- SWIGPython_GetDynamicSetting swig_plugin_get,
- SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
- SWIGPythonCallThreadPlan swig_call_thread_plan);
-
- const char *
- GetDictionaryName ()
- {
- return m_dictionary_name.c_str();
- }
-
- PyThreadState *
- GetThreadState()
- {
- return m_command_thread_state;
- }
-
- void
- SetThreadState (PyThreadState *s)
- {
- if (s)
- m_command_thread_state = s;
- }
-
- //----------------------------------------------------------------------
- // IOHandlerDelegate
- //----------------------------------------------------------------------
- void
- IOHandlerActivated (IOHandler &io_handler) override;
-
- void
- IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override;
-
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb::ScriptInterpreterSP
- CreateInstance(CommandInterpreter &interpreter);
-
- static lldb_private::ConstString
- GetPluginNameStatic();
-
- static const char *
- GetPluginDescriptionStatic();
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString
- GetPluginName() override;
-
- uint32_t
- GetPluginVersion() override;
-
- class Locker : public ScriptInterpreterLocker
- {
- public:
- enum OnEntry
- {
- AcquireLock = 0x0001,
- InitSession = 0x0002,
- InitGlobals = 0x0004,
- NoSTDIN = 0x0008
- };
-
- enum OnLeave
- {
- FreeLock = 0x0001,
- FreeAcquiredLock = 0x0002, // do not free the lock if we already held it when calling constructor
- TearDownSession = 0x0004
- };
-
- Locker(ScriptInterpreterPython *py_interpreter = nullptr,
- uint16_t on_entry = AcquireLock | InitSession,
- uint16_t on_leave = FreeLock | TearDownSession,
- FILE *in = nullptr,
- FILE *out = nullptr,
- FILE *err = nullptr);
-
- ~Locker () override;
-
- private:
- bool
- DoAcquireLock ();
-
- bool
- DoInitSession (uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
-
- bool
- DoFreeLock ();
-
- bool
- DoTearDownSession ();
-
- static void
- ReleasePythonLock ();
-
- bool m_teardown_session;
- ScriptInterpreterPython *m_python_interpreter;
-// FILE* m_tmp_fh;
- PyGILState_STATE m_GILState;
- };
+ typedef bool (*SWIGBreakpointCallbackFunction)(
+ const char *python_function_name, const char *session_dictionary_name,
+ const lldb::StackFrameSP &frame_sp,
+ const lldb::BreakpointLocationSP &bp_loc_sp);
-protected:
- class SynchronicityHandler
- {
- private:
- lldb::DebuggerSP m_debugger_sp;
- ScriptedCommandSynchronicity m_synch_wanted;
- bool m_old_asynch;
-
- public:
- SynchronicityHandler(lldb::DebuggerSP,
- ScriptedCommandSynchronicity);
+ typedef bool (*SWIGWatchpointCallbackFunction)(
+ const char *python_function_name, const char *session_dictionary_name,
+ const lldb::StackFrameSP &frame_sp, const lldb::WatchpointSP &wp_sp);
+
+ typedef bool (*SWIGPythonTypeScriptCallbackFunction)(
+ const char *python_function_name, void *session_dictionary,
+ const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper,
+ const lldb::TypeSummaryOptionsSP &options, std::string &retval);
+
+ typedef void *(*SWIGPythonCreateSyntheticProvider)(
+ const char *python_class_name, const char *session_dictionary_name,
+ const lldb::ValueObjectSP &valobj_sp);
+
+ typedef void *(*SWIGPythonCreateCommandObject)(
+ const char *python_class_name, const char *session_dictionary_name,
+ const lldb::DebuggerSP debugger_sp);
+
+ typedef void *(*SWIGPythonCreateScriptedThreadPlan)(
+ const char *python_class_name, const char *session_dictionary_name,
+ const lldb::ThreadPlanSP &thread_plan_sp);
+
+ typedef bool (*SWIGPythonCallThreadPlan)(void *implementor,
+ const char *method_name,
+ Event *event_sp, bool &got_error);
+
+ typedef void *(*SWIGPythonCreateOSPlugin)(const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ProcessSP &process_sp);
+
+ typedef size_t (*SWIGPythonCalculateNumChildren)(void *implementor,
+ uint32_t max);
+
+ typedef void *(*SWIGPythonGetChildAtIndex)(void *implementor, uint32_t idx);
+
+ typedef int (*SWIGPythonGetIndexOfChildWithName)(void *implementor,
+ const char *child_name);
+
+ typedef void *(*SWIGPythonCastPyObjectToSBValue)(void *data);
+
+ typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue)(
+ void *data);
+
+ typedef bool (*SWIGPythonUpdateSynthProviderInstance)(void *data);
+
+ typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance)(void *data);
+
+ typedef void *(*SWIGPythonGetValueSynthProviderInstance)(void *implementor);
+
+ typedef bool (*SWIGPythonCallCommand)(
+ const char *python_function_name, const char *session_dictionary_name,
+ lldb::DebuggerSP &debugger, const char *args,
+ lldb_private::CommandReturnObject &cmd_retobj,
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp);
+
+ typedef bool (*SWIGPythonCallCommandObject)(
+ void *implementor, lldb::DebuggerSP &debugger, const char *args,
+ lldb_private::CommandReturnObject &cmd_retobj,
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp);
+
+ typedef bool (*SWIGPythonCallModuleInit)(const char *python_module_name,
+ const char *session_dictionary_name,
+ lldb::DebuggerSP &debugger);
+
+ typedef bool (*SWIGPythonScriptKeyword_Process)(
+ const char *python_function_name, const char *session_dictionary_name,
+ lldb::ProcessSP &process, std::string &output);
+
+ typedef bool (*SWIGPythonScriptKeyword_Thread)(
+ const char *python_function_name, const char *session_dictionary_name,
+ lldb::ThreadSP &thread, std::string &output);
+
+ typedef bool (*SWIGPythonScriptKeyword_Target)(
+ const char *python_function_name, const char *session_dictionary_name,
+ lldb::TargetSP &target, std::string &output);
+
+ typedef bool (*SWIGPythonScriptKeyword_Frame)(
+ const char *python_function_name, const char *session_dictionary_name,
+ lldb::StackFrameSP &frame, std::string &output);
+
+ typedef bool (*SWIGPythonScriptKeyword_Value)(
+ const char *python_function_name, const char *session_dictionary_name,
+ lldb::ValueObjectSP &value, std::string &output);
+
+ typedef void *(*SWIGPython_GetDynamicSetting)(
+ void *module, const char *setting, const lldb::TargetSP &target_sp);
+
+ friend class ::IOHandlerPythonInterpreter;
+
+ ScriptInterpreterPython(CommandInterpreter &interpreter);
+
+ ~ScriptInterpreterPython() override;
+
+ bool Interrupt() override;
+
+ bool ExecuteOneLine(
+ const char *command, CommandReturnObject *result,
+ const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
+
+ void ExecuteInterpreterLoop() override;
+
+ bool ExecuteOneLineWithReturn(
+ const char *in_string, ScriptInterpreter::ScriptReturnType return_type,
+ void *ret_value,
+ const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
+
+ lldb_private::Error ExecuteMultipleLines(
+ const char *in_string,
+ const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
+
+ Error
+ ExportFunctionDefinitionToInterpreter(StringList &function_def) override;
+
+ bool GenerateTypeScriptFunction(StringList &input, std::string &output,
+ const void *name_token = nullptr) override;
+
+ bool GenerateTypeSynthClass(StringList &input, std::string &output,
+ const void *name_token = nullptr) override;
+
+ bool GenerateTypeSynthClass(const char *oneliner, std::string &output,
+ const void *name_token = nullptr) override;
+
+ // use this if the function code is just a one-liner script
+ bool GenerateTypeScriptFunction(const char *oneliner, std::string &output,
+ const void *name_token = nullptr) override;
+
+ bool GenerateScriptAliasFunction(StringList &input,
+ std::string &output) override;
+
+ StructuredData::ObjectSP
+ CreateSyntheticScriptedProvider(const char *class_name,
+ lldb::ValueObjectSP valobj) override;
+
+ StructuredData::GenericSP
+ CreateScriptCommandObject(const char *class_name) override;
+
+ StructuredData::ObjectSP
+ CreateScriptedThreadPlan(const char *class_name,
+ lldb::ThreadPlanSP thread_plan) override;
+
+ bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
+ Event *event,
+ bool &script_error) override;
+
+ bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
+ Event *event, bool &script_error) override;
+
+ bool ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
+ bool &script_error) override;
+
+ lldb::StateType
+ ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
+ bool &script_error) override;
+
+ StructuredData::GenericSP
+ OSPlugin_CreatePluginObject(const char *class_name,
+ lldb::ProcessSP process_sp) override;
+
+ StructuredData::DictionarySP
+ OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
+
+ StructuredData::ArraySP
+ OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
+
+ StructuredData::StringSP
+ OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp,
+ lldb::tid_t thread_id) override;
+
+ StructuredData::DictionarySP
+ OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp,
+ lldb::tid_t tid, lldb::addr_t context) override;
+
+ StructuredData::ObjectSP
+ LoadPluginModule(const FileSpec &file_spec,
+ lldb_private::Error &error) override;
+
+ StructuredData::DictionarySP
+ GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
+ const char *setting_name,
+ lldb_private::Error &error) override;
+
+ size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor,
+ uint32_t max) override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(const StructuredData::ObjectSP &implementor,
+ uint32_t idx) override;
+
+ int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,
+ const char *child_name) override;
+
+ bool UpdateSynthProviderInstance(
+ const StructuredData::ObjectSP &implementor) override;
+
+ bool MightHaveChildrenSynthProviderInstance(
+ const StructuredData::ObjectSP &implementor) override;
+
+ lldb::ValueObjectSP
+ GetSyntheticValue(const StructuredData::ObjectSP &implementor) override;
+
+ ConstString
+ GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override;
+
+ bool
+ RunScriptBasedCommand(const char *impl_function, const char *args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject &cmd_retobj,
+ Error &error,
+ const lldb_private::ExecutionContext &exe_ctx) override;
+
+ bool
+ RunScriptBasedCommand(StructuredData::GenericSP impl_obj_sp, const char *args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject &cmd_retobj,
+ Error &error,
+ const lldb_private::ExecutionContext &exe_ctx) override;
+
+ Error GenerateFunction(const char *signature,
+ const StringList &input) override;
- ~SynchronicityHandler();
+ Error GenerateBreakpointCommandCallbackData(StringList &input,
+ std::string &output) override;
+
+ bool GenerateWatchpointCommandCallbackData(StringList &input,
+ std::string &output) override;
+
+ // static size_t
+ // GenerateBreakpointOptionsCommandCallback (void *baton,
+ // InputReader &reader,
+ // lldb::InputReaderAction
+ // notification,
+ // const char *bytes,
+ // size_t bytes_len);
+ //
+ // static size_t
+ // GenerateWatchpointOptionsCommandCallback (void *baton,
+ // InputReader &reader,
+ // lldb::InputReaderAction
+ // notification,
+ // const char *bytes,
+ // size_t bytes_len);
+
+ static bool BreakpointCallbackFunction(void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ static bool WatchpointCallbackFunction(void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t watch_id);
+
+ bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj,
+ StructuredData::ObjectSP &callee_wrapper_sp,
+ const TypeSummaryOptions &options,
+ std::string &retval) override;
+
+ void Clear() override;
+
+ bool GetDocumentationForItem(const char *item, std::string &dest) override;
+
+ bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
+ std::string &dest) override;
+
+ uint32_t
+ GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;
+
+ bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
+ std::string &dest) override;
+
+ bool CheckObjectExists(const char *name) override {
+ if (!name || !name[0])
+ return false;
+ std::string temp;
+ return GetDocumentationForItem(name, temp);
+ }
+
+ bool RunScriptFormatKeyword(const char *impl_function, Process *process,
+ std::string &output, Error &error) override;
+
+ bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,
+ std::string &output, Error &error) override;
+
+ bool RunScriptFormatKeyword(const char *impl_function, Target *target,
+ std::string &output, Error &error) override;
+
+ bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame,
+ std::string &output, Error &error) override;
+
+ bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
+ std::string &output, Error &error) override;
+
+ bool
+ LoadScriptingModule(const char *filename, bool can_reload, bool init_session,
+ lldb_private::Error &error,
+ StructuredData::ObjectSP *module_sp = nullptr) override;
+
+ bool IsReservedWord(const char *word) override;
+
+ std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;
+
+ void CollectDataForBreakpointCommandCallback(
+ std::vector<BreakpointOptions *> &bp_options_vec,
+ CommandReturnObject &result) override;
+
+ void
+ CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
+ CommandReturnObject &result) override;
+
+ /// Set the callback body text into the callback for the breakpoint.
+ Error SetBreakpointCommandCallback(BreakpointOptions *bp_options,
+ const char *callback_body) override;
+
+ void SetBreakpointCommandCallbackFunction(BreakpointOptions *bp_options,
+ const char *function_name) override;
+
+ /// Set a one-liner as the callback for the watchpoint.
+ void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
+ const char *oneliner) override;
+
+ StringList ReadCommandInputFromUser(FILE *in_file);
+
+ void ResetOutputFileHandle(FILE *new_fh) override;
+
+ static void InitializePrivate();
+
+ static void InitializeInterpreter(
+ SWIGInitCallback python_swig_init_callback,
+ SWIGBreakpointCallbackFunction swig_breakpoint_callback,
+ SWIGWatchpointCallbackFunction swig_watchpoint_callback,
+ SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
+ SWIGPythonCreateSyntheticProvider swig_synthetic_script,
+ SWIGPythonCreateCommandObject swig_create_cmd,
+ SWIGPythonCalculateNumChildren swig_calc_children,
+ SWIGPythonGetChildAtIndex swig_get_child_index,
+ SWIGPythonGetIndexOfChildWithName swig_get_index_child,
+ SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue,
+ SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
+ SWIGPythonUpdateSynthProviderInstance swig_update_provider,
+ SWIGPythonMightHaveChildrenSynthProviderInstance
+ swig_mighthavechildren_provider,
+ SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
+ SWIGPythonCallCommand swig_call_command,
+ SWIGPythonCallCommandObject swig_call_command_object,
+ SWIGPythonCallModuleInit swig_call_module_init,
+ SWIGPythonCreateOSPlugin swig_create_os_plugin,
+ SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
+ SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
+ SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
+ SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
+ SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
+ SWIGPython_GetDynamicSetting swig_plugin_get,
+ SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+ SWIGPythonCallThreadPlan swig_call_thread_plan);
+
+ const char *GetDictionaryName() { return m_dictionary_name.c_str(); }
+
+ PyThreadState *GetThreadState() { return m_command_thread_state; }
+
+ void SetThreadState(PyThreadState *s) {
+ if (s)
+ m_command_thread_state = s;
+ }
+
+ //----------------------------------------------------------------------
+ // IOHandlerDelegate
+ //----------------------------------------------------------------------
+ void IOHandlerActivated(IOHandler &io_handler) override;
+
+ void IOHandlerInputComplete(IOHandler &io_handler,
+ std::string &data) override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb::ScriptInterpreterSP
+ CreateInstance(CommandInterpreter &interpreter);
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ class Locker : public ScriptInterpreterLocker {
+ public:
+ enum OnEntry {
+ AcquireLock = 0x0001,
+ InitSession = 0x0002,
+ InitGlobals = 0x0004,
+ NoSTDIN = 0x0008
};
-
- enum class AddLocation
- {
- Beginning,
- End
+
+ enum OnLeave {
+ FreeLock = 0x0001,
+ FreeAcquiredLock = 0x0002, // do not free the lock if we already held it
+ // when calling constructor
+ TearDownSession = 0x0004
};
- static void AddToSysPath(AddLocation location, std::string path);
+ Locker(ScriptInterpreterPython *py_interpreter = nullptr,
+ uint16_t on_entry = AcquireLock | InitSession,
+ uint16_t on_leave = FreeLock | TearDownSession, FILE *in = nullptr,
+ FILE *out = nullptr, FILE *err = nullptr);
- bool
- EnterSession(uint16_t on_entry_flags,
- FILE *in,
- FILE *out,
- FILE *err);
-
- void
- LeaveSession();
-
- void
- SaveTerminalState(int fd);
-
- void
- RestoreTerminalState();
-
- uint32_t
- IsExecutingPython () const
- {
- return m_lock_count > 0;
- }
-
- uint32_t
- IncrementLockCount()
- {
- return ++m_lock_count;
- }
-
- uint32_t
- DecrementLockCount()
- {
- if (m_lock_count > 0)
- --m_lock_count;
- return m_lock_count;
- }
-
- enum ActiveIOHandler {
- eIOHandlerNone,
- eIOHandlerBreakpoint,
- eIOHandlerWatchpoint
- };
+ ~Locker() override;
+
+ private:
+ bool DoAcquireLock();
+
+ bool DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
+
+ bool DoFreeLock();
+
+ bool DoTearDownSession();
+
+ static void ReleasePythonLock();
+
+ bool m_teardown_session;
+ ScriptInterpreterPython *m_python_interpreter;
+ // FILE* m_tmp_fh;
+ PyGILState_STATE m_GILState;
+ };
+
+protected:
+ class SynchronicityHandler {
+ private:
+ lldb::DebuggerSP m_debugger_sp;
+ ScriptedCommandSynchronicity m_synch_wanted;
+ bool m_old_asynch;
+
+ public:
+ SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity);
+
+ ~SynchronicityHandler();
+ };
+
+ enum class AddLocation { Beginning, End };
+
+ static void AddToSysPath(AddLocation location, std::string path);
+
+ bool EnterSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
+
+ void LeaveSession();
+
+ void SaveTerminalState(int fd);
+
+ void RestoreTerminalState();
+
+ uint32_t IsExecutingPython() const { return m_lock_count > 0; }
+
+ uint32_t IncrementLockCount() { return ++m_lock_count; }
+
+ uint32_t DecrementLockCount() {
+ if (m_lock_count > 0)
+ --m_lock_count;
+ return m_lock_count;
+ }
+
+ enum ActiveIOHandler {
+ eIOHandlerNone,
+ eIOHandlerBreakpoint,
+ eIOHandlerWatchpoint
+ };
+
+ PythonObject &GetMainModule();
+
+ PythonDictionary &GetSessionDictionary();
+
+ PythonDictionary &GetSysModuleDictionary();
+
+ bool GetEmbeddedInterpreterModuleObjects();
- PythonObject &GetMainModule();
+ bool SetStdHandle(File &file, const char *py_name, PythonFile &save_file,
+ const char *mode);
- PythonDictionary &
- GetSessionDictionary ();
-
- PythonDictionary &
- GetSysModuleDictionary ();
-
- bool
- GetEmbeddedInterpreterModuleObjects ();
-
- bool
- SetStdHandle(File &file, const char *py_name, PythonFile &save_file, const char *mode);
-
- PythonFile m_saved_stdin;
- PythonFile m_saved_stdout;
- PythonFile m_saved_stderr;
- PythonObject m_main_module;
- PythonObject m_lldb_module;
- PythonDictionary m_session_dict;
- PythonDictionary m_sys_module_dict;
- PythonObject m_run_one_line_function;
- PythonObject m_run_one_line_str_global;
- std::string m_dictionary_name;
- TerminalState m_terminal_state;
- ActiveIOHandler m_active_io_handler;
- bool m_session_is_active;
- bool m_pty_slave_is_open;
- bool m_valid_session;
- uint32_t m_lock_count;
- PyThreadState *m_command_thread_state;
+ PythonFile m_saved_stdin;
+ PythonFile m_saved_stdout;
+ PythonFile m_saved_stderr;
+ PythonObject m_main_module;
+ PythonObject m_lldb_module;
+ PythonDictionary m_session_dict;
+ PythonDictionary m_sys_module_dict;
+ PythonObject m_run_one_line_function;
+ PythonObject m_run_one_line_str_global;
+ std::string m_dictionary_name;
+ TerminalState m_terminal_state;
+ ActiveIOHandler m_active_io_handler;
+ bool m_session_is_active;
+ bool m_pty_slave_is_open;
+ bool m_valid_session;
+ uint32_t m_lock_count;
+ PyThreadState *m_command_thread_state;
};
} // namespace lldb_private
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/lldb-python.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/lldb-python.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/lldb-python.h (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/lldb-python.h Tue Sep 6 15:57:50 2016
@@ -1,4 +1,5 @@
-//===-- lldb-python.h --------------------------------------------*- C++ -*-===//
+//===-- lldb-python.h --------------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,14 +11,16 @@
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
-// Python.h needs to be included before any system headers in order to avoid redefinition of macros
+// Python.h needs to be included before any system headers in order to avoid
+// redefinition of macros
#ifdef LLDB_DISABLE_PYTHON
// Python is disabled in this build
#else
#include "llvm/Support/Compiler.h"
#if defined(LLVM_ON_WIN32)
-// If anyone #includes Host/PosixApi.h later, it will try to typedef pid_t. We need to ensure
+// If anyone #includes Host/PosixApi.h later, it will try to typedef pid_t. We
+// need to ensure
// this doesn't happen.
#define NO_PID_T
#endif
More information about the lldb-commits
mailing list