summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2015-05-26 18:00:51 +0000
committerGreg Clayton <gclayton@apple.com>2015-05-26 18:00:51 +0000
commitd04f0edad9afe46f18b86de9199884ea1dceb220 (patch)
treeb0fc46f21a8b89ad468b8fae3c98e81f29e182c3 /lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
parentbfecc06656d0f9fcdf22270b6c0aa15441d8d198 (diff)
downloadbcm5719-llvm-d04f0edad9afe46f18b86de9199884ea1dceb220.tar.gz
bcm5719-llvm-d04f0edad9afe46f18b86de9199884ea1dceb220.zip
Added XML to the host layer.
We know have on API we should use for all XML within LLDB in XML.h. This API will be easy back the XML parsing by different libraries in case libxml2 doesn't work on all platforms. It also allows the only place for #ifdef ...XML... to be in XML.h and XML.cpp. The API is designed so it will still compile with or without XML support and there is a static function "bool XMLDocument::XMLEnabled()" that can be called to see if XML is currently supported. All APIs will return errors, false, or nothing when XML isn't enabled. Converted all locations that used XML over to using the host XML implementation. Added target.xml support to debugserver. Extended the XML register format to work for LLDB by including extra attributes and elements where needed. This allows the target.xml to replace the qRegisterInfo packets and allows us to fetch all register info in a single packet. <rdar://problem/21090173> llvm-svn: 238224
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp895
1 files changed, 335 insertions, 560 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index a03c43b005f..0399634c274 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -26,11 +26,6 @@
#include <map>
#include <mutex>
-// Other libraries and framework includes
-#if defined( LIBXML2_DEFINED )
-#include <libxml/xmlreader.h>
-#endif
-
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Core/ArchSpec.h"
@@ -45,11 +40,13 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
+#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Host/XML.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
@@ -478,7 +475,7 @@ ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_
m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue();
}
- if (m_register_info.SetRegisterInfo(*target_definition_sp, GetTarget().GetArchitecture().GetByteOrder()) > 0)
+ if (m_register_info.SetRegisterInfo(*target_definition_sp, GetTarget().GetArchitecture()) > 0)
{
return true;
}
@@ -487,6 +484,25 @@ ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_
return false;
}
+static size_t
+SplitCommaSeparatedRegisterNumberString(const llvm::StringRef &comma_separated_regiter_numbers, std::vector<uint32_t> &regnums, 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)
@@ -494,8 +510,21 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
if (!force && m_register_info.GetNumRegisters() > 0)
return;
- char packet[128];
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);
+ }
+
+ if (GetGDBServerRegisterInfo ())
+ return;
+
+ char packet[128];
uint32_t reg_offset = 0;
uint32_t reg_num = 0;
for (StringExtractorGDBRemote::ResponseType response_type = StringExtractorGDBRemote::eResponse;
@@ -610,33 +639,11 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
}
else if (name.compare("container-regs") == 0)
{
- std::pair<llvm::StringRef, llvm::StringRef> value_pair;
- value_pair.second = value;
- 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, 16);
- if (reg != LLDB_INVALID_REGNUM)
- value_regs.push_back (reg);
- }
- } while (!value_pair.second.empty());
+ SplitCommaSeparatedRegisterNumberString(value, value_regs, 16);
}
else if (name.compare("invalidate-regs") == 0)
{
- std::pair<llvm::StringRef, llvm::StringRef> value_pair;
- value_pair.second = value;
- 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, 16);
- if (reg != LLDB_INVALID_REGNUM)
- invalidate_regs.push_back (reg);
- }
- } while (!value_pair.second.empty());
+ SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16);
}
}
@@ -667,30 +674,19 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
}
}
- // 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)
+ if (m_register_info.GetNumRegisters() > 0)
{
- GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout);
+ m_register_info.Finalize(GetTarget().GetArchitecture());
+ return;
}
-
- if (reg_num == 0)
+ FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();
+
+ if (target_definition_fspec)
{
- // try to extract information from servers target.xml
- if (GetGDBServerRegisterInfo ())
+ // See if we can get register definitions from a python file
+ if (ParsePythonTargetDefinition (target_definition_fspec))
return;
-
- FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();
-
- if (target_definition_fspec)
- {
- // See if we can get register definitions from a python file
- if (ParsePythonTargetDefinition (target_definition_fspec))
- return;
- }
}
// We didn't get anything if the accumulated reg_num is zero. See if we are
@@ -698,7 +694,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
// 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 = (reg_num == 0);
+ bool from_scratch = (m_register_info.GetNumRegisters() == 0);
const ArchSpec &target_arch = GetTarget().GetArchitecture();
const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture();
@@ -724,7 +720,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
}
// At this point, we can finalize our register info.
- m_register_info.Finalize ();
+ m_register_info.Finalize (GetTarget().GetArchitecture());
}
Error
@@ -3595,420 +3591,208 @@ ProcessGDBRemote::GetModuleSpec(const FileSpec& module_file_spec,
return true;
}
-#if defined( LIBXML2_DEFINED )
namespace {
typedef std::vector<std::string> stringVec;
-typedef std::vector<xmlNodePtr> xmlNodePtrVec;
-
-struct GdbServerRegisterInfo
-{
-
- struct
- {
- bool m_has_name : 1;
- bool m_has_bitSize : 1;
- bool m_has_type : 1;
- bool m_has_group : 1;
- bool m_has_regNum : 1;
- }
- m_flags;
-
- std::string m_name;
- std::string m_group;
- uint32_t m_bitSize;
- uint32_t m_regNum;
-
- enum RegType
- {
- eUnknown ,
- eCodePtr ,
- eDataPtr ,
- eInt32 ,
- eI387Ext ,
- }
- m_type;
-
- void clear()
- {
- memset(&m_flags, 0, sizeof(m_flags));
- }
-};
typedef std::vector<struct GdbServerRegisterInfo> GDBServerRegisterVec;
-
-struct GdbServerTargetInfo
+struct RegisterSetInfo
{
- std::string m_arch;
- std::string m_osabi;
+ ConstString name;
};
-// conversion table between gdb register type and enum
-struct
-{
- const char * m_name;
- GdbServerRegisterInfo::RegType m_type;
-}
-RegTypeTable[] =
+typedef std::map<uint32_t, RegisterSetInfo> RegisterSetMap;
+
+struct GdbServerTargetInfo
{
- { "int32" , GdbServerRegisterInfo::eInt32 },
- { "int" , GdbServerRegisterInfo::eInt32 },
- { "data_ptr", GdbServerRegisterInfo::eDataPtr },
- { "code_ptr", GdbServerRegisterInfo::eCodePtr },
- { "i387_ext", GdbServerRegisterInfo::eI387Ext }, // 80bit fpu
- { nullptr , GdbServerRegisterInfo::eUnknown } // sentinel
+ std::string arch;
+ std::string osabi;
+ stringVec includes;
+ RegisterSetMap reg_set_map;
+ XMLNode feature_node;
};
-
-// find the first sibling with a matching name
-xmlNodePtr
-xmlExFindSibling (xmlNodePtr node,
- const std::string & name)
-{
-
- if ( !node ) return nullptr;
- // iterate through all siblings
- for ( xmlNodePtr temp = node; temp; temp=temp->next ) {
- // we are looking for elements
- if ( temp->type != XML_ELEMENT_NODE )
- continue;
- // check element name matches
- if ( !temp->name ) continue;
- if ( std::strcmp((const char*)temp->name, name.c_str() ) == 0 )
- return temp;
- }
- // no sibling found
- return nullptr;
-}
-
-// find an element from a given element path
-xmlNodePtr
-xmlExFindElement (xmlNodePtr node,
- const stringVec & path)
-{
-
- if (!node)
- return nullptr;
- xmlNodePtr temp = node;
- // iterate all elements in path
- for (uint32_t i = 0; i < path.size(); i++)
- {
-
- // search for a sibling with this name
- temp = xmlExFindSibling(temp, path[i]);
- if (!temp)
- return nullptr;
- // enter this node if we still need to search
- if ((i + 1) < path.size())
- // enter the node we have found
- temp = temp->children;
- }
- // note: node may still be nullptr at this step
- return temp;
-}
-
-// locate a specific attribute in an element
-xmlAttr *
-xmlExFindAttribute (xmlNodePtr node,
- const std::string & name)
-{
-
- if (!node)
- return nullptr;
- if (node->type != XML_ELEMENT_NODE)
- return nullptr;
- // iterate over all attributes
- for (xmlAttrPtr attr = node->properties; attr != nullptr; attr=attr->next)
- {
- // check if name matches
- if (!attr->name)
- continue;
- if (std::strcmp((const char*) attr->name, name.c_str()) == 0)
- return attr;
- }
- return nullptr;
-}
-
-// find all child elements with given name and add them to a vector
-//
-// input: node = xml element to search
-// name = name used when matching child elements
-// output: out = list of matches
-// return: number of children added to 'out'
-int
-xmlExFindChildren (xmlNodePtr node,
- const std::string & name,
- xmlNodePtrVec & out)
-{
-
- if (!node)
- return 0;
- int count = 0;
- // iterate over all children
- for (xmlNodePtr child = node->children; child; child = child->next)
- {
- // if name matches
- if (!child->name)
- continue;
- if (std::strcmp((const char*) child->name, name.c_str()) == 0)
- {
- // add to output list
- out.push_back(child);
- ++count;
- }
- }
- return count;
-}
-
-// get the text content from an attribute
-std::string
-xmlExGetTextContent (xmlAttrPtr attr)
-{
- if (!attr)
- return std::string();
- if (attr->type != XML_ATTRIBUTE_NODE)
- return std::string();
- // check child is a text node
- xmlNodePtr child = attr->children;
- if (child->type != XML_TEXT_NODE)
- return std::string();
- // access the content
- assert(child->content != nullptr);
- return std::string((const char*) child->content);
-}
-
-// get the text content from an node
-std::string
-xmlExGetTextContent (xmlNodePtr node)
-{
- if (!node)
- return std::string();
- if (node->type != XML_ELEMENT_NODE)
- return std::string();
- // check child is a text node
- xmlNodePtr child = node->children;
- if (child->type != XML_TEXT_NODE)
- return std::string();
- // access the content
- assert(child->content != nullptr);
- return std::string((const char*) child->content);
-}
-
-// compile a list of xml includes from the target file
-// input: doc = target.xml
-// output: includes = list of .xml names specified in target.xml
-// return: number of .xml files specified in target.xml and added to includes
-int
-parseTargetIncludes (xmlDocPtr doc, stringVec & includes)
-{
- if (!doc)
- return 0;
- int count = 0;
- xmlNodePtr elm = xmlExFindElement(doc->children, {"target"});
- if (!elm)
- return 0;
- xmlNodePtrVec nodes;
- xmlExFindChildren(elm, "xi:include", nodes);
- // iterate over all includes
- for (uint32_t i = 0; i < nodes.size(); i++)
- {
- xmlAttrPtr attr = xmlExFindAttribute(nodes[i], "href");
- if (attr != nullptr)
- {
- std::string text = xmlExGetTextContent(attr);
- includes.push_back(text);
- ++count;
- }
- }
- return count;
-}
-
-// extract target arch information from the target.xml file
-// input: doc = target.xml document
-// output: out = remote target information
-// return: 'true' on success
-// 'false' on failure
-bool
-parseTargetInfo (xmlDocPtr doc, GdbServerTargetInfo & out)
-{
- if (!doc)
- return false;
- xmlNodePtr e1 = xmlExFindElement (doc->children, {"target", "architecture"});
- if (!e1)
- return false;
- out.m_arch = xmlExGetTextContent (e1);
-
- xmlNodePtr e2 = xmlExFindElement (doc->children, {"target", "osabi"});
- if (!e2)
- return false;
- out.m_osabi = xmlExGetTextContent (e2);
-
- return true;
-}
-
-// extract register information from one of the xml files specified in target.xml
-// input: doc = xml document
-// output: regList = list of extracted register info
-// return: 'true' on success
-// 'false' on failure
+
bool
-parseRegisters (xmlDocPtr doc, GDBServerRegisterVec & regList)
+ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info)
{
-
- if (!doc)
+ if (!feature_node)
return false;
- xmlNodePtr elm = xmlExFindElement (doc->children, {"feature"});
- if (!elm)
- return false;
-
- xmlAttrPtr attr = nullptr;
-
- xmlNodePtrVec regs;
- xmlExFindChildren (elm, "reg", regs);
- for (unsigned long i = 0; i < regs.size(); i++)
- {
-
- GdbServerRegisterInfo reg;
- reg.clear();
-
- if ((attr = xmlExFindAttribute(regs[i], "name")))
- {
- reg.m_name = xmlExGetTextContent(attr).c_str();
- reg.m_flags.m_has_name = true;
- }
-
- if ((attr = xmlExFindAttribute( regs[i], "bitsize")))
- {
- const std::string v = xmlExGetTextContent(attr);
- reg.m_bitSize = atoi(v.c_str());
- reg.m_flags.m_has_bitSize = true;
- }
-
- if ((attr = xmlExFindAttribute(regs[i], "type")))
- {
- const std::string v = xmlExGetTextContent(attr);
- reg.m_type = GdbServerRegisterInfo::eUnknown;
+
+ uint32_t prev_reg_num = 0;
+ uint32_t reg_offset = 0;
- // search the type table for a match
- for (int j = 0; RegTypeTable[j].m_name !=nullptr; ++j)
+ feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &prev_reg_num, &reg_offset](const XMLNode &reg_node) -> bool {
+ std::string name;
+ std::string gdb_group;
+ std::string gdb_type;
+ ConstString reg_name;
+ ConstString alt_name;
+ ConstString set_name;
+ std::vector<uint32_t> value_regs;
+ std::vector<uint32_t> invalidate_regs;
+ 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, // formate
+ {
+ LLDB_INVALID_REGNUM, // GCC reg num
+ LLDB_INVALID_REGNUM, // DWARF reg num
+ LLDB_INVALID_REGNUM, // generic reg num
+ prev_reg_num, // GDB reg num
+ prev_reg_num // native register number
+ },
+ NULL,
+ NULL
+ };
+
+ reg_node.ForEachAttribute([&target_info, &name, &gdb_group, &gdb_type, &reg_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, &reg_info, &prev_reg_num, &reg_offset](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
+ if (name == "name")
{
- if (RegTypeTable[j].m_name == v)
+ 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.m_type = RegTypeTable[j].m_type;
- break;
+ reg_info.kinds[eRegisterKindGDB] = regnum;
+ reg_info.kinds[eRegisterKindLLDB] = regnum;
+ prev_reg_num = regnum;
}
}
-
- reg.m_flags.m_has_type = (reg.m_type != GdbServerRegisterInfo::eUnknown);
- }
-
- if ((attr = xmlExFindAttribute( regs[i], "group")))
- {
- reg.m_group = xmlExGetTextContent(attr);
- reg.m_flags.m_has_group = true;
- }
-
- if ((attr = xmlExFindAttribute(regs[i], "regnum")))
- {
- const std::string v = xmlExGetTextContent(attr);
- reg.m_regNum = atoi(v.c_str());
- reg.m_flags.m_has_regNum = true;
- }
-
- regList.push_back(reg);
- }
-
- //TODO: there is also a "vector" element to parse
- //TODO: there is also eflags to parse
-
- return true;
-}
-
-// build lldb gdb-remote's dynamic register info from a vector of gdb provided registers
-// input: regList = register information provided by gdbserver
-// output: regInfo = dynamic register information required by gdb-remote
-void
-BuildRegisters (const GDBServerRegisterVec & regList,
- GDBRemoteDynamicRegisterInfo & regInfo)
-{
-
- using namespace lldb_private;
-
- const uint32_t defSize = 32;
- uint32_t regNum = 0;
- uint32_t byteOffset = 0;
-
- for (uint32_t i = 0; i < regList.size(); ++i)
- {
-
- const GdbServerRegisterInfo & gdbReg = regList[i];
-
- std::string name = gdbReg.m_flags.m_has_name ? gdbReg.m_name : "unknown";
- std::string group = gdbReg.m_flags.m_has_group ? gdbReg.m_group : "general";
- uint32_t byteSize = gdbReg.m_flags.m_has_bitSize ? (gdbReg.m_bitSize/8) : defSize;
-
- if (gdbReg.m_flags.m_has_regNum)
- regNum = gdbReg.m_regNum;
-
- uint32_t regNumGcc = LLDB_INVALID_REGNUM;
- uint32_t regNumDwarf = LLDB_INVALID_REGNUM;
- uint32_t regNumGeneric = LLDB_INVALID_REGNUM;
- uint32_t regNumGdb = regNum;
- uint32_t regNumNative = regNum;
-
- if (name == "eip" || name == "pc")
- {
- regNumGeneric = LLDB_REGNUM_GENERIC_PC;
- }
- if (name == "esp" || name == "sp")
+ 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")
+ {
+ reg_info.kinds[eRegisterKindGCC] = 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
+ {
+ 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))
{
- regNumGeneric = LLDB_REGNUM_GENERIC_SP;
+ 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;
+ }
}
- if (name == "ebp")
+
+ // 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());
+
+ reg_info.byte_offset = reg_offset;
+ assert (reg_info.byte_size != 0);
+ reg_offset += reg_info.byte_size;
+ if (!value_regs.empty())
{
- regNumGeneric = LLDB_REGNUM_GENERIC_FP;
+ value_regs.push_back(LLDB_INVALID_REGNUM);
+ reg_info.value_regs = value_regs.data();
}
- if (name == "lr")
+ if (!invalidate_regs.empty())
{
- regNumGeneric = LLDB_REGNUM_GENERIC_RA;
+ invalidate_regs.push_back(LLDB_INVALID_REGNUM);
+ reg_info.invalidate_regs = invalidate_regs.data();
}
-
- RegisterInfo info =
- {
- name.c_str(),
- nullptr ,
- byteSize ,
- byteOffset ,
- lldb::Encoding::eEncodingUint,
- lldb::Format::eFormatDefault,
- { regNumGcc ,
- regNumDwarf ,
- regNumGeneric,
- regNumGdb ,
- regNumNative },
- nullptr,
- nullptr
- };
-
- ConstString regName = ConstString(gdbReg.m_name);
- ConstString regAltName = ConstString();
- ConstString regGroup = ConstString(group);
- regInfo.AddRegister(info, regName, regAltName, regGroup);
-
- // advance register info
- byteOffset += byteSize;
- regNum += 1;
- }
-
- regInfo.Finalize ();
+
+ dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);
+
+ return true; // Keep iterating through all "reg" elements
+ });
+ return true;
}
-
+
} // namespace {}
-void XMLCDECL
-libxml2NullErrorFunc (void *ctx, const char *msg, ...)
-{
- // do nothing currently
-}
// query the target of gdb-remote for extended target information
// return: 'true' on success
@@ -4016,13 +3800,13 @@ libxml2NullErrorFunc (void *ctx, const char *msg, ...)
bool
ProcessGDBRemote::GetGDBServerRegisterInfo ()
{
+ // 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
- xmlGenericErrorFunc func = libxml2NullErrorFunc;
- initGenericErrorDefaultFunc( &func );
GDBRemoteCommunicationClient & comm = m_gdb_comm;
- GDBRemoteDynamicRegisterInfo & regInfo = m_register_info;
// check that we have extended feature read support
if ( !comm.GetQXferFeaturesReadSupported( ) )
@@ -4038,66 +3822,102 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
{
return false;
}
+
- // parse the xml file in memory
- xmlDocPtr doc = xmlReadMemory(raw.c_str(), raw.size(), "noname.xml", nullptr, 0);
- if (doc == nullptr)
- return false;
-
- // extract target info from target.xml
- GdbServerTargetInfo gdbInfo;
- if (parseTargetInfo(doc, gdbInfo))
- {
- // NOTE: We could deduce triple from gdbInfo if lldb doesn't already have one set
- }
+ XMLDocument xml_document;
- // collect registers from all of the includes
- GDBServerRegisterVec regList;
- stringVec includes;
- if (parseTargetIncludes(doc, includes) > 0)
+ if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml"))
{
-
- for (uint32_t i = 0; i < includes.size(); ++i)
+ GdbServerTargetInfo target_info;
+
+ XMLNode target_node = xml_document.GetRootElement("target");
+ if (target_node)
{
-
- // request register file
- if (!comm.ReadExtFeature(ConstString("features"),
- ConstString(includes[i]),
- raw,
- lldberr))
- continue;
-
- // parse register file
- xmlDocPtr regXml = xmlReadMemory(raw.c_str(),
- raw.size( ),
- includes[i].c_str(),
- nullptr,
- 0);
- if (!regXml)
- continue;
-
- // pass registers to lldb
- parseRegisters(regXml, regList);
+ 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")
+ {
+ 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
+ });
+
+ if (feature_node)
+ {
+ ParseRegisters(feature_node, target_info, this->m_register_info);
+ }
+
+ 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);
+ }
+ }
+ this->m_register_info.Finalize(GetTarget().GetArchitecture());
}
}
- // pass all of these registers to lldb
- BuildRegisters(regList, regInfo);
-
- return true;
+ return m_register_info.GetNumRegisters() > 0;
}
Error
ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & 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__);
- // redirect libxml2's error handler since the default prints to stdout
- xmlGenericErrorFunc func = libxml2NullErrorFunc;
- initGenericErrorDefaultFunc (&func);
-
GDBRemoteCommunicationClient & comm = m_gdb_comm;
// check that we have extended feature read support
@@ -4115,79 +3935,53 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
// parse the xml file in memory
if (log)
log->Printf ("parsing: %s", raw.c_str());
- xmlDocPtr doc = xmlReadMemory (raw.c_str(), raw.size(), "noname.xml", nullptr, 0);
- if (doc == nullptr)
+ XMLDocument doc;
+
+ if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
return Error (0, ErrorType::eErrorTypeGeneric);
- xmlNodePtr elm = xmlExFindElement (doc->children, {"library-list-svr4"});
- if (!elm)
+ XMLNode root_element = doc.GetRootElement("library-list-svr4");
+ if (!root_element)
return Error();
// main link map structure
- xmlAttr * attr = xmlExFindAttribute (elm, "main-lm");
- if (attr)
+ llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm");
+ if (!main_lm.empty())
{
- std::string val = xmlExGetTextContent (attr);
- if (val.length() > 2)
- {
- uint32_t process_lm = std::stoul (val.c_str()+2, 0, 16);
- list.m_link_map = process_lm;
- }
+ list.m_link_map = StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0);
}
- // parse individual library entries
- for (xmlNode * child = elm->children; child; child=child->next)
- {
- if (!child->name)
- continue;
-
- if (strcmp ((const char*)child->name, "library") != 0)
- continue;
+ root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
GDBLoadedModuleInfoList::LoadedModuleInfo module;
- for (xmlAttrPtr prop = child->properties; prop; prop=prop->next)
- {
- if (strcmp ((const char*)prop->name, "name") == 0)
- module.set_name (xmlExGetTextContent (prop));
-
- // the address of the link_map struct.
- if (strcmp ((const char*)prop->name, "lm") == 0)
+ 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")
{
- std::string val = xmlExGetTextContent (prop);
- if (val.length() > 2)
- {
- uint32_t module_lm = std::stoul (val.c_str()+2, 0, 16);
- module.set_link_map (module_lm);
- }
+ // the address of the link_map struct.
+ module.set_link_map(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
}
-
- // the displacement as read from the field 'l_addr' of the link_map struct.
- if (strcmp ((const char*)prop->name, "l_addr") == 0)
+ else if (name == "l_addr")
{
- std::string val = xmlExGetTextContent (prop);
- if (val.length() > 2)
- {
- uint32_t module_base = std::stoul (val.c_str()+2, 0, 16);
- module.set_base (module_base);
- }
+ // 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));
+
}
-
- // the memory address of the libraries PT_DYAMIC section.
- if (strcmp ((const char*)prop->name, "l_ld") == 0)
+ else if (name == "l_ld")
{
- std::string val = xmlExGetTextContent (prop);
- if (val.length() > 2)
- {
- uint32_t module_dyn = std::stoul (val.c_str()+2, 0, 16);
- module.set_dynamic (module_dyn);
- }
+ // 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 ("");
+ std::string name;
lldb::addr_t lm=0, base=0, ld=0;
module.get_name (name);
@@ -4199,7 +3993,8 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
}
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());
@@ -4207,26 +4002,6 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
return Error();
}
-#else // if defined( LIBXML2_DEFINED )
-
-Error
-ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList &)
-{
- // stub (libxml2 not present)
- Error err;
- err.SetError (0, ErrorType::eErrorTypeGeneric);
- return err;
-}
-
-bool
-ProcessGDBRemote::GetGDBServerRegisterInfo ()
-{
- // stub (libxml2 not present)
- return false;
-}
-
-#endif // if defined( LIBXML2_DEFINED )
-
lldb::ModuleSP
ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr)
{
OpenPOWER on IntegriCloud