Added XML to the host layer.
We know have on API we should use for all XML within LLDB in XML.h. This API will be easy back the XML parsing by different libraries in case libxml2 doesn't work on all platforms. It also allows the only place for #ifdef ...XML... to be in XML.h and XML.cpp. The API is designed so it will still compile with or without XML support and there is a static function "bool XMLDocument::XMLEnabled()" that can be called to see if XML is currently supported. All APIs will return errors, false, or nothing when XML isn't enabled. Converted all locations that used XML over to using the host XML implementation. Added target.xml support to debugserver. Extended the XML register format to work for LLDB by including extra attributes and elements where needed. This allows the target.xml to replace the qRegisterInfo packets and allows us to fetch all register info in a single packet. <rdar://problem/21090173> llvm-svn: 238224
This commit is contained in:
parent
bfecc06656
commit
d04f0edad9
|
@ -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_
|
|
@ -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 */,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -742,4 +742,4 @@ PlatformWindows::GetEnvironment(StringList &env)
|
|||
}
|
||||
|
||||
return Host::GetEnvironment(env);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ®_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 ®: 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 ®: 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 ®: 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 ®: 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 ®: 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
|
||||
|
|
|
@ -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 ®_info,
|
||||
|
@ -40,7 +42,7 @@ public:
|
|||
lldb_private::ConstString &set_name);
|
||||
|
||||
void
|
||||
Finalize ();
|
||||
Finalize (const lldb_private::ArchSpec &arch);
|
||||
|
||||
size_t
|
||||
GetNumRegisters() const;
|
||||
|
|
|
@ -3929,9 +3929,12 @@ GDBRemoteCommunicationClient::ReadExtFeature (const lldb_private::ConstString ob
|
|||
std::stringstream output;
|
||||
StringExtractorGDBRemote chunk;
|
||||
|
||||
const int size = 0xfff;
|
||||
int offset = 0;
|
||||
bool active = true;
|
||||
uint64_t size = GetRemoteMaxPacketSize();
|
||||
if (size == 0)
|
||||
size = 0x1000;
|
||||
size = size - 1; // Leave space for the 'm' or 'l' character in the response
|
||||
int offset = 0;
|
||||
bool active = true;
|
||||
|
||||
// loop until all data has been read
|
||||
while ( active ) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,11 +9,6 @@
|
|||
|
||||
#include "SymbolVendorMacOSX.h"
|
||||
|
||||
#if defined( LIBXML2_DEFINED )
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
#endif // #if defined( LIBXML2_DEFINED )
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lldb/Core/Module.h"
|
||||
|
@ -24,6 +19,7 @@
|
|||
#include "lldb/Core/Timer.h"
|
||||
#include "lldb/Host/Host.h"
|
||||
#include "lldb/Host/Symbols.h"
|
||||
#include "lldb/Host/XML.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
|
||||
using namespace lldb;
|
||||
|
@ -177,103 +173,39 @@ SymbolVendorMacOSX::CreateInstance (const lldb::ModuleSP &module_sp, lldb_privat
|
|||
dsym_objfile_sp = ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(), dsym_file_data_sp, dsym_file_data_offset);
|
||||
if (UUIDsMatch(module_sp.get(), dsym_objfile_sp.get(), feedback_strm))
|
||||
{
|
||||
#if defined( LIBXML2_DEFINED )
|
||||
char dsym_path[PATH_MAX];
|
||||
if (module_sp->GetSourceMappingList().IsEmpty() && dsym_fspec.GetPath(dsym_path, sizeof(dsym_path)))
|
||||
// We need a XML parser if we hope to parse a plist...
|
||||
if (XMLDocument::XMLEnabled())
|
||||
{
|
||||
lldb_private::UUID dsym_uuid;
|
||||
if (dsym_objfile_sp->GetUUID(&dsym_uuid))
|
||||
char dsym_path[PATH_MAX];
|
||||
if (module_sp->GetSourceMappingList().IsEmpty() && dsym_fspec.GetPath(dsym_path, sizeof(dsym_path)))
|
||||
{
|
||||
std::string uuid_str = dsym_uuid.GetAsString ();
|
||||
if (!uuid_str.empty())
|
||||
lldb_private::UUID dsym_uuid;
|
||||
if (dsym_objfile_sp->GetUUID(&dsym_uuid))
|
||||
{
|
||||
char *resources = strstr (dsym_path, "/Contents/Resources/");
|
||||
if (resources)
|
||||
std::string uuid_str = dsym_uuid.GetAsString ();
|
||||
if (!uuid_str.empty())
|
||||
{
|
||||
char dsym_uuid_plist_path[PATH_MAX];
|
||||
resources[strlen("/Contents/Resources/")] = '\0';
|
||||
snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path), "%s%s.plist", dsym_path, uuid_str.c_str());
|
||||
FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path, false);
|
||||
if (dsym_uuid_plist_spec.Exists())
|
||||
char *resources = strstr (dsym_path, "/Contents/Resources/");
|
||||
if (resources)
|
||||
{
|
||||
xmlDoc *doc = ::xmlReadFile (dsym_uuid_plist_path, NULL, 0);
|
||||
if (doc)
|
||||
char dsym_uuid_plist_path[PATH_MAX];
|
||||
resources[strlen("/Contents/Resources/")] = '\0';
|
||||
snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path), "%s%s.plist", dsym_path, uuid_str.c_str());
|
||||
FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path, false);
|
||||
if (dsym_uuid_plist_spec.Exists())
|
||||
{
|
||||
char DBGBuildSourcePath[PATH_MAX];
|
||||
char DBGSourcePath[PATH_MAX];
|
||||
DBGBuildSourcePath[0] = '\0';
|
||||
DBGSourcePath[0] = '\0';
|
||||
for (xmlNode *node = doc->children; node; node = node ? node->next : NULL)
|
||||
ApplePropertyList plist(dsym_uuid_plist_path);
|
||||
if (plist)
|
||||
{
|
||||
if (node->type == XML_ELEMENT_NODE)
|
||||
{
|
||||
if (node->name && strcmp((const char*)node->name, "plist") == 0)
|
||||
{
|
||||
xmlNode *dict_node = node->children;
|
||||
while (dict_node && dict_node->type != XML_ELEMENT_NODE)
|
||||
dict_node = dict_node->next;
|
||||
if (dict_node && dict_node->name && strcmp((const char *)dict_node->name, "dict") == 0)
|
||||
{
|
||||
for (xmlNode *key_node = dict_node->children; key_node; key_node = key_node->next)
|
||||
{
|
||||
if (key_node && key_node->type == XML_ELEMENT_NODE && key_node->name)
|
||||
{
|
||||
if (strcmp((const char *)key_node->name, "key") == 0)
|
||||
{
|
||||
const char *key_name = (const char *)::xmlNodeGetContent(key_node);
|
||||
if (strcmp(key_name, "DBGBuildSourcePath") == 0)
|
||||
{
|
||||
xmlNode *value_node = key_node->next;
|
||||
while (value_node && value_node->type != XML_ELEMENT_NODE)
|
||||
value_node = value_node->next;
|
||||
if (value_node && value_node->name)
|
||||
{
|
||||
if (strcmp((const char *)value_node->name, "string") == 0)
|
||||
{
|
||||
const char *node_content = (const char *)::xmlNodeGetContent(value_node);
|
||||
if (node_content)
|
||||
{
|
||||
::snprintf(DBGBuildSourcePath, sizeof(DBGBuildSourcePath), "%s", node_content);
|
||||
xmlFree((void *) node_content);
|
||||
}
|
||||
}
|
||||
key_node = value_node;
|
||||
}
|
||||
}
|
||||
else if (strcmp(key_name, "DBGSourcePath") == 0)
|
||||
{
|
||||
xmlNode *value_node = key_node->next;
|
||||
while (value_node && value_node->type != XML_ELEMENT_NODE)
|
||||
value_node = value_node->next;
|
||||
if (value_node && value_node->name)
|
||||
{
|
||||
if (strcmp((const char *)value_node->name, "string") == 0)
|
||||
{
|
||||
const char *node_content = (const char *)::xmlNodeGetContent(value_node);
|
||||
if (node_content)
|
||||
{
|
||||
FileSpec resolved_source_path(node_content, true);
|
||||
resolved_source_path.GetPath(DBGSourcePath, sizeof(DBGSourcePath));
|
||||
xmlFree ((void *) node_content);
|
||||
}
|
||||
}
|
||||
key_node = value_node;
|
||||
}
|
||||
}
|
||||
if (key_name != NULL)
|
||||
xmlFree((void *) key_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
::xmlFreeDoc (doc);
|
||||
std::string DBGBuildSourcePath;
|
||||
std::string DBGSourcePath;
|
||||
|
||||
if (DBGBuildSourcePath[0] && DBGSourcePath[0])
|
||||
{
|
||||
module_sp->GetSourceMappingList().Append (ConstString(DBGBuildSourcePath), ConstString(DBGSourcePath), true);
|
||||
plist.GetValueAsString("DBGBuildSourcePath", DBGBuildSourcePath);
|
||||
plist.GetValueAsString("DBGSourcePath", DBGSourcePath);
|
||||
if (DBGBuildSourcePath[0] && DBGSourcePath[0])
|
||||
{
|
||||
module_sp->GetSourceMappingList().Append (ConstString(DBGBuildSourcePath), ConstString(DBGSourcePath), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -281,7 +213,6 @@ SymbolVendorMacOSX::CreateInstance (const lldb::ModuleSP &module_sp, lldb_privat
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif // #if defined( LIBXML2_DEFINED )
|
||||
|
||||
symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp);
|
||||
return symbol_vendor;
|
||||
|
|
|
@ -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.
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -43,6 +43,9 @@ public:
|
|||
static DNBArchProtocol *
|
||||
Create (MachThread *thread);
|
||||
|
||||
static uint32_t
|
||||
GetRegisterCPUType ();
|
||||
|
||||
static const DNBRegisterSetInfo *
|
||||
GetRegisterSetInfo (nub_size_t *num_reg_sets);
|
||||
|
||||
|
|
|
@ -210,6 +210,7 @@ RNBRemote::CreatePacketTable ()
|
|||
t.push_back (Packet (set_process_event, &RNBRemote::HandlePacket_QSetProcessEvent, NULL, "QSetProcessEvent:", "Set a process event, to be passed to the process, can be set before the process is started, or after."));
|
||||
t.push_back (Packet (set_detach_on_error, &RNBRemote::HandlePacket_QSetDetachOnError, NULL, "QSetDetachOnError:", "Set whether debugserver will detach (1) or kill (0) from the process it is controlling if it loses connection to lldb."));
|
||||
t.push_back (Packet (speed_test, &RNBRemote::HandlePacket_qSpeedTest, NULL, "qSpeedTest:", "Test the maximum speed at which packet can be sent/received."));
|
||||
t.push_back (Packet (query_transfer, &RNBRemote::HandlePacket_qXfer, NULL, "qXfer:", "Support the qXfer packet."));
|
||||
}
|
||||
|
||||
|
||||
|
@ -3085,7 +3086,7 @@ RNBRemote::HandlePacket_qSupported (const char *p)
|
|||
{
|
||||
uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet size--debugger can always use less
|
||||
char buf[64];
|
||||
snprintf (buf, sizeof(buf), "PacketSize=%x", max_packet_size);
|
||||
snprintf (buf, sizeof(buf), "qXfer:features:read+;PacketSize=%x", max_packet_size);
|
||||
return SendPacket (buf);
|
||||
}
|
||||
|
||||
|
@ -3979,38 +3980,94 @@ RNBRemote::HandlePacket_S (const char *p)
|
|||
return rnb_success;
|
||||
}
|
||||
|
||||
static const char *
|
||||
GetArchName (const uint32_t cputype, const uint32_t cpusubtype)
|
||||
{
|
||||
switch (cputype)
|
||||
{
|
||||
case CPU_TYPE_ARM:
|
||||
switch (cpusubtype)
|
||||
{
|
||||
case 5: return "armv4";
|
||||
case 6: return "armv6";
|
||||
case 7: return "armv5t";
|
||||
case 8: return "xscale";
|
||||
case 9: return "armv7";
|
||||
case 10: return "armv7f";
|
||||
case 11: return "armv7s";
|
||||
case 12: return "armv7k";
|
||||
case 14: return "armv6m";
|
||||
case 15: return "armv7m";
|
||||
case 16: return "armv7em";
|
||||
default: return "arm";
|
||||
}
|
||||
break;
|
||||
case CPU_TYPE_ARM64: return "arm64";
|
||||
case CPU_TYPE_I386: return "i386";
|
||||
case CPU_TYPE_X86_64:
|
||||
switch (cpusubtype)
|
||||
{
|
||||
default: return "x86_64";
|
||||
case 8: return "x86_64h";
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetHostCPUType (uint32_t &cputype, uint32_t &cpusubtype, uint32_t &is_64_bit_capable, bool &promoted_to_64)
|
||||
{
|
||||
static uint32_t g_host_cputype = 0;
|
||||
static uint32_t g_host_cpusubtype = 0;
|
||||
static uint32_t g_is_64_bit_capable = 0;
|
||||
static bool g_promoted_to_64 = false;
|
||||
|
||||
if (g_host_cputype == 0)
|
||||
{
|
||||
g_promoted_to_64 = false;
|
||||
size_t len = sizeof(uint32_t);
|
||||
if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0)
|
||||
{
|
||||
len = sizeof (uint32_t);
|
||||
if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len, NULL, 0) == 0)
|
||||
{
|
||||
if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0))
|
||||
{
|
||||
g_promoted_to_64 = true;
|
||||
g_host_cputype |= CPU_ARCH_ABI64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len = sizeof(uint32_t);
|
||||
if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) == 0)
|
||||
{
|
||||
if (g_promoted_to_64 &&
|
||||
g_host_cputype == CPU_TYPE_X86_64 && g_host_cpusubtype == CPU_SUBTYPE_486)
|
||||
g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
cputype = g_host_cputype;
|
||||
cpusubtype = g_host_cpusubtype;
|
||||
is_64_bit_capable = g_is_64_bit_capable;
|
||||
promoted_to_64 = g_promoted_to_64;
|
||||
return g_host_cputype != 0;
|
||||
}
|
||||
|
||||
rnb_err_t
|
||||
RNBRemote::HandlePacket_qHostInfo (const char *p)
|
||||
{
|
||||
std::ostringstream strm;
|
||||
|
||||
uint32_t cputype, is_64_bit_capable;
|
||||
size_t len = sizeof(cputype);
|
||||
uint32_t cputype = 0;
|
||||
uint32_t cpusubtype = 0;
|
||||
uint32_t is_64_bit_capable = 0;
|
||||
bool promoted_to_64 = false;
|
||||
if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
|
||||
if (GetHostCPUType (cputype, cpusubtype, is_64_bit_capable, promoted_to_64))
|
||||
{
|
||||
len = sizeof (is_64_bit_capable);
|
||||
if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
|
||||
{
|
||||
if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0))
|
||||
{
|
||||
promoted_to_64 = true;
|
||||
cputype |= CPU_ARCH_ABI64;
|
||||
}
|
||||
}
|
||||
|
||||
strm << "cputype:" << std::dec << cputype << ';';
|
||||
}
|
||||
|
||||
uint32_t cpusubtype;
|
||||
len = sizeof(cpusubtype);
|
||||
if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
|
||||
{
|
||||
if (promoted_to_64 &&
|
||||
cputype == CPU_TYPE_X86_64 &&
|
||||
cpusubtype == CPU_SUBTYPE_486)
|
||||
cpusubtype = CPU_SUBTYPE_X86_64_ALL;
|
||||
|
||||
strm << "cpusubtype:" << std::dec << cpusubtype << ';';
|
||||
}
|
||||
|
||||
|
@ -4054,6 +4111,340 @@ RNBRemote::HandlePacket_qHostInfo (const char *p)
|
|||
return SendPacket (strm.str());
|
||||
}
|
||||
|
||||
void
|
||||
XMLElementStart (std::ostringstream &s, uint32_t indent, const char *name, bool has_attributes)
|
||||
{
|
||||
if (indent)
|
||||
s << INDENT_WITH_SPACES(indent);
|
||||
s << '<' << name;
|
||||
if (!has_attributes)
|
||||
s << '>' << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
XMLElementStartEndAttributes (std::ostringstream &s, bool empty)
|
||||
{
|
||||
if (empty)
|
||||
s << '/';
|
||||
s << '>' << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
XMLElementEnd (std::ostringstream &s, uint32_t indent, const char *name)
|
||||
{
|
||||
if (indent)
|
||||
s << INDENT_WITH_SPACES(indent);
|
||||
s << '<' << '/' << name << '>' << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
XMLElementWithStringValue (std::ostringstream &s, uint32_t indent, const char *name, const char *value, bool close = true)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
if (indent)
|
||||
s << INDENT_WITH_SPACES(indent);
|
||||
s << '<' << name << '>' << value;
|
||||
if (close)
|
||||
XMLElementEnd(s, 0, name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
XMLElementWithUnsignedValue (std::ostringstream &s, uint32_t indent, const char *name, uint64_t value, bool close = true)
|
||||
{
|
||||
if (indent)
|
||||
s << INDENT_WITH_SPACES(indent);
|
||||
|
||||
s << '<' << name << '>' << DECIMAL << value;
|
||||
if (close)
|
||||
XMLElementEnd(s, 0, name);
|
||||
}
|
||||
|
||||
void
|
||||
XMLAttributeString (std::ostringstream &s, const char *name, const char *value, const char *default_value = NULL)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
if (default_value && strcmp(value, default_value) == 0)
|
||||
return; // No need to emit the attribute because it matches the default value
|
||||
s <<' ' << name << "=\"" << value << "\"";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
XMLAttributeUnsignedDecimal (std::ostringstream &s, const char *name, uint64_t value)
|
||||
{
|
||||
s <<' ' << name << "=\"" << DECIMAL << value << "\"";
|
||||
}
|
||||
|
||||
void
|
||||
GenerateTargetXMLRegister (std::ostringstream &s,
|
||||
const uint32_t reg_num,
|
||||
nub_size_t num_reg_sets,
|
||||
const DNBRegisterSetInfo *reg_set_info,
|
||||
const register_map_entry_t ®)
|
||||
{
|
||||
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 ®: 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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue