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

Ilia K ki.stfu at gmail.com
Thu Apr 16 22:18:21 PDT 2015


The same thing for me as I wrote in http://reviews.llvm.org/rL235109.

Thanks,
Ilia
On Apr 17, 2015 12:35 AM, "Chuck Ries" <Chuck.Ries at microsoft.com> wrote:

> 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/lldbPl!
>  uginProcessGDBRemote.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
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20150417/cd667c6a/attachment.html>


More information about the lldb-commits mailing list