[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