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
This commit is contained in:
Greg Clayton 2015-05-26 18:00:51 +00:00
parent bfecc06656
commit d04f0edad9
17 changed files with 1719 additions and 724 deletions

View File

@ -0,0 +1,216 @@
//===-- XML.h ---------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_XML_h_
#define liblldb_XML_h_
// C Includes
#if defined( LIBXML2_DEFINED )
#include <libxml/xmlreader.h>
#endif
// C++ Includes
#include <functional>
#include <string>
#include <vector>
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "llvm/ADT/StringRef.h"
#include "lldb/Core/StreamString.h"
namespace lldb_private {
#if defined( LIBXML2_DEFINED )
typedef xmlNodePtr XMLNodeImpl;
typedef xmlDocPtr XMLDocumentImpl;
#else
typedef void * XMLNodeImpl;
typedef void * XMLDocumentImpl;
#endif
class XMLNode;
typedef std::vector<std::string> NamePath;
typedef std::function <bool(const XMLNode &node)> NodeCallback;
typedef std::function <bool(const llvm::StringRef &name, const llvm::StringRef &value)> AttributeCallback;
class XMLNode
{
public:
XMLNode();
XMLNode(XMLNodeImpl node);
~XMLNode();
explicit operator bool() const
{
return IsValid();
}
void
Clear();
bool
IsValid() const;
bool
IsElement () const;
llvm::StringRef
GetName() const;
bool
GetElementText (std::string &text) const;
bool
NameIs (const char *name) const;
XMLNode
GetParent() const;
XMLNode
GetSibling() const;
XMLNode
GetChild () const;
llvm::StringRef
GetAttributeValue(const char *name, const char *fail_value = NULL) const;
XMLNode
FindFirstChildElementWithName (const char *name) const;
XMLNode
GetElementForPath (const NamePath &path);
//----------------------------------------------------------------------
// Iterate through all sibling nodes of any type
//----------------------------------------------------------------------
void
ForEachSiblingNode (NodeCallback const &callback) const;
//----------------------------------------------------------------------
// Iterate through only the sibling nodes that are elements
//----------------------------------------------------------------------
void
ForEachSiblingElement (NodeCallback const &callback) const;
//----------------------------------------------------------------------
// Iterate through only the sibling nodes that are elements and whose
// name matches \a name.
//----------------------------------------------------------------------
void
ForEachSiblingElementWithName (const char *name, NodeCallback const &callback) const;
void
ForEachChildNode (NodeCallback const &callback) const;
void
ForEachChildElement (NodeCallback const &callback) const;
void
ForEachChildElementWithName (const char *name, NodeCallback const &callback) const;
void
ForEachAttribute (AttributeCallback const &callback) const;
protected:
XMLNodeImpl m_node;
};
class XMLDocument
{
public:
XMLDocument ();
~XMLDocument ();
explicit operator bool() const
{
return IsValid();
}
bool
IsValid() const;
void
Clear();
bool
ParseFile (const char *path);
bool
ParseMemory (const char *xml, size_t xml_length, const char *url = "untitled.xml");
//----------------------------------------------------------------------
// If \a name is NULL, just get the root element node, else only return
// a value XMLNode if the name of the root element matches \a name.
//----------------------------------------------------------------------
XMLNode
GetRootElement(const char *required_name = nullptr);
static void
ErrorCallback (void *ctx, const char *format, ...);
static bool
XMLEnabled ();
protected:
XMLDocumentImpl m_document;
StreamString m_errors;
};
class ApplePropertyList
{
public:
ApplePropertyList();
ApplePropertyList(const char *path);
bool
ParseFile (const char *path);
explicit operator bool() const
{
return IsValid();
}
bool
IsValid() const;
XMLNode
GetValueNode (const char *key) const;
bool
GetValueAsString (const char *key, std::string &value) const;
protected:
// Using a node returned from GetValueNode() extract its value as a
// string (if possible). Array and dictionary nodes will return false
// as they have no string value. Boolean nodes will return true and
// \a value will be "true" or "false" as the string value comes from
// the element name itself. All other nodes will return the text
// content of the XMLNode.
static bool
ExtractStringFromValueNode (const XMLNode &node, std::string &value);
XMLDocument m_xml_doc;
XMLNode m_dict_node;
};
} // namespace lldb_private
#endif // liblldb_XML_h_

View File

@ -71,15 +71,10 @@
23059A101958B319007B8189 /* SBUnixSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23059A0F1958B319007B8189 /* SBUnixSignals.cpp */; };
23059A121958B3B2007B8189 /* SBUnixSignals.h in Headers */ = {isa = PBXBuildFile; fileRef = 23059A111958B37B007B8189 /* SBUnixSignals.h */; settings = {ATTRIBUTES = (Public, ); }; };
232CB615191E00CD00EF39FC /* NativeBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */; };
232CB616191E00CD00EF39FC /* NativeBreakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 232CB60C191E00CC00EF39FC /* NativeBreakpoint.h */; };
232CB617191E00CD00EF39FC /* NativeBreakpointList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */; };
232CB618191E00CD00EF39FC /* NativeBreakpointList.h in Headers */ = {isa = PBXBuildFile; fileRef = 232CB60E191E00CC00EF39FC /* NativeBreakpointList.h */; };
232CB619191E00CD00EF39FC /* NativeProcessProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */; };
232CB61A191E00CD00EF39FC /* NativeProcessProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 232CB610191E00CC00EF39FC /* NativeProcessProtocol.h */; };
232CB61B191E00CD00EF39FC /* NativeThreadProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */; };
232CB61C191E00CD00EF39FC /* NativeThreadProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 232CB612191E00CC00EF39FC /* NativeThreadProtocol.h */; };
232CB61D191E00CD00EF39FC /* SoftwareBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */; };
232CB61E191E00CD00EF39FC /* SoftwareBreakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 232CB614191E00CD00EF39FC /* SoftwareBreakpoint.h */; };
233B007D1960C9F90090E598 /* ProcessInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B007B1960C9E60090E598 /* ProcessInfo.cpp */; };
233B007F1960CB280090E598 /* ProcessLaunchInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B007E1960CB280090E598 /* ProcessLaunchInfo.cpp */; };
236124A41986B4E2004EFC37 /* IOObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 236124A21986B4E2004EFC37 /* IOObject.cpp */; };
@ -336,6 +331,10 @@
26744EF11338317700EF765A /* GDBRemoteCommunicationClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */; };
26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */; };
26780C611867C33D00234593 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2670F8111862B44A006B332C /* libncurses.dylib */; };
267A47FB1B1411C40021A5BC /* NativeRegisterContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267A47FA1B1411C40021A5BC /* NativeRegisterContext.cpp */; };
267A47FD1B1411CC0021A5BC /* NativeRegisterContextRegisterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267A47FC1B1411CC0021A5BC /* NativeRegisterContextRegisterInfo.cpp */; };
267A47FF1B1411D90021A5BC /* NativeWatchpointList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267A47FE1B1411D90021A5BC /* NativeWatchpointList.cpp */; };
267A48011B1411E40021A5BC /* XML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267A48001B1411E40021A5BC /* XML.cpp */; };
267C012B136880DF006E963E /* OptionGroupValueObjectDisplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */; };
267C01371368C49C006E963E /* OptionGroupOutputFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BCFC531368B3E4006DC050 /* OptionGroupOutputFile.cpp */; };
267DFB461B06752A00000FB7 /* MICmdArgValPrintValues.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267DFB441B06752A00000FB7 /* MICmdArgValPrintValues.cpp */; };
@ -1196,15 +1195,10 @@
23059A111958B37B007B8189 /* SBUnixSignals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBUnixSignals.h; path = include/lldb/API/SBUnixSignals.h; sourceTree = "<group>"; };
23173F8B192BA93F005C708F /* lldb-x86-register-enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-x86-register-enums.h"; path = "Utility/lldb-x86-register-enums.h"; sourceTree = "<group>"; };
232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpoint.cpp; path = source/Host/common/NativeBreakpoint.cpp; sourceTree = "<group>"; };
232CB60C191E00CC00EF39FC /* NativeBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeBreakpoint.h; path = source/Host/common/NativeBreakpoint.h; sourceTree = "<group>"; };
232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpointList.cpp; path = source/Host/common/NativeBreakpointList.cpp; sourceTree = "<group>"; };
232CB60E191E00CC00EF39FC /* NativeBreakpointList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeBreakpointList.h; path = source/Host/common/NativeBreakpointList.h; sourceTree = "<group>"; };
232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = NativeProcessProtocol.cpp; path = source/Host/common/NativeProcessProtocol.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
232CB610191E00CC00EF39FC /* NativeProcessProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeProcessProtocol.h; path = source/Host/common/NativeProcessProtocol.h; sourceTree = "<group>"; };
232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeThreadProtocol.cpp; path = source/Host/common/NativeThreadProtocol.cpp; sourceTree = "<group>"; };
232CB612191E00CC00EF39FC /* NativeThreadProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeThreadProtocol.h; path = source/Host/common/NativeThreadProtocol.h; sourceTree = "<group>"; };
232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SoftwareBreakpoint.cpp; path = source/Host/common/SoftwareBreakpoint.cpp; sourceTree = "<group>"; };
232CB614191E00CD00EF39FC /* SoftwareBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SoftwareBreakpoint.h; path = source/Host/common/SoftwareBreakpoint.h; sourceTree = "<group>"; };
232CB62B19213AC200EF39FC /* NativeProcessLinux.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NativeProcessLinux.cpp; sourceTree = "<group>"; };
232CB62C19213AC200EF39FC /* NativeProcessLinux.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = NativeProcessLinux.h; sourceTree = "<group>"; };
232CB62D19213AC200EF39FC /* NativeThreadLinux.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NativeThreadLinux.cpp; sourceTree = "<group>"; };
@ -1737,6 +1731,19 @@
2675F6FF1332BE690067997B /* PlatformRemoteiOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformRemoteiOS.h; sourceTree = "<group>"; };
2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractorGDBRemote.cpp; path = source/Utility/StringExtractorGDBRemote.cpp; sourceTree = "<group>"; };
2676A094119C93C8008A98EF /* StringExtractorGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringExtractorGDBRemote.h; path = source/Utility/StringExtractorGDBRemote.h; sourceTree = "<group>"; };
267A47F21B14115A0021A5BC /* SoftwareBreakpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SoftwareBreakpoint.h; path = include/lldb/Host/common/SoftwareBreakpoint.h; sourceTree = "<group>"; };
267A47F31B14116E0021A5BC /* NativeBreakpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeBreakpoint.h; path = include/lldb/Host/common/NativeBreakpoint.h; sourceTree = "<group>"; };
267A47F41B1411750021A5BC /* NativeBreakpointList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeBreakpointList.h; path = include/lldb/Host/common/NativeBreakpointList.h; sourceTree = "<group>"; };
267A47F51B14117F0021A5BC /* NativeProcessProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeProcessProtocol.h; path = include/lldb/Host/common/NativeProcessProtocol.h; sourceTree = "<group>"; };
267A47F61B14118F0021A5BC /* NativeRegisterContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeRegisterContext.h; path = include/lldb/Host/common/NativeRegisterContext.h; sourceTree = "<group>"; };
267A47F71B14119A0021A5BC /* NativeRegisterContextRegisterInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeRegisterContextRegisterInfo.h; path = include/lldb/Host/common/NativeRegisterContextRegisterInfo.h; sourceTree = "<group>"; };
267A47F81B1411A40021A5BC /* NativeThreadProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeThreadProtocol.h; path = include/lldb/Host/common/NativeThreadProtocol.h; sourceTree = "<group>"; };
267A47F91B1411AC0021A5BC /* NativeWatchpointList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeWatchpointList.h; path = include/lldb/Host/common/NativeWatchpointList.h; sourceTree = "<group>"; };
267A47FA1B1411C40021A5BC /* NativeRegisterContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContext.cpp; path = source/Host/common/NativeRegisterContext.cpp; sourceTree = "<group>"; };
267A47FC1B1411CC0021A5BC /* NativeRegisterContextRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContextRegisterInfo.cpp; path = source/Host/common/NativeRegisterContextRegisterInfo.cpp; sourceTree = "<group>"; };
267A47FE1B1411D90021A5BC /* NativeWatchpointList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeWatchpointList.cpp; path = source/Host/common/NativeWatchpointList.cpp; sourceTree = "<group>"; };
267A48001B1411E40021A5BC /* XML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = XML.cpp; path = source/Host/common/XML.cpp; sourceTree = "<group>"; };
267A48031B1416080021A5BC /* XML.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = XML.h; path = include/lldb/Host/XML.h; sourceTree = "<group>"; };
267C0128136880C7006E963E /* OptionGroupValueObjectDisplay.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupValueObjectDisplay.h; path = include/lldb/Interpreter/OptionGroupValueObjectDisplay.h; sourceTree = "<group>"; };
267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupValueObjectDisplay.cpp; path = source/Interpreter/OptionGroupValueObjectDisplay.cpp; sourceTree = "<group>"; };
267DFB441B06752A00000FB7 /* MICmdArgValPrintValues.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValPrintValues.cpp; path = "tools/lldb-mi/MICmdArgValPrintValues.cpp"; sourceTree = SOURCE_ROOT; };
@ -4418,14 +4425,20 @@
3FDFE57519AFABFD009756A7 /* HostThread.h */,
236124A61986B50E004EFC37 /* IOObject.h */,
26BC7DD510F1B7D500F91463 /* Mutex.h */,
267A47F31B14116E0021A5BC /* NativeBreakpoint.h */,
232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */,
232CB60C191E00CC00EF39FC /* NativeBreakpoint.h */,
267A47F41B1411750021A5BC /* NativeBreakpointList.h */,
232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */,
232CB60E191E00CC00EF39FC /* NativeBreakpointList.h */,
267A47F51B14117F0021A5BC /* NativeProcessProtocol.h */,
232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */,
232CB610191E00CC00EF39FC /* NativeProcessProtocol.h */,
267A47F61B14118F0021A5BC /* NativeRegisterContext.h */,
267A47FA1B1411C40021A5BC /* NativeRegisterContext.cpp */,
267A47F71B14119A0021A5BC /* NativeRegisterContextRegisterInfo.h */,
267A47FC1B1411CC0021A5BC /* NativeRegisterContextRegisterInfo.cpp */,
267A47F81B1411A40021A5BC /* NativeThreadProtocol.h */,
232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */,
232CB612191E00CC00EF39FC /* NativeThreadProtocol.h */,
267A47F91B1411AC0021A5BC /* NativeWatchpointList.h */,
267A47FE1B1411D90021A5BC /* NativeWatchpointList.cpp */,
A36FF33D17D8E98800244D40 /* OptionParser.h */,
260A39A519647A3A004B4130 /* Pipe.h */,
3F5E8AF31A40D4A500A73232 /* PipeBase.h */,
@ -4434,14 +4447,16 @@
236124A71986B50E004EFC37 /* Socket.h */,
26D7E45B13D5E2F9007FD12B /* SocketAddress.h */,
26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */,
267A47F21B14115A0021A5BC /* SoftwareBreakpoint.h */,
232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */,
232CB614191E00CD00EF39FC /* SoftwareBreakpoint.h */,
2689B0A4113EE3CD00A4AEDB /* Symbols.h */,
268DA871130095D000C9483A /* Terminal.h */,
3FDFED0D19B7D269009756A7 /* ThisThread.cpp */,
3FDFED0919B7C8C7009756A7 /* ThisThread.h */,
3FDFED2319BA6D55009756A7 /* ThreadLauncher.h */,
26B4E26E112F35F700AB3F64 /* TimeValue.h */,
267A48031B1416080021A5BC /* XML.h */,
267A48001B1411E40021A5BC /* XML.cpp */,
);
name = Host;
sourceTree = "<group>";
@ -5435,7 +5450,6 @@
AF1F7B08189C904B0087DB9C /* AppleGetPendingItemsHandler.h in Headers */,
AF77E0AA1A033D740096C0EA /* RegisterContextPOSIXCore_powerpc.h in Headers */,
AF2BCA6D18C7EFDE005B4526 /* JITLoaderGDB.h in Headers */,
232CB61E191E00CD00EF39FC /* SoftwareBreakpoint.h in Headers */,
B5EFAE871AE53B1D007059F3 /* RegisterContextFreeBSD_arm.h in Headers */,
26BC17B218C7F4CB00D2196D /* ThreadElfCore.h in Headers */,
AF77E0A51A033D360096C0EA /* RegisterContextPOSIX_powerpc.h in Headers */,
@ -5461,7 +5475,6 @@
260CC63115D04377002BF2E0 /* OptionValueProperties.h in Headers */,
260CC63215D04377002BF2E0 /* OptionValueDictionary.h in Headers */,
262173A118395D3800C52091 /* SectionLoadHistory.h in Headers */,
232CB61A191E00CD00EF39FC /* NativeProcessProtocol.h in Headers */,
260CC63315D04377002BF2E0 /* OptionValueEnumeration.h in Headers */,
AF45FDE618A1F3AC0007051C /* AppleGetThreadItemInfoHandler.h in Headers */,
260A63171861008E00FECF8E /* IOHandler.h in Headers */,
@ -5515,10 +5528,7 @@
49724D9A1AD6ED390033C538 /* RenderScriptRuntime.h in Headers */,
4C73152219B7D71700F865A4 /* Iterable.h in Headers */,
2698699D15E6CBD0002415FF /* OperatingSystemPython.h in Headers */,
232CB618191E00CD00EF39FC /* NativeBreakpointList.h in Headers */,
260D9B2715EC369500960137 /* ModuleSpec.h in Headers */,
232CB61C191E00CD00EF39FC /* NativeThreadProtocol.h in Headers */,
232CB616191E00CD00EF39FC /* NativeBreakpoint.h in Headers */,
947A1D651616476B0017C8D1 /* CommandObjectPlugin.h in Headers */,
262ED0051631FA2800879631 /* OptionGroupString.h in Headers */,
26474CA918D0CB070073DEBA /* RegisterContextFreeBSD_i386.h in Headers */,
@ -6029,6 +6039,7 @@
2689FFDA13353D9D00698AC0 /* lldb.cpp in Sources */,
26474CCD18D0CB5B0073DEBA /* RegisterContextPOSIX_x86.cpp in Sources */,
2689FFEF13353DB600698AC0 /* Breakpoint.cpp in Sources */,
267A47FB1B1411C40021A5BC /* NativeRegisterContext.cpp in Sources */,
2689FFF113353DB600698AC0 /* BreakpointID.cpp in Sources */,
AF77E0A91A033D740096C0EA /* RegisterContextPOSIXCore_powerpc.cpp in Sources */,
2689FFF313353DB600698AC0 /* BreakpointIDList.cpp in Sources */,
@ -6088,6 +6099,7 @@
2689002413353DDE00698AC0 /* CommandObjectSettings.cpp in Sources */,
2689002513353DDE00698AC0 /* CommandObjectSource.cpp in Sources */,
2689002613353DDE00698AC0 /* CommandObjectSyntax.cpp in Sources */,
267A48011B1411E40021A5BC /* XML.cpp in Sources */,
3F8169331ABB7A6D001DA9DF /* SystemLifetimeManager.cpp in Sources */,
4959511F1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp in Sources */,
26BC179918C7F2B300D2196D /* JITLoader.cpp in Sources */,
@ -6256,6 +6268,7 @@
3FDFE56C19AF9C44009756A7 /* HostProcessPosix.cpp in Sources */,
268900B413353E5000698AC0 /* RegisterContextMacOSXFrameBackchain.cpp in Sources */,
3F8169311ABB7A6D001DA9DF /* SystemInitializer.cpp in Sources */,
267A47FD1B1411CC0021A5BC /* NativeRegisterContextRegisterInfo.cpp in Sources */,
3FDFED2D19C257A0009756A7 /* HostProcess.cpp in Sources */,
268900B513353E5000698AC0 /* StopInfoMachException.cpp in Sources */,
268900B613353E5000698AC0 /* UnwindMacOSXFrameBackchain.cpp in Sources */,
@ -6467,6 +6480,7 @@
26D7E45D13D5E30A007FD12B /* SocketAddress.cpp in Sources */,
94CD7D0C19A3FBCE00908B7C /* AppleObjCTypeEncodingParser.cpp in Sources */,
94B6E76213D88365005F417F /* ValueObjectSyntheticFilter.cpp in Sources */,
267A47FF1B1411D90021A5BC /* NativeWatchpointList.cpp in Sources */,
26F4A21C13FBA31A0064B613 /* ThreadMemory.cpp in Sources */,
94EA27CE17DE91750070F505 /* LibCxxUnorderedMap.cpp in Sources */,
266DFE9713FD656E00D0C574 /* OperatingSystem.cpp in Sources */,

View File

@ -37,6 +37,7 @@ add_host_subdirectory(common
common/ThisThread.cpp
common/ThreadLauncher.cpp
common/TimeValue.cpp
common/XML.cpp
)
if (NOT LLDB_DISABLE_LIBEDIT)

View File

@ -0,0 +1,548 @@
//===-- XML.cpp -------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Host/XML.h"
using namespace lldb;
using namespace lldb_private;
#pragma mark -- XMLDocument
XMLDocument::XMLDocument () :
m_document (nullptr)
{
}
XMLDocument::~XMLDocument ()
{
Clear();
}
void
XMLDocument::Clear()
{
#if defined( LIBXML2_DEFINED )
if (m_document)
{
xmlDocPtr doc = m_document;
m_document = nullptr;
xmlFreeDoc(doc);
}
#endif
}
bool
XMLDocument::IsValid() const
{
return m_document != nullptr;
}
void
XMLDocument::ErrorCallback (void *ctx, const char *format, ...)
{
XMLDocument *document = (XMLDocument *)ctx;
va_list args;
va_start (args, format);
document->m_errors.PrintfVarArg(format, args);
document->m_errors.EOL();
va_end (args);
}
bool
XMLDocument::ParseFile (const char *path)
{
#if defined( LIBXML2_DEFINED )
Clear();
xmlSetGenericErrorFunc( (void *)this, XMLDocument::ErrorCallback );
m_document = xmlParseFile(path);
xmlSetGenericErrorFunc(nullptr, nullptr);
#endif
return IsValid();
}
bool
XMLDocument::ParseMemory (const char *xml, size_t xml_length, const char *url)
{
#if defined( LIBXML2_DEFINED )
Clear();
xmlSetGenericErrorFunc( (void *)this, XMLDocument::ErrorCallback );
m_document = xmlReadMemory(xml, (int)xml_length, url, nullptr, 0);
xmlSetGenericErrorFunc(nullptr, nullptr);
#endif
return IsValid();
}
XMLNode
XMLDocument::GetRootElement(const char *required_name)
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
{
XMLNode root_node(xmlDocGetRootElement(m_document));
if (required_name)
{
llvm::StringRef actual_name = root_node.GetName();
if (actual_name == required_name)
return root_node;
}
else
{
return root_node;
}
}
#endif
return XMLNode();
}
bool
XMLDocument::XMLEnabled ()
{
#if defined( LIBXML2_DEFINED )
return true;
#else
return false;
#endif
}
#pragma mark -- XMLNode
XMLNode::XMLNode() :
m_node(nullptr)
{
}
XMLNode::XMLNode(XMLNodeImpl node) :
m_node(node)
{
}
XMLNode::~XMLNode()
{
}
void
XMLNode::Clear()
{
m_node = nullptr;
}
XMLNode
XMLNode::GetParent() const
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
return XMLNode(m_node->parent);
else
return XMLNode();
#else
return XMLNode();
#endif
}
XMLNode
XMLNode::GetSibling() const
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
return XMLNode(m_node->next);
else
return XMLNode();
#else
return XMLNode();
#endif
}
XMLNode
XMLNode::GetChild () const
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
return XMLNode(m_node->children);
else
return XMLNode();
#else
return XMLNode();
#endif
}
llvm::StringRef
XMLNode::GetAttributeValue(const char *name, const char *fail_value) const
{
const char *attr_value = NULL;
#if defined( LIBXML2_DEFINED )
if (IsValid())
attr_value = (const char *)xmlGetProp(m_node, (const xmlChar *)name);
else
attr_value = fail_value;
#else
attr_value = fail_value;
#endif
if (attr_value)
return llvm::StringRef(attr_value);
else
return llvm::StringRef();
}
void
XMLNode::ForEachChildNode (NodeCallback const &callback) const
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
GetChild().ForEachSiblingNode(callback);
#endif
}
void
XMLNode::ForEachChildElement (NodeCallback const &callback) const
{
#if defined( LIBXML2_DEFINED )
XMLNode child = GetChild();
if (child)
child.ForEachSiblingElement(callback);
#endif
}
void
XMLNode::ForEachChildElementWithName (const char *name, NodeCallback const &callback) const
{
#if defined( LIBXML2_DEFINED )
XMLNode child = GetChild();
if (child)
child.ForEachSiblingElementWithName(name, callback);
#endif
}
void
XMLNode::ForEachAttribute (AttributeCallback const &callback) const
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
{
for (xmlAttrPtr attr = m_node->properties; attr != nullptr; attr=attr->next)
{
// check if name matches
if (attr->name)
{
// check child is a text node
xmlNodePtr child = attr->children;
if (child->type == XML_TEXT_NODE)
{
llvm::StringRef attr_value;
if (child->content)
attr_value = llvm::StringRef((const char *)child->content);
if (callback(llvm::StringRef((const char *)attr->name), attr_value) == false)
return;
}
}
}
}
#endif
}
void
XMLNode::ForEachSiblingNode (NodeCallback const &callback) const
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
{
// iterate through all siblings
for (xmlNodePtr node = m_node; node; node=node->next)
{
if (callback(XMLNode(node)) == false)
return;
}
}
#endif
}
void
XMLNode::ForEachSiblingElement (NodeCallback const &callback) const
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
{
// iterate through all siblings
for (xmlNodePtr node = m_node; node; node=node->next)
{
// we are looking for element nodes only
if (node->type != XML_ELEMENT_NODE)
continue;
if (callback(XMLNode(node)) == false)
return;
}
}
#endif
}
void
XMLNode::ForEachSiblingElementWithName (const char *name, NodeCallback const &callback) const
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
{
// iterate through all siblings
for (xmlNodePtr node = m_node; node; node=node->next)
{
// we are looking for element nodes only
if (node->type != XML_ELEMENT_NODE)
continue;
// If name is nullptr, we take all nodes of type "t", else
// just the ones whose name matches
if (name)
{
if (strcmp((const char *)node->name, name) != 0)
continue; // Name mismatch, ignore this one
}
else
{
if (node->name)
continue; // nullptr name specified and this elemnt has a name, ignore this one
}
if (callback(XMLNode(node)) == false)
return;
}
}
#endif
}
llvm::StringRef
XMLNode::GetName() const
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
{
if (m_node->name)
return llvm::StringRef((const char *)m_node->name);
}
#endif
return llvm::StringRef();
}
bool
XMLNode::GetElementText (std::string &text) const
{
text.clear();
#if defined( LIBXML2_DEFINED )
if (IsValid())
{
bool success = false;
if (m_node->type == XML_ELEMENT_NODE)
{
// check child is a text node
for (xmlNodePtr node = m_node->children;
node != nullptr;
node = node->next)
{
if (node->type == XML_TEXT_NODE)
{
text.append((const char *)node->content);
success = true;
}
}
}
return success;
}
#endif
return false;
}
bool
XMLNode::NameIs (const char *name) const
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
{
// In case we are looking for a nullptr name or an exact pointer match
if (m_node->name == (const xmlChar *)name)
return true;
if (m_node->name)
return strcmp((const char *)m_node->name, name) == 0;
}
#endif
return false;
}
XMLNode
XMLNode::FindFirstChildElementWithName (const char *name) const
{
XMLNode result_node;
#if defined( LIBXML2_DEFINED )
ForEachChildElementWithName(name, [&result_node, name](const XMLNode& node) -> bool {
result_node = node;
// Stop iterating, we found the node we wanted
return false;
});
#endif
return result_node;
}
bool
XMLNode::IsValid() const
{
return m_node != nullptr;
}
bool
XMLNode::IsElement () const
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
return m_node->type == XML_ELEMENT_NODE;
#endif
return false;
}
XMLNode
XMLNode::GetElementForPath (const NamePath &path)
{
#if defined( LIBXML2_DEFINED )
if (IsValid())
{
if (path.empty())
return *this;
else
{
XMLNode node = FindFirstChildElementWithName(path[0].c_str());
const size_t n = path.size();
for (size_t i=1; node && i<n; ++i)
node = node.FindFirstChildElementWithName(path[i].c_str());
return node;
}
}
#endif
return XMLNode();
}
#pragma mark -- ApplePropertyList
ApplePropertyList::ApplePropertyList() :
m_xml_doc(),
m_dict_node()
{
}
ApplePropertyList::ApplePropertyList (const char *path) :
m_xml_doc(),
m_dict_node()
{
ParseFile(path);
}
bool
ApplePropertyList::ParseFile (const char *path)
{
if (m_xml_doc.ParseFile(path))
{
XMLNode plist = m_xml_doc.GetRootElement("plist");
if (plist)
{
plist.ForEachChildElementWithName("dict", [this](const XMLNode &dict) -> bool {
this->m_dict_node = dict;
return false; // Stop iterating
});
return (bool)m_dict_node;
}
}
return false;
}
bool
ApplePropertyList::IsValid() const
{
return (bool)m_dict_node;
}
bool
ApplePropertyList::GetValueAsString (const char *key, std::string &value) const
{
XMLNode value_node = GetValueNode (key);
if (value_node)
return ApplePropertyList::ExtractStringFromValueNode(value_node, value);
return false;
}
XMLNode
ApplePropertyList::GetValueNode (const char *key) const
{
XMLNode value_node;
#if defined( LIBXML2_DEFINED )
if (IsValid())
{
m_dict_node.ForEachChildElementWithName("key", [key, &value_node](const XMLNode &key_node) -> bool {
std::string key_name;
if (key_node.GetElementText(key_name))
{
if (key_name.compare(key) == 0)
{
value_node = key_node.GetSibling();
while (value_node && !value_node.IsElement())
value_node = value_node.GetSibling();
return false; // Stop iterating
}
}
return true; // Keep iterating
});
}
#endif
return value_node;
}
bool
ApplePropertyList::ExtractStringFromValueNode (const XMLNode &node, std::string &value)
{
value.clear();
#if defined( LIBXML2_DEFINED )
if (node.IsValid())
{
llvm::StringRef element_name = node.GetName();
if (element_name == "true" or element_name == "false")
{
// The text value _is_ the element name itself...
value = std::move(element_name.str());
return true;
}
else if (element_name == "dict" or element_name == "array")
return false; // dictionaries and arrays have no text value, so we fail
else
return node.GetElementText(value);
}
#endif
return false;
}

View File

@ -146,7 +146,7 @@ OperatingSystemPython::GetDynamicRegisterInfo ()
if (!dictionary)
return NULL;
m_register_info_ap.reset(new DynamicRegisterInfo(*dictionary, m_process->GetTarget().GetArchitecture().GetByteOrder()));
m_register_info_ap.reset(new DynamicRegisterInfo(*dictionary, m_process->GetTarget().GetArchitecture()));
assert (m_register_info_ap->GetNumRegisters() > 0);
assert (m_register_info_ap->GetNumRegisterSets() > 0);
}

View File

@ -742,4 +742,4 @@ PlatformWindows::GetEnvironment(StringList &env)
}
return Host::GetEnvironment(env);
}
}

View File

@ -15,11 +15,12 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Host/StringConvert.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/StringConvert.h"
using namespace lldb;
using namespace lldb_private;
@ -36,17 +37,18 @@ DynamicRegisterInfo::DynamicRegisterInfo () :
{
}
DynamicRegisterInfo::DynamicRegisterInfo(const StructuredData::Dictionary &dict, ByteOrder byte_order)
: m_regs()
, m_sets()
, m_set_reg_nums()
, m_set_names()
, m_value_regs_map()
, m_invalidate_regs_map()
, m_reg_data_byte_size(0)
, m_finalized(false)
DynamicRegisterInfo::DynamicRegisterInfo(const lldb_private::StructuredData::Dictionary &dict,
const lldb_private::ArchSpec &arch) :
m_regs (),
m_sets (),
m_set_reg_nums (),
m_set_names (),
m_value_regs_map (),
m_invalidate_regs_map (),
m_reg_data_byte_size (0),
m_finalized (false)
{
SetRegisterInfo (dict, byte_order);
SetRegisterInfo (dict, arch);
}
DynamicRegisterInfo::~DynamicRegisterInfo ()
@ -54,7 +56,7 @@ DynamicRegisterInfo::~DynamicRegisterInfo ()
}
size_t
DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, ByteOrder byte_order)
DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, const ArchSpec &arch)
{
assert(!m_finalized);
StructuredData::Array *sets = nullptr;
@ -121,6 +123,8 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, Byt
reg_info_dict->GetValueForKeyAsInteger("offset", reg_info.byte_offset, UINT32_MAX);
const ByteOrder byte_order = arch.GetByteOrder();
if (reg_info.byte_offset == UINT32_MAX)
{
// No offset for this register, see if the register has a value expression
@ -384,7 +388,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, Byt
m_regs.push_back(reg_info);
m_set_reg_nums[set].push_back(i);
}
Finalize();
Finalize(arch);
return m_regs.size();
}
@ -423,7 +427,7 @@ DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info,
}
void
DynamicRegisterInfo::Finalize ()
DynamicRegisterInfo::Finalize (const ArchSpec &arch)
{
if (m_finalized)
return;
@ -518,6 +522,95 @@ DynamicRegisterInfo::Finalize ()
else
m_regs[i].invalidate_regs = NULL;
}
// Check if we need to automatically set the generic registers in case
// they weren't set
bool generic_regs_specified = false;
for (const auto &reg: m_regs)
{
if (reg.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
{
generic_regs_specified = true;
break;
}
}
if (!generic_regs_specified)
{
switch (arch.GetMachine())
{
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
for (auto &reg: m_regs)
{
if (strcmp(reg.name, "pc") == 0)
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
else if ((strcmp(reg.name, "fp") == 0) || (strcmp(reg.name, "x29") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
else if ((strcmp(reg.name, "lr") == 0) || (strcmp(reg.name, "x30") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
else if ((strcmp(reg.name, "sp") == 0) || (strcmp(reg.name, "x31") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
else if (strcmp(reg.name, "cpsr") == 0)
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
}
break;
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
for (auto &reg: m_regs)
{
if ((strcmp(reg.name, "pc") == 0) || (strcmp(reg.name, "r15") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
else if ((strcmp(reg.name, "sp") == 0) || (strcmp(reg.name, "r13") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
else if ((strcmp(reg.name, "lr") == 0) || (strcmp(reg.name, "r14") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
else if ((strcmp(reg.name, "r7") == 0) && arch.GetTriple().getVendor() == llvm::Triple::Apple)
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
else if ((strcmp(reg.name, "r11") == 0) && arch.GetTriple().getVendor() != llvm::Triple::Apple)
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
else if (strcmp(reg.name, "fp") == 0)
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
else if (strcmp(reg.name, "cpsr") == 0)
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
}
break;
case llvm::Triple::x86:
for (auto &reg: m_regs)
{
if ((strcmp(reg.name, "eip") == 0) || (strcmp(reg.name, "pc") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
else if ((strcmp(reg.name, "esp") == 0) || (strcmp(reg.name, "sp") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
else if ((strcmp(reg.name, "ebp") == 0) || (strcmp(reg.name, "fp") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
else if ((strcmp(reg.name, "eflags") == 0) || (strcmp(reg.name, "flags") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
}
break;
case llvm::Triple::x86_64:
for (auto &reg: m_regs)
{
if ((strcmp(reg.name, "rip") == 0) || (strcmp(reg.name, "pc") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
else if ((strcmp(reg.name, "rsp") == 0) || (strcmp(reg.name, "sp") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
else if ((strcmp(reg.name, "rbp") == 0) || (strcmp(reg.name, "fp") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
else if ((strcmp(reg.name, "rflags") == 0) || (strcmp(reg.name, "flags") == 0))
reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
}
break;
default:
break;
}
}
}
size_t

View File

@ -26,12 +26,14 @@ class DynamicRegisterInfo
public:
DynamicRegisterInfo ();
DynamicRegisterInfo(const lldb_private::StructuredData::Dictionary &dict, lldb::ByteOrder byte_order);
DynamicRegisterInfo(const lldb_private::StructuredData::Dictionary &dict,
const lldb_private::ArchSpec &arch);
virtual
~DynamicRegisterInfo ();
size_t SetRegisterInfo(const lldb_private::StructuredData::Dictionary &dict, lldb::ByteOrder byte_order);
size_t SetRegisterInfo(const lldb_private::StructuredData::Dictionary &dict,
const lldb_private::ArchSpec &arch);
void
AddRegister (lldb_private::RegisterInfo &reg_info,
@ -40,7 +42,7 @@ public:
lldb_private::ConstString &set_name);
void
Finalize ();
Finalize (const lldb_private::ArchSpec &arch);
size_t
GetNumRegisters() const;

View File

@ -3929,9 +3929,12 @@ GDBRemoteCommunicationClient::ReadExtFeature (const lldb_private::ConstString ob
std::stringstream output;
StringExtractorGDBRemote chunk;
const int size = 0xfff;
int offset = 0;
bool active = true;
uint64_t size = GetRemoteMaxPacketSize();
if (size == 0)
size = 0x1000;
size = size - 1; // Leave space for the 'm' or 'l' character in the response
int offset = 0;
bool active = true;
// loop until all data has been read
while ( active ) {

File diff suppressed because it is too large Load Diff

View File

@ -9,11 +9,6 @@
#include "SymbolVendorMacOSX.h"
#if defined( LIBXML2_DEFINED )
#include <libxml/parser.h>
#include <libxml/tree.h>
#endif // #if defined( LIBXML2_DEFINED )
#include <string.h>
#include "lldb/Core/Module.h"
@ -24,6 +19,7 @@
#include "lldb/Core/Timer.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Host/XML.h"
#include "lldb/Symbol/ObjectFile.h"
using namespace lldb;
@ -177,103 +173,39 @@ SymbolVendorMacOSX::CreateInstance (const lldb::ModuleSP &module_sp, lldb_privat
dsym_objfile_sp = ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(), dsym_file_data_sp, dsym_file_data_offset);
if (UUIDsMatch(module_sp.get(), dsym_objfile_sp.get(), feedback_strm))
{
#if defined( LIBXML2_DEFINED )
char dsym_path[PATH_MAX];
if (module_sp->GetSourceMappingList().IsEmpty() && dsym_fspec.GetPath(dsym_path, sizeof(dsym_path)))
// We need a XML parser if we hope to parse a plist...
if (XMLDocument::XMLEnabled())
{
lldb_private::UUID dsym_uuid;
if (dsym_objfile_sp->GetUUID(&dsym_uuid))
char dsym_path[PATH_MAX];
if (module_sp->GetSourceMappingList().IsEmpty() && dsym_fspec.GetPath(dsym_path, sizeof(dsym_path)))
{
std::string uuid_str = dsym_uuid.GetAsString ();
if (!uuid_str.empty())
lldb_private::UUID dsym_uuid;
if (dsym_objfile_sp->GetUUID(&dsym_uuid))
{
char *resources = strstr (dsym_path, "/Contents/Resources/");
if (resources)
std::string uuid_str = dsym_uuid.GetAsString ();
if (!uuid_str.empty())
{
char dsym_uuid_plist_path[PATH_MAX];
resources[strlen("/Contents/Resources/")] = '\0';
snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path), "%s%s.plist", dsym_path, uuid_str.c_str());
FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path, false);
if (dsym_uuid_plist_spec.Exists())
char *resources = strstr (dsym_path, "/Contents/Resources/");
if (resources)
{
xmlDoc *doc = ::xmlReadFile (dsym_uuid_plist_path, NULL, 0);
if (doc)
char dsym_uuid_plist_path[PATH_MAX];
resources[strlen("/Contents/Resources/")] = '\0';
snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path), "%s%s.plist", dsym_path, uuid_str.c_str());
FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path, false);
if (dsym_uuid_plist_spec.Exists())
{
char DBGBuildSourcePath[PATH_MAX];
char DBGSourcePath[PATH_MAX];
DBGBuildSourcePath[0] = '\0';
DBGSourcePath[0] = '\0';
for (xmlNode *node = doc->children; node; node = node ? node->next : NULL)
ApplePropertyList plist(dsym_uuid_plist_path);
if (plist)
{
if (node->type == XML_ELEMENT_NODE)
{
if (node->name && strcmp((const char*)node->name, "plist") == 0)
{
xmlNode *dict_node = node->children;
while (dict_node && dict_node->type != XML_ELEMENT_NODE)
dict_node = dict_node->next;
if (dict_node && dict_node->name && strcmp((const char *)dict_node->name, "dict") == 0)
{
for (xmlNode *key_node = dict_node->children; key_node; key_node = key_node->next)
{
if (key_node && key_node->type == XML_ELEMENT_NODE && key_node->name)
{
if (strcmp((const char *)key_node->name, "key") == 0)
{
const char *key_name = (const char *)::xmlNodeGetContent(key_node);
if (strcmp(key_name, "DBGBuildSourcePath") == 0)
{
xmlNode *value_node = key_node->next;
while (value_node && value_node->type != XML_ELEMENT_NODE)
value_node = value_node->next;
if (value_node && value_node->name)
{
if (strcmp((const char *)value_node->name, "string") == 0)
{
const char *node_content = (const char *)::xmlNodeGetContent(value_node);
if (node_content)
{
::snprintf(DBGBuildSourcePath, sizeof(DBGBuildSourcePath), "%s", node_content);
xmlFree((void *) node_content);
}
}
key_node = value_node;
}
}
else if (strcmp(key_name, "DBGSourcePath") == 0)
{
xmlNode *value_node = key_node->next;
while (value_node && value_node->type != XML_ELEMENT_NODE)
value_node = value_node->next;
if (value_node && value_node->name)
{
if (strcmp((const char *)value_node->name, "string") == 0)
{
const char *node_content = (const char *)::xmlNodeGetContent(value_node);
if (node_content)
{
FileSpec resolved_source_path(node_content, true);
resolved_source_path.GetPath(DBGSourcePath, sizeof(DBGSourcePath));
xmlFree ((void *) node_content);
}
}
key_node = value_node;
}
}
if (key_name != NULL)
xmlFree((void *) key_name);
}
}
}
}
}
}
}
::xmlFreeDoc (doc);
std::string DBGBuildSourcePath;
std::string DBGSourcePath;
if (DBGBuildSourcePath[0] && DBGSourcePath[0])
{
module_sp->GetSourceMappingList().Append (ConstString(DBGBuildSourcePath), ConstString(DBGSourcePath), true);
plist.GetValueAsString("DBGBuildSourcePath", DBGBuildSourcePath);
plist.GetValueAsString("DBGSourcePath", DBGSourcePath);
if (DBGBuildSourcePath[0] && DBGSourcePath[0])
{
module_sp->GetSourceMappingList().Append (ConstString(DBGBuildSourcePath), ConstString(DBGSourcePath), true);
}
}
}
}
@ -281,7 +213,6 @@ SymbolVendorMacOSX::CreateInstance (const lldb::ModuleSP &module_sp, lldb_privat
}
}
}
#endif // #if defined( LIBXML2_DEFINED )
symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp);
return symbol_vendor;

View File

@ -1482,6 +1482,12 @@ DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, stru
return 0;
}
uint32_t
DNBGetRegisterCPUType()
{
return DNBArchProtocol::GetRegisterCPUType ();
}
//----------------------------------------------------------------------
// Get the register set information for a specific thread.
//----------------------------------------------------------------------

View File

@ -151,6 +151,7 @@ nub_bool_t DNBWatchpointSet (nub_process_t pid, nub_addr_t a
nub_bool_t DNBWatchpointClear (nub_process_t pid, nub_addr_t addr);
uint32_t DNBWatchpointGetNumSupportedHWP (nub_process_t pid);
uint32_t DNBGetRegisterCPUType ();
const DNBRegisterSetInfo *
DNBGetRegisterSetInfo (nub_size_t *num_reg_sets);
nub_bool_t DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info);

View File

@ -57,6 +57,15 @@ DNBArchProtocol::RegisterArchPlugin (const DNBArchPluginInfo &arch_info)
g_arch_plugins[arch_info.cpu_type] = arch_info;
}
uint32_t
DNBArchProtocol::GetRegisterCPUType ()
{
const DNBArchPluginInfo *arch_info = GetArchInfo ();
if (arch_info)
return arch_info->cpu_type;
return 0;
}
const DNBRegisterSetInfo *
DNBArchProtocol::GetRegisterSetInfo (nub_size_t *num_reg_sets)
{

View File

@ -43,6 +43,9 @@ public:
static DNBArchProtocol *
Create (MachThread *thread);
static uint32_t
GetRegisterCPUType ();
static const DNBRegisterSetInfo *
GetRegisterSetInfo (nub_size_t *num_reg_sets);

View File

@ -210,6 +210,7 @@ RNBRemote::CreatePacketTable ()
t.push_back (Packet (set_process_event, &RNBRemote::HandlePacket_QSetProcessEvent, NULL, "QSetProcessEvent:", "Set a process event, to be passed to the process, can be set before the process is started, or after."));
t.push_back (Packet (set_detach_on_error, &RNBRemote::HandlePacket_QSetDetachOnError, NULL, "QSetDetachOnError:", "Set whether debugserver will detach (1) or kill (0) from the process it is controlling if it loses connection to lldb."));
t.push_back (Packet (speed_test, &RNBRemote::HandlePacket_qSpeedTest, NULL, "qSpeedTest:", "Test the maximum speed at which packet can be sent/received."));
t.push_back (Packet (query_transfer, &RNBRemote::HandlePacket_qXfer, NULL, "qXfer:", "Support the qXfer packet."));
}
@ -3085,7 +3086,7 @@ RNBRemote::HandlePacket_qSupported (const char *p)
{
uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet size--debugger can always use less
char buf[64];
snprintf (buf, sizeof(buf), "PacketSize=%x", max_packet_size);
snprintf (buf, sizeof(buf), "qXfer:features:read+;PacketSize=%x", max_packet_size);
return SendPacket (buf);
}
@ -3979,38 +3980,94 @@ RNBRemote::HandlePacket_S (const char *p)
return rnb_success;
}
static const char *
GetArchName (const uint32_t cputype, const uint32_t cpusubtype)
{
switch (cputype)
{
case CPU_TYPE_ARM:
switch (cpusubtype)
{
case 5: return "armv4";
case 6: return "armv6";
case 7: return "armv5t";
case 8: return "xscale";
case 9: return "armv7";
case 10: return "armv7f";
case 11: return "armv7s";
case 12: return "armv7k";
case 14: return "armv6m";
case 15: return "armv7m";
case 16: return "armv7em";
default: return "arm";
}
break;
case CPU_TYPE_ARM64: return "arm64";
case CPU_TYPE_I386: return "i386";
case CPU_TYPE_X86_64:
switch (cpusubtype)
{
default: return "x86_64";
case 8: return "x86_64h";
}
break;
}
return NULL;
}
static bool
GetHostCPUType (uint32_t &cputype, uint32_t &cpusubtype, uint32_t &is_64_bit_capable, bool &promoted_to_64)
{
static uint32_t g_host_cputype = 0;
static uint32_t g_host_cpusubtype = 0;
static uint32_t g_is_64_bit_capable = 0;
static bool g_promoted_to_64 = false;
if (g_host_cputype == 0)
{
g_promoted_to_64 = false;
size_t len = sizeof(uint32_t);
if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0)
{
len = sizeof (uint32_t);
if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len, NULL, 0) == 0)
{
if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0))
{
g_promoted_to_64 = true;
g_host_cputype |= CPU_ARCH_ABI64;
}
}
}
len = sizeof(uint32_t);
if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) == 0)
{
if (g_promoted_to_64 &&
g_host_cputype == CPU_TYPE_X86_64 && g_host_cpusubtype == CPU_SUBTYPE_486)
g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL;
}
}
cputype = g_host_cputype;
cpusubtype = g_host_cpusubtype;
is_64_bit_capable = g_is_64_bit_capable;
promoted_to_64 = g_promoted_to_64;
return g_host_cputype != 0;
}
rnb_err_t
RNBRemote::HandlePacket_qHostInfo (const char *p)
{
std::ostringstream strm;
uint32_t cputype, is_64_bit_capable;
size_t len = sizeof(cputype);
uint32_t cputype = 0;
uint32_t cpusubtype = 0;
uint32_t is_64_bit_capable = 0;
bool promoted_to_64 = false;
if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
if (GetHostCPUType (cputype, cpusubtype, is_64_bit_capable, promoted_to_64))
{
len = sizeof (is_64_bit_capable);
if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
{
if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0))
{
promoted_to_64 = true;
cputype |= CPU_ARCH_ABI64;
}
}
strm << "cputype:" << std::dec << cputype << ';';
}
uint32_t cpusubtype;
len = sizeof(cpusubtype);
if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
{
if (promoted_to_64 &&
cputype == CPU_TYPE_X86_64 &&
cpusubtype == CPU_SUBTYPE_486)
cpusubtype = CPU_SUBTYPE_X86_64_ALL;
strm << "cpusubtype:" << std::dec << cpusubtype << ';';
}
@ -4054,6 +4111,340 @@ RNBRemote::HandlePacket_qHostInfo (const char *p)
return SendPacket (strm.str());
}
void
XMLElementStart (std::ostringstream &s, uint32_t indent, const char *name, bool has_attributes)
{
if (indent)
s << INDENT_WITH_SPACES(indent);
s << '<' << name;
if (!has_attributes)
s << '>' << std::endl;
}
void
XMLElementStartEndAttributes (std::ostringstream &s, bool empty)
{
if (empty)
s << '/';
s << '>' << std::endl;
}
void
XMLElementEnd (std::ostringstream &s, uint32_t indent, const char *name)
{
if (indent)
s << INDENT_WITH_SPACES(indent);
s << '<' << '/' << name << '>' << std::endl;
}
void
XMLElementWithStringValue (std::ostringstream &s, uint32_t indent, const char *name, const char *value, bool close = true)
{
if (value)
{
if (indent)
s << INDENT_WITH_SPACES(indent);
s << '<' << name << '>' << value;
if (close)
XMLElementEnd(s, 0, name);
}
}
void
XMLElementWithUnsignedValue (std::ostringstream &s, uint32_t indent, const char *name, uint64_t value, bool close = true)
{
if (indent)
s << INDENT_WITH_SPACES(indent);
s << '<' << name << '>' << DECIMAL << value;
if (close)
XMLElementEnd(s, 0, name);
}
void
XMLAttributeString (std::ostringstream &s, const char *name, const char *value, const char *default_value = NULL)
{
if (value)
{
if (default_value && strcmp(value, default_value) == 0)
return; // No need to emit the attribute because it matches the default value
s <<' ' << name << "=\"" << value << "\"";
}
}
void
XMLAttributeUnsignedDecimal (std::ostringstream &s, const char *name, uint64_t value)
{
s <<' ' << name << "=\"" << DECIMAL << value << "\"";
}
void
GenerateTargetXMLRegister (std::ostringstream &s,
const uint32_t reg_num,
nub_size_t num_reg_sets,
const DNBRegisterSetInfo *reg_set_info,
const register_map_entry_t &reg)
{
const char *default_lldb_encoding = "uint";
const char *lldb_encoding = default_lldb_encoding;
const char *gdb_group = "general";
const char *default_gdb_type = "int";
const char *gdb_type = default_gdb_type;
const char *default_lldb_format = "hex";
const char *lldb_format = default_lldb_format;
const char *lldb_set = NULL;
switch (reg.nub_info.type)
{
case Uint: lldb_encoding = "uint"; break;
case Sint: lldb_encoding = "sint"; break;
case IEEE754: lldb_encoding = "ieee754"; if (reg.nub_info.set > 0) gdb_group = "float"; break;
case Vector: lldb_encoding = "vector"; if (reg.nub_info.set > 0) gdb_group = "vector"; break;
}
switch (reg.nub_info.format)
{
case Binary: lldb_format = "binary"; break;
case Decimal: lldb_format = "decimal"; break;
case Hex: lldb_format = "hex"; break;
case Float: gdb_type = "float"; lldb_format = "float"; break;
case VectorOfSInt8: gdb_type = "float"; lldb_format = "vector-sint8"; break;
case VectorOfUInt8: gdb_type = "float"; lldb_format = "vector-uint8"; break;
case VectorOfSInt16: gdb_type = "float"; lldb_format = "vector-sint16"; break;
case VectorOfUInt16: gdb_type = "float"; lldb_format = "vector-uint16"; break;
case VectorOfSInt32: gdb_type = "float"; lldb_format = "vector-sint32"; break;
case VectorOfUInt32: gdb_type = "float"; lldb_format = "vector-uint32"; break;
case VectorOfFloat32: gdb_type = "float"; lldb_format = "vector-float32"; break;
case VectorOfUInt128: gdb_type = "float"; lldb_format = "vector-uint128"; break;
};
if (reg_set_info && reg.nub_info.set < num_reg_sets)
lldb_set = reg_set_info[reg.nub_info.set].name;
uint32_t indent = 2;
XMLElementStart(s, indent, "reg", true);
XMLAttributeString(s, "name", reg.nub_info.name);
XMLAttributeUnsignedDecimal(s, "regnum", reg_num);
XMLAttributeUnsignedDecimal(s, "offset", reg.offset);
XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8);
XMLAttributeString(s, "group", gdb_group);
XMLAttributeString(s, "type", gdb_type, default_gdb_type);
XMLAttributeString (s, "altname", reg.nub_info.alt);
XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding);
XMLAttributeString(s, "format", lldb_format, default_lldb_format);
XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set);
if (reg.nub_info.reg_gcc != INVALID_NUB_REGNUM)
XMLAttributeUnsignedDecimal(s, "gcc_regnum", reg.nub_info.reg_gcc);
if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM)
XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf);
const char *lldb_generic = NULL;
switch (reg.nub_info.reg_generic)
{
case GENERIC_REGNUM_FP: lldb_generic = "fp"; break;
case GENERIC_REGNUM_PC: lldb_generic = "pc"; break;
case GENERIC_REGNUM_SP: lldb_generic = "sp"; break;
case GENERIC_REGNUM_RA: lldb_generic = "ra"; break;
case GENERIC_REGNUM_FLAGS: lldb_generic = "flags"; break;
case GENERIC_REGNUM_ARG1: lldb_generic = "arg1"; break;
case GENERIC_REGNUM_ARG2: lldb_generic = "arg2"; break;
case GENERIC_REGNUM_ARG3: lldb_generic = "arg3"; break;
case GENERIC_REGNUM_ARG4: lldb_generic = "arg4"; break;
case GENERIC_REGNUM_ARG5: lldb_generic = "arg5"; break;
case GENERIC_REGNUM_ARG6: lldb_generic = "arg6"; break;
case GENERIC_REGNUM_ARG7: lldb_generic = "arg7"; break;
case GENERIC_REGNUM_ARG8: lldb_generic = "arg8"; break;
default: break;
}
XMLAttributeString(s, "generic", lldb_generic);
bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty();
if (!empty)
{
if (!reg.value_regnums.empty())
{
std::ostringstream regnums;
bool first = true;
regnums << DECIMAL;
for (auto regnum : reg.value_regnums)
{
if (!first)
regnums << ',';
regnums << regnum;
first = false;
}
XMLAttributeString(s, "value_regnums", regnums.str().c_str());
}
if (!reg.invalidate_regnums.empty())
{
std::ostringstream regnums;
bool first = true;
regnums << DECIMAL;
for (auto regnum : reg.invalidate_regnums)
{
if (!first)
regnums << ',';
regnums << regnum;
first = false;
}
XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str());
}
}
XMLElementStartEndAttributes(s, true);
}
void
GenerateTargetXMLRegisters (std::ostringstream &s)
{
nub_size_t num_reg_sets = 0;
const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets);
uint32_t cputype = DNBGetRegisterCPUType();
if (cputype)
{
XMLElementStart(s, 0, "feature", true);
std::ostringstream name_strm;
name_strm << "com.apple.debugserver." << GetArchName (cputype, 0);
XMLAttributeString(s, "name", name_strm.str().c_str());
XMLElementStartEndAttributes(s, false);
for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num)
// for (const auto &reg: g_dynamic_register_map)
{
GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets, g_reg_entries[reg_num]);
}
XMLElementEnd(s, 0, "feature");
if (num_reg_sets > 0)
{
XMLElementStart(s, 0, "groups", false);
for (uint32_t set=1; set<num_reg_sets; ++set)
{
XMLElementStart(s, 2, "group", true);
XMLAttributeUnsignedDecimal(s, "id", set);
XMLAttributeString(s, "name", reg_sets[set].name);
XMLElementStartEndAttributes(s, true);
}
XMLElementEnd(s, 0, "groups");
}
}
}
static const char *g_target_xml_header = R"(<?xml version="1.0"?>
<target version="1.0">)";
static const char *g_target_xml_footer = "</target>";
static std::string g_target_xml;
void
UpdateTargetXML ()
{
std::ostringstream s;
s << g_target_xml_header << std::endl;
// Set the architecture
//s << "<architecture>" << arch "</architecture>" << std::endl;
// Set the OSABI
//s << "<osabi>abi-name</osabi>"
GenerateTargetXMLRegisters(s);
s << g_target_xml_footer << std::endl;
// Save the XML output in case it gets retrieved in chunks
g_target_xml = s.str();
}
rnb_err_t
RNBRemote::HandlePacket_qXfer (const char *command)
{
const char *p = command;
p += strlen ("qXfer:");
const char *sep = strchr(p, ':');
if (sep)
{
std::string object(p, sep - p); // "auxv", "backtrace", "features", etc
p = sep + 1;
sep = strchr(p, ':');
if (sep)
{
std::string rw(p, sep - p); // "read" or "write"
p = sep + 1;
sep = strchr(p, ':');
if (sep)
{
std::string annex(p, sep - p); // "read" or "write"
p = sep + 1;
sep = strchr(p, ',');
if (sep)
{
std::string offset_str(p, sep - p); // read the length as a string
p = sep + 1;
std::string length_str(p); // read the offset as a string
char *end = nullptr;
const uint64_t offset = strtoul(offset_str.c_str(), &end, 16); // convert offset_str to a offset
if (*end == '\0')
{
const uint64_t length = strtoul(length_str.c_str(), &end, 16); // convert length_str to a length
if (*end == '\0')
{
if (object == "features" &&
rw == "read" &&
annex == "target.xml")
{
std::ostringstream xml_out;
if (offset == 0)
{
InitializeRegisters (true);
UpdateTargetXML();
if (g_target_xml.empty())
return SendPacket("E83");
if (length > g_target_xml.size())
{
xml_out << 'l'; // No more data
xml_out << binary_encode_string(g_target_xml);
}
else
{
xml_out << 'm'; // More data needs to be read with a subsequent call
xml_out << binary_encode_string(std::string(g_target_xml, offset, length));
}
}
else
{
// Retrieving target XML in chunks
if (offset < g_target_xml.size())
{
std::string chunk(g_target_xml, offset, length);
if (chunk.size() < length)
xml_out << 'l'; // No more data
else
xml_out << 'm'; // More data needs to be read with a subsequent call
xml_out << binary_encode_string(chunk.data());
}
}
return SendPacket(xml_out.str());
}
// Well formed, put not supported
return HandlePacket_UNIMPLEMENTED (command);
}
}
}
}
}
}
return SendPacket ("E82");
}
rnb_err_t
RNBRemote::HandlePacket_qGDBServerVersion (const char *p)
{

View File

@ -127,6 +127,7 @@ public:
restore_register_state, // '_G'
speed_test, // 'qSpeedTest:'
set_detach_on_error, // 'QSetDetachOnError:'
query_transfer, // 'qXfer:'
unknown_type
} PacketEnum;
@ -234,6 +235,7 @@ public:
rnb_err_t HandlePacket_SetEnableAsyncProfiling(const char *p);
rnb_err_t HandlePacket_WatchpointSupportInfo (const char *p);
rnb_err_t HandlePacket_qSpeedTest (const char *p);
rnb_err_t HandlePacket_qXfer (const char *p);
rnb_err_t HandlePacket_stop_process (const char *p);
rnb_err_t HandlePacket_QSetDetachOnError (const char *p);