[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.

Colin Riley colin at codeplay.com
Thu Apr 16 08:51:33 PDT 2015


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/GDBRemoteCommunicationClient.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/GDBRemoteCommunicationClient.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;





More information about the lldb-commits mailing list