[Lldb-commits] [lldb] r235109 - Adds lldb support for querying the register mapping from gdbserver remote targets using qXfer:features:read packet. Only enabled if libxml2 enabled in build.
Chuck Ries
Chuck.Ries at microsoft.com
Thu Apr 16 14:35:03 PDT 2015
After this change I am seeing the cmake build broken on mac os.
FAILED: /usr/bin/c++ -DGTEST_HAS_RTTI=0 -DHAVE_ROUND -DLIBXML2_DEFINED -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -fPIC -fvisibility-inlines-hidden -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wcovered-switch-default -std=c++11 -fcolor-diagnostics -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-deprecated-register -fno-exceptions -fno-rtti -fPIC -fPIC -g -Itools/lldb/source/Plugins/Process/gdb-remote -I/Users/chuckr/llama/llvm/tools/lldb/source/Plugins/Process/gdb-remote -I/Users/chuckr/llama/llvm/tools/lldb/include -Itools/lldb/include -Iinclude -I/Users/chuckr/llama/llvm/include -I/System/Library/Frameworks/Python.framework/Headers -I/Users/chuckr/llama/llvm/tools/lldb/../clang/include -Itools/lldb/../clang/include -I/Users/chuckr/llama/llvm/tools/lldb/source/. -fno-exceptions -fno-rtti -MMD -MT tools/lldb/source/Plugins/Process/gdb-remote/CMakeFiles/lldbPluginProcessGDBRemote.dir/ProcessGDBRemote.cpp.o -MF tools/lldb/source/Plugins/Process/gdb-remote/CMakeFiles/lldbPluginProcessGDBRemote.dir/ProcessGDBRemote.cpp.o.d -o tools/lldb/source/Plugins/Process/gdb-remote/CMakeFiles/lldbPluginProcessGDBRemote.dir/ProcessGDBRemote.cpp.o -c /Users/chuckr/llama/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
/Users/chuckr/llama/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp:31:10: fatal error: 'libxml/xmlreader.h' file not found
#include <libxml/xmlreader.h>
^
1 error generated.
-----Original Message-----
From: lldb-commits-bounces at cs.uiuc.edu [mailto:lldb-commits-bounces at cs.uiuc.edu] On Behalf Of Colin Riley
Sent: Thursday, April 16, 2015 8:52 AM
To: lldb-commits at cs.uiuc.edu
Subject: [Lldb-commits] [lldb] r235109 - Adds lldb support for querying the register mapping from gdbserver remote targets using qXfer:features:read packet. Only enabled if libxml2 enabled in build.
Author: domipheus
Date: Thu Apr 16 10:51:33 2015
New Revision: 235109
URL: http://llvm.org/viewvc/llvm-project?rev=235109&view=rev
Log:
Adds lldb support for querying the register mapping from gdbserver remote targets using qXfer:features:read packet. Only enabled if libxml2 enabled in build.
Differential Revision: http://reviews.llvm.org/D8999
Modified:
lldb/trunk/cmake/modules/LLDBConfig.cmake
lldb/trunk/source/Commands/CommandObjectRegister.cpp
lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
Modified: lldb/trunk/cmake/modules/LLDBConfig.cmake
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/cmake/modules/LLDBConfig.cmake?rev=235109&r1=235108&r2=235109&view=diff
==============================================================================
--- lldb/trunk/cmake/modules/LLDBConfig.cmake (original)
+++ lldb/trunk/cmake/modules/LLDBConfig.cmake Thu Apr 16 10:51:33 2015
@@ -187,29 +187,39 @@ install(DIRECTORY include/
DESTINATION include
FILES_MATCHING
PATTERN "*.h"
- PATTERN ".svn" EXCLUDE
- )
-
-
-# Find libraries or frameworks that may be needed -if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+ PATTERN ".svn" EXCLUDE
+ )
+
+if (NOT LIBXML2_FOUND)
+ find_package(LibXml2)
+endif()
+
+# Find libraries or frameworks that may be needed if (CMAKE_SYSTEM_NAME
+MATCHES "Darwin")
find_library(CARBON_LIBRARY Carbon)
find_library(FOUNDATION_LIBRARY Foundation)
find_library(CORE_FOUNDATION_LIBRARY CoreFoundation)
find_library(CORE_SERVICES_LIBRARY CoreServices)
- find_library(SECURITY_LIBRARY Security)
- find_library(DEBUG_SYMBOLS_LIBRARY DebugSymbols PATHS "/System/Library/PrivateFrameworks")
-
- if (NOT LIBXML2_FOUND)
- find_package(LibXml2)
- endif ()
- list(APPEND system_libs xml2 ncurses panel)
- list(APPEND system_libs ${CARBON_LIBRARY} ${FOUNDATION_LIBRARY}
- ${CORE_FOUNDATION_LIBRARY} ${CORE_SERVICES_LIBRARY} ${SECURITY_LIBRARY}
- ${DEBUG_SYMBOLS_LIBRARY})
-endif()
-
-if(LLDB_REQUIRES_EH)
+ find_library(SECURITY_LIBRARY Security)
+ find_library(DEBUG_SYMBOLS_LIBRARY DebugSymbols PATHS
+ "/System/Library/PrivateFrameworks")
+
+ add_definitions( -DLIBXML2_DEFINED )
+ list(APPEND system_libs xml2 ncurses panel) list(APPEND system_libs
+ ${CARBON_LIBRARY} ${FOUNDATION_LIBRARY} ${CORE_FOUNDATION_LIBRARY}
+ ${CORE_SERVICES_LIBRARY} ${SECURITY_LIBRARY}
+ ${DEBUG_SYMBOLS_LIBRARY})
+
+else()
+
+ if (LIBXML2_FOUND)
+ add_definitions( -DLIBXML2_DEFINED )
+ list(APPEND system_libs ${LIBXML2_LIBRARIES})
+ include_directories(${LIBXML2_INCLUDE_DIR})
+ endif()
+
+endif()
+
+if(LLDB_REQUIRES_EH)
set(LLDB_REQUIRES_RTTI ON)
else()
if(LLVM_COMPILER_IS_GCC_COMPATIBLE)
Modified: lldb/trunk/source/Commands/CommandObjectRegister.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectRegister.cpp?rev=235109&r1=235108&r2=235109&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectRegister.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectRegister.cpp Thu Apr 16
+++ 10:51:33 2015
@@ -144,7 +144,7 @@ public:
const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx);
if (reg_set)
{
- strm.Printf ("%s:\n", reg_set->name);
+ strm.Printf ("%s:\n", (reg_set->name ? reg_set->name :
+ "unknown") );
strm.IndentMore ();
const size_t num_registers = reg_set->num_registers;
for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=235109&r1=235108&r2=235109&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationC
+++ lient.cpp Thu Apr 16 10:51:33 2015
@@ -79,6 +79,7 @@ GDBRemoteCommunicationClient::GDBRemoteC
m_supports_QSaveRegisterState (eLazyBoolCalculate),
m_supports_qXfer_auxv_read (eLazyBoolCalculate),
m_supports_qXfer_libraries_read (eLazyBoolCalculate),
+ m_supports_qXfer_features_read (eLazyBoolCalculate),
m_supports_qXfer_libraries_svr4_read (eLazyBoolCalculate),
m_supports_augmented_libraries_svr4_read (eLazyBoolCalculate),
m_supports_jThreadExtendedInfo (eLazyBoolCalculate), @@ -214,6 +215,16 @@ GDBRemoteCommunicationClient::GetQXferAu
return (m_supports_qXfer_auxv_read == eLazyBoolYes); }
+bool
+GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported () {
+ if (m_supports_qXfer_features_read == eLazyBoolCalculate)
+ {
+ GetRemoteQSupported();
+ }
+ return (m_supports_qXfer_features_read == eLazyBoolYes); }
+
uint64_t
GDBRemoteCommunicationClient::GetRemoteMaxPacketSize()
{
@@ -335,6 +346,7 @@ GDBRemoteCommunicationClient::ResetDisco
m_supports_qXfer_auxv_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
+ m_supports_qXfer_features_read = eLazyBoolCalculate;
m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
m_supports_qProcessInfoPID = true;
@@ -373,10 +385,21 @@ GDBRemoteCommunicationClient::GetRemoteQ
m_supports_qXfer_libraries_read = eLazyBoolNo;
m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
+ m_supports_qXfer_features_read = eLazyBoolNo;
m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if not, we assume no limit
+ // build the qSupported packet
+ std::vector<std::string> features = {"xmlRegisters=i386,arm,mips"};
+ StreamString packet;
+ packet.PutCString( "qSupported" );
+ for ( uint32_t i = 0; i < features.size( ); ++i )
+ {
+ packet.PutCString( i==0 ? ":" : ";");
+ packet.PutCString( features[i].c_str( ) );
+ }
+
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qSupported",
+ if (SendPacketAndWaitForResponse(packet.GetData(),
response,
/*send_async=*/false) == PacketResult::Success)
{
@@ -392,6 +415,8 @@ GDBRemoteCommunicationClient::GetRemoteQ
}
if (::strstr (response_cstr, "qXfer:libraries:read+"))
m_supports_qXfer_libraries_read = eLazyBoolYes;
+ if (::strstr (response_cstr, "qXfer:features:read+"))
+ m_supports_qXfer_features_read = eLazyBoolYes;
const char *packet_size_str = ::strstr (response_cstr, "PacketSize=");
if (packet_size_str)
@@ -3776,3 +3801,74 @@ GDBRemoteCommunicationClient::GetModuleI
return true;
}
+
+// query the target remote for extended information using the qXfer
+packet // // example: object='features', annex='target.xml', out=<xml
+output> // return: 'true' on success
+// 'false' on failure (err set)
+bool
+GDBRemoteCommunicationClient::ReadExtFeature (const lldb_private::ConstString object,
+ const lldb_private::ConstString annex,
+ std::string & out,
+ lldb_private::Error &
+err) {
+
+ std::stringstream output;
+ StringExtractorGDBRemote chunk;
+
+ const int size = 0xfff;
+ int offset = 0;
+ bool active = true;
+
+ // loop until all data has been read
+ while ( active ) {
+
+ // send query extended feature packet
+ std::stringstream packet;
+ packet << "qXfer:"
+ << object.AsCString( ) << ":read:"
+ << annex.AsCString( ) << ":"
+ << std::hex << offset << ","
+ << std::hex << size;
+
+ GDBRemoteCommunication::PacketResult res =
+ SendPacketAndWaitForResponse( packet.str().c_str(),
+ chunk,
+ false );
+
+ if ( res != GDBRemoteCommunication::PacketResult::Success ) {
+ err.SetErrorString( "Error sending $qXfer packet" );
+ return false;
+ }
+
+ const std::string & str = chunk.GetStringRef( );
+ if ( str.length() == 0 ) {
+ // should have some data in chunk
+ err.SetErrorString( "Empty response from $qXfer packet" );
+ return false;
+ }
+
+ // check packet code
+ switch ( str[0] ) {
+ // last chunk
+ case ( 'l' ):
+ active = false;
+ // fall through intensional
+
+ // more chunks
+ case ( 'm' ) :
+ if ( str.length() > 1 )
+ output << &str[1];
+ break;
+
+ // unknown chunk
+ default:
+ err.SetErrorString( "Invalid continuation code from $qXfer packet" );
+ return false;
+ }
+ }
+
+ out = output.str( );
+ err.Success( );
+ return true;
+}
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h?rev=235109&r1=235108&r2=235109&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationC
+++ lient.h Thu Apr 16 10:51:33 2015
@@ -426,6 +426,9 @@ public:
bool
GetAugmentedLibrariesSVR4ReadSupported ();
+ bool
+ GetQXferFeaturesReadSupported ();
+
LazyBool
SupportsAllocDeallocMemory () // const
{
@@ -533,6 +536,12 @@ public:
const ArchSpec& arch_spec,
ModuleSpec &module_spec);
+ bool
+ ReadExtFeature (const lldb_private::ConstString object,
+ const lldb_private::ConstString annex,
+ std::string & out,
+ lldb_private::Error & err);
+
protected:
PacketResult
@@ -576,6 +585,7 @@ protected:
LazyBool m_supports_qXfer_auxv_read;
LazyBool m_supports_qXfer_libraries_read;
LazyBool m_supports_qXfer_libraries_svr4_read;
+ LazyBool m_supports_qXfer_features_read;
LazyBool m_supports_augmented_libraries_svr4_read;
LazyBool m_supports_jThreadExtendedInfo;
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=235109&r1=235108&r2=235109&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ Thu Apr 16 10:51:33 2015
@@ -27,6 +27,9 @@
#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"
@@ -571,6 +574,10 @@ ProcessGDBRemote::BuildDynamicRegisterIn
if (reg_num == 0)
{
+ // try to extract information from servers target.xml
+ if ( GetGDBServerInfo( ) )
+ return;
+
FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();
if (target_definition_fspec)
@@ -3429,6 +3436,465 @@ ProcessGDBRemote::GetModuleSpec(const Fi
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 {
+
+ std::string m_arch;
+ std::string m_osabi;
+};
+
+// conversion table between gdb register type and enum struct {
+ const char * m_name;
+ GdbServerRegisterInfo::RegType m_type; } RegTypeTable[] = {
+ { "int32" , GdbServerRegisterInfo::eInt32 },
+ { "int" , GdbServerRegisterInfo::eInt32 },
+ { "data_ptr", GdbServerRegisterInfo::eDataPtr },
+ { "code_ptr", GdbServerRegisterInfo::eCodePtr },
+ { "i387_ext", GdbServerRegisterInfo::eI387Ext }, // 80bit fpu
+ { nullptr } // sentinel
+};
+
+// 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) {
+
+ if ( !doc ) return false;
+ xmlNodePtr elm = xmlExFindElement( doc->children, { "feature" } );
+ if ( !elm ) return false;
+
+ xmlAttrPtr attr = nullptr;
+
+ xmlNodePtrVec regs;
+ xmlExFindChildren( elm, "reg", regs );
+ for ( int 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;
+
+ // search the type table for a match
+ for ( int j = 0; RegTypeTable[j].m_name !=nullptr ;++j ) {
+ if (RegTypeTable[j].m_name == v) {
+ reg.m_type = RegTypeTable[j].m_type;
+ break;
+ }
+ }
+
+ 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" ) {
+ regNumGeneric = LLDB_REGNUM_GENERIC_SP;
+ }
+ if ( name == "ebp") {
+ regNumGeneric = LLDB_REGNUM_GENERIC_FP;
+ }
+ if ( name == "lr" ) {
+ regNumGeneric = LLDB_REGNUM_GENERIC_RA;
+ }
+
+ 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 ();
+}
+
+} // 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
+// 'false' on failure
+bool
+ProcessGDBRemote::GetGDBServerInfo ()
+{
+
+ // 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( ) )
+ return false;
+
+ // request the target xml file
+ std::string raw;
+ lldb_private::Error lldberr;
+ if (! comm.ReadExtFeature( ConstString( "features" ),
+ ConstString( "target.xml" ),
+ raw,
+ lldberr ) ) {
+ 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
+ }
+
+ // collect registers from all of the includes
+ GDBServerRegisterVec regList;
+ stringVec includes;
+ if ( parseTargetIncludes( doc, includes ) > 0 ) {
+
+ for ( uint32_t i = 0; i < includes.size( ); ++i ) {
+
+ // 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 );
+ }
+ }
+
+ // pass all of these registers to lldb
+ BuildRegisters( regList, regInfo );
+
+ return true;
+}
+
+#else // if defined( LIBXML2_DEFINED )
+
+using namespace lldb_private::process_gdb_remote;
+
+bool
+ProcessGDBRemote::GetGDBServerInfo ()
+{
+ // stub (libxml2 not present)
+ return false;
+}
+
+#endif // if defined( LIBXML2_DEFINED )
+
+
class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed {
private:
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=235109&r1=235108&r2=235109&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Thu
+++ Apr 16 10:51:33 2015
@@ -241,6 +241,10 @@ public:
const ArchSpec& arch,
ModuleSpec &module_spec) override;
+ // query remote gdbserver for information
+ bool
+ GetGDBServerInfo ( );
+
protected:
friend class ThreadGDBRemote;
friend class GDBRemoteCommunicationClient;
_______________________________________________
lldb-commits mailing list
lldb-commits at cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
More information about the lldb-commits
mailing list