aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2013-10-15 00:14:28 +0000
committerGreg Clayton <gclayton@apple.com>2013-10-15 00:14:28 +0000
commitef8180a3f6c963478c0c3e5b10b89a274a594017 (patch)
tree551a2a4c992187567584f0c0f37fde08cde516d2 /lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
parent059e05eeef102bcd6d55e09ebca5c0b4b9ac76d7 (diff)
downloadllvm-ef8180a3f6c963478c0c3e5b10b89a274a594017.zip
llvm-ef8180a3f6c963478c0c3e5b10b89a274a594017.tar.gz
llvm-ef8180a3f6c963478c0c3e5b10b89a274a594017.tar.bz2
<rdar://problem/14972424>
When debugging with the GDB remote in LLDB, LLDB uses special packets to discover the registers on the remote server. When those packets aren't supported, LLDB doesn't know what the registers look like. This checkin implements a setting that can be used to specify a python file that contains the registers definitions. The setting is: (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/module.py Inside module there should be a function: def get_dynamic_setting(target, setting_name): This dynamic setting function is handed the "target" which is a SBTarget, and the "setting_name", which is the name of the dynamic setting to retrieve. For the GDB remote target definition the setting name is 'gdb-server-target-definition'. The return value is a dictionary that follows the same format as the OperatingSystem plugins follow. I have checked in an example file that implements the x86_64 GDB register set for people to see: examples/python/x86_64_target_definition.py This allows LLDB to debug to any archticture that is support and allows users to define the registers contexts when the discovery packets (qRegisterInfo, qHostInfo) are not supported by the remote GDB server. A few benefits of doing this in Python: 1 - The dynamic register context was already supported in the OperatingSystem plug-in 2 - Register contexts can use all of the LLDB enumerations and definitions for things like lldb::Format, lldb::Encoding, generic register numbers, invalid registers numbers, etc. 3 - The code that generates the register context can use the program to calculate the register context contents (like offsets, register numbers, and more) 4 - True dynamic detection could be used where variables and types could be read from the target program itself in order to determine which registers are available since the target is passed into the python function. This is designed to be used instead of XML since it is more dynamic and code flow and functions can be used to make the dictionary. llvm-svn: 192646
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp132
1 files changed, 132 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index b8129c9..69dae05 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -17,6 +17,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/PythonDataObjects.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/Utils.h"
// Project includes
@@ -696,6 +697,137 @@ GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, ui
return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num);
}
+size_t
+GDBRemoteDynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict)
+{
+#ifndef LLDB_DISABLE_PYTHON
+ PythonList sets (dict.GetItemForKey("sets"));
+ if (sets)
+ {
+ const uint32_t num_sets = sets.GetSize();
+ for (uint32_t i=0; i<num_sets; ++i)
+ {
+ PythonString py_set_name(sets.GetItemAtIndex(i));
+ ConstString set_name;
+ if (py_set_name)
+ set_name.SetCString(py_set_name.GetString());
+ if (set_name)
+ {
+ RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
+ m_sets.push_back (new_set);
+ }
+ else
+ {
+ Clear();
+ return 0;
+ }
+ }
+ m_set_reg_nums.resize(m_sets.size());
+ }
+ PythonList regs (dict.GetItemForKey("registers"));
+ if (regs)
+ {
+ const uint32_t num_regs = regs.GetSize();
+ PythonString name_pystr("name");
+ PythonString altname_pystr("alt-name");
+ PythonString bitsize_pystr("bitsize");
+ PythonString offset_pystr("offset");
+ PythonString encoding_pystr("encoding");
+ PythonString format_pystr("format");
+ PythonString set_pystr("set");
+ PythonString gcc_pystr("gcc");
+ PythonString gdb_pystr("gdb");
+ PythonString dwarf_pystr("dwarf");
+ PythonString generic_pystr("generic");
+ for (uint32_t i=0; i<num_regs; ++i)
+ {
+ PythonDictionary reg_info_dict(regs.GetItemAtIndex(i));
+ if (reg_info_dict)
+ {
+ // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
+ RegisterInfo reg_info;
+ bzero (&reg_info, sizeof(reg_info));
+
+ reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString();
+ if (reg_info.name == NULL)
+ {
+ Clear();
+ return 0;
+ }
+
+ reg_info.alt_name = ConstString (reg_info_dict.GetItemForKeyAsString(altname_pystr)).GetCString();
+
+ reg_info.byte_offset = reg_info_dict.GetItemForKeyAsInteger(offset_pystr, UINT32_MAX);
+
+ if (reg_info.byte_offset == UINT32_MAX)
+ {
+ Clear();
+ return 0;
+ }
+ reg_info.byte_size = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0) / 8;
+
+ if (reg_info.byte_size == 0)
+ {
+ Clear();
+ return 0;
+ }
+
+ const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr);
+ if (format_cstr)
+ {
+ if (Args::StringToFormat(format_cstr, reg_info.format, NULL).Fail())
+ {
+ Clear();
+ return 0;
+ }
+ }
+ else
+ {
+ reg_info.format = (Format)reg_info_dict.GetItemForKeyAsInteger (format_pystr, eFormatHex);
+ }
+
+ const char *encoding_cstr = reg_info_dict.GetItemForKeyAsString(encoding_pystr);
+ if (encoding_cstr)
+ reg_info.encoding = Args::StringToEncoding (encoding_cstr, eEncodingUint);
+ else
+ reg_info.encoding = (Encoding)reg_info_dict.GetItemForKeyAsInteger (encoding_pystr, eEncodingUint);
+
+ const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1);
+ if (set >= m_sets.size())
+ {
+ Clear();
+ return 0;
+ }
+
+ reg_info.kinds[lldb::eRegisterKindLLDB] = i;
+ reg_info.kinds[lldb::eRegisterKindGDB] = reg_info_dict.GetItemForKeyAsInteger(gdb_pystr , LLDB_INVALID_REGNUM);
+ reg_info.kinds[lldb::eRegisterKindGCC] = reg_info_dict.GetItemForKeyAsInteger(gcc_pystr , LLDB_INVALID_REGNUM);
+ reg_info.kinds[lldb::eRegisterKindDWARF] = reg_info_dict.GetItemForKeyAsInteger(dwarf_pystr , LLDB_INVALID_REGNUM);
+ const char *generic_cstr = reg_info_dict.GetItemForKeyAsString(generic_pystr);
+ if (generic_cstr)
+ reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (generic_cstr);
+ else
+ reg_info.kinds[lldb::eRegisterKindGeneric] = reg_info_dict.GetItemForKeyAsInteger(generic_pystr, LLDB_INVALID_REGNUM);
+ const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
+ if (m_reg_data_byte_size < end_reg_offset)
+ m_reg_data_byte_size = end_reg_offset;
+
+ m_regs.push_back (reg_info);
+ m_set_reg_nums[set].push_back(i);
+
+ }
+ else
+ {
+ Clear();
+ return 0;
+ }
+ }
+ Finalize ();
+ }
+#endif
+ return 0;
+}
+
void
GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)
{