summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Host/XML.h216
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj54
-rw-r--r--lldb/source/Host/CMakeLists.txt1
-rw-r--r--lldb/source/Host/common/XML.cpp548
-rw-r--r--lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp2
-rw-r--r--lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp121
-rw-r--r--lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h8
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp9
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp895
-rw-r--r--lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp119
-rw-r--r--lldb/tools/debugserver/source/DNB.cpp6
-rw-r--r--lldb/tools/debugserver/source/DNB.h1
-rw-r--r--lldb/tools/debugserver/source/DNBArch.cpp9
-rw-r--r--lldb/tools/debugserver/source/DNBArch.h3
-rw-r--r--lldb/tools/debugserver/source/RNBRemote.cpp435
-rw-r--r--lldb/tools/debugserver/source/RNBRemote.h2
17 files changed, 1713 insertions, 718 deletions
diff --git a/lldb/include/lldb/Host/XML.h b/lldb/include/lldb/Host/XML.h
new file mode 100644
index 00000000000..d0e2ea3c84c
--- /dev/null
+++ b/lldb/include/lldb/Host/XML.h
@@ -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_
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index 9c37e1798e6..8f13355fd06 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -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 */,
diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt
index a13defa46c5..0a005af18d7 100644
--- a/lldb/source/Host/CMakeLists.txt
+++ b/lldb/source/Host/CMakeLists.txt
@@ -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)
diff --git a/lldb/source/Host/common/XML.cpp b/lldb/source/Host/common/XML.cpp
new file mode 100644
index 00000000000..6e84428fc6b
--- /dev/null
+++ b/lldb/source/Host/common/XML.cpp
@@ -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;
+}
+
diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index df847dbb9ce..95bd8402446 100644
--- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -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);
}
diff --git a/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp b/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
index 3dce3e2ba4a..dce88bc62db 100644
--- a/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
+++ b/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
@@ -742,4 +742,4 @@ PlatformWindows::GetEnvironment(StringList &env)
}
return Host::GetEnvironment(env);
-} \ No newline at end of file
+}
diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 0e9b540b7cf..f91cd19b7f2 100644
--- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -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
diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
index 128d8987397..1b99e2f1e70 100644
--- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -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;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 7f194cdd55b..a452ae95b07 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -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 ) {
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)
{
diff --git a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
index 1e99dcf4599..15e31c1774e 100644
--- a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -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,111 +173,46 @@ 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)
+ std::string DBGBuildSourcePath;
+ std::string DBGSourcePath;
+
+ plist.GetValueAsString("DBGBuildSourcePath", DBGBuildSourcePath);
+ plist.GetValueAsString("DBGSourcePath", DBGSourcePath);
+ if (DBGBuildSourcePath[0] && DBGSourcePath[0])
{
- 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);
- }
- }
- }
- }
- }
+ module_sp->GetSourceMappingList().Append (ConstString(DBGBuildSourcePath), ConstString(DBGSourcePath), true);
}
}
- ::xmlFreeDoc (doc);
-
- if (DBGBuildSourcePath[0] && DBGSourcePath[0])
- {
- module_sp->GetSourceMappingList().Append (ConstString(DBGBuildSourcePath), ConstString(DBGSourcePath), true);
- }
}
}
}
}
}
}
-#endif // #if defined( LIBXML2_DEFINED )
symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp);
return symbol_vendor;
diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp
index 875193440b2..4d773221a45 100644
--- a/lldb/tools/debugserver/source/DNB.cpp
+++ b/lldb/tools/debugserver/source/DNB.cpp
@@ -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.
//----------------------------------------------------------------------
diff --git a/lldb/tools/debugserver/source/DNB.h b/lldb/tools/debugserver/source/DNB.h
index 363ca042e83..e57bb08b678 100644
--- a/lldb/tools/debugserver/source/DNB.h
+++ b/lldb/tools/debugserver/source/DNB.h
@@ -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);
diff --git a/lldb/tools/debugserver/source/DNBArch.cpp b/lldb/tools/debugserver/source/DNBArch.cpp
index c3f1fdf2682..4b56cae18e1 100644
--- a/lldb/tools/debugserver/source/DNBArch.cpp
+++ b/lldb/tools/debugserver/source/DNBArch.cpp
@@ -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)
{
diff --git a/lldb/tools/debugserver/source/DNBArch.h b/lldb/tools/debugserver/source/DNBArch.h
index b3cb070e55c..998ca4df55b 100644
--- a/lldb/tools/debugserver/source/DNBArch.h
+++ b/lldb/tools/debugserver/source/DNBArch.h
@@ -43,6 +43,9 @@ public:
static DNBArchProtocol *
Create (MachThread *thread);
+ static uint32_t
+ GetRegisterCPUType ();
+
static const DNBRegisterSetInfo *
GetRegisterSetInfo (nub_size_t *num_reg_sets);
diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp
index 88ff9242fdb..25988b9294b 100644
--- a/lldb/tools/debugserver/source/RNBRemote.cpp
+++ b/lldb/tools/debugserver/source/RNBRemote.cpp
@@ -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;
}
-rnb_err_t
-RNBRemote::HandlePacket_qHostInfo (const char *p)
+static const char *
+GetArchName (const uint32_t cputype, const uint32_t cpusubtype)
{
- std::ostringstream strm;
+ 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;
+}
- uint32_t cputype, is_64_bit_capable;
- size_t len = sizeof(cputype);
- bool promoted_to_64 = false;
- if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
+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)
{
- len = sizeof (is_64_bit_capable);
- if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
+ g_promoted_to_64 = false;
+ size_t len = sizeof(uint32_t);
+ if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0)
{
- if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0))
+ len = sizeof (uint32_t);
+ if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len, NULL, 0) == 0)
{
- promoted_to_64 = true;
- cputype |= CPU_ARCH_ABI64;
+ if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0))
+ {
+ g_promoted_to_64 = true;
+ g_host_cputype |= CPU_ARCH_ABI64;
+ }
}
}
- strm << "cputype:" << std::dec << cputype << ';';
+ 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;
+}
- 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;
+rnb_err_t
+RNBRemote::HandlePacket_qHostInfo (const char *p)
+{
+ std::ostringstream strm;
+ uint32_t cputype = 0;
+ uint32_t cpusubtype = 0;
+ uint32_t is_64_bit_capable = 0;
+ bool promoted_to_64 = false;
+ if (GetHostCPUType (cputype, cpusubtype, is_64_bit_capable, promoted_to_64))
+ {
+ strm << "cputype:" << std::dec << cputype << ';';
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)
{
diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h
index 0d99465f507..c58c32b1b02 100644
--- a/lldb/tools/debugserver/source/RNBRemote.h
+++ b/lldb/tools/debugserver/source/RNBRemote.h
@@ -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);
OpenPOWER on IntegriCloud