<p dir="ltr">The same thing for me as I wrote in <a href="http://reviews.llvm.org/rL235109">http://reviews.llvm.org/rL235109</a>.</p>
<p dir="ltr">Thanks,<br>
Ilia </p>
<div class="gmail_quote">On Apr 17, 2015 12:35 AM, "Chuck Ries" <<a href="mailto:Chuck.Ries@microsoft.com">Chuck.Ries@microsoft.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">After this change I am seeing the cmake build broken on mac os.<br>
<br>
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!<br>
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<br>
/Users/chuckr/llama/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp:31:10: fatal error: 'libxml/xmlreader.h' file not found<br>
#include <libxml/xmlreader.h><br>
^<br>
1 error generated.<br>
<br>
-----Original Message-----<br>
From: <a href="mailto:lldb-commits-bounces@cs.uiuc.edu">lldb-commits-bounces@cs.uiuc.edu</a> [mailto:<a href="mailto:lldb-commits-bounces@cs.uiuc.edu">lldb-commits-bounces@cs.uiuc.edu</a>] On Behalf Of Colin Riley<br>
Sent: Thursday, April 16, 2015 8:52 AM<br>
To: <a href="mailto:lldb-commits@cs.uiuc.edu">lldb-commits@cs.uiuc.edu</a><br>
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.<br>
<br>
Author: domipheus<br>
Date: Thu Apr 16 10:51:33 2015<br>
New Revision: 235109<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=235109&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=235109&view=rev</a><br>
Log:<br>
Adds lldb support for querying the register mapping from gdbserver remote targets using qXfer:features:read packet. Only enabled if libxml2 enabled in build.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D8999" target="_blank">http://reviews.llvm.org/D8999</a><br>
<br>
Modified:<br>
lldb/trunk/cmake/modules/LLDBConfig.cmake<br>
lldb/trunk/source/Commands/CommandObjectRegister.cpp<br>
lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp<br>
lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h<br>
lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp<br>
lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h<br>
<br>
Modified: lldb/trunk/cmake/modules/LLDBConfig.cmake<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/cmake/modules/LLDBConfig.cmake?rev=235109&r1=235108&r2=235109&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/cmake/modules/LLDBConfig.cmake?rev=235109&r1=235108&r2=235109&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/cmake/modules/LLDBConfig.cmake (original)<br>
+++ lldb/trunk/cmake/modules/LLDBConfig.cmake Thu Apr 16 10:51:33 2015<br>
@@ -187,29 +187,39 @@ install(DIRECTORY include/<br>
DESTINATION include<br>
FILES_MATCHING<br>
PATTERN "*.h"<br>
- PATTERN ".svn" EXCLUDE<br>
- )<br>
-<br>
-<br>
-# Find libraries or frameworks that may be needed -if (CMAKE_SYSTEM_NAME MATCHES "Darwin")<br>
+ PATTERN ".svn" EXCLUDE<br>
+ )<br>
+<br>
+if (NOT LIBXML2_FOUND)<br>
+ find_package(LibXml2)<br>
+endif()<br>
+<br>
+# Find libraries or frameworks that may be needed if (CMAKE_SYSTEM_NAME<br>
+MATCHES "Darwin")<br>
find_library(CARBON_LIBRARY Carbon)<br>
find_library(FOUNDATION_LIBRARY Foundation)<br>
find_library(CORE_FOUNDATION_LIBRARY CoreFoundation)<br>
find_library(CORE_SERVICES_LIBRARY CoreServices)<br>
- find_library(SECURITY_LIBRARY Security)<br>
- find_library(DEBUG_SYMBOLS_LIBRARY DebugSymbols PATHS "/System/Library/PrivateFrameworks")<br>
-<br>
- if (NOT LIBXML2_FOUND)<br>
- find_package(LibXml2)<br>
- endif ()<br>
- list(APPEND system_libs xml2 ncurses panel)<br>
- list(APPEND system_libs ${CARBON_LIBRARY} ${FOUNDATION_LIBRARY}<br>
- ${CORE_FOUNDATION_LIBRARY} ${CORE_SERVICES_LIBRARY} ${SECURITY_LIBRARY}<br>
- ${DEBUG_SYMBOLS_LIBRARY})<br>
-endif()<br>
-<br>
-if(LLDB_REQUIRES_EH)<br>
+ find_library(SECURITY_LIBRARY Security)<br>
+ find_library(DEBUG_SYMBOLS_LIBRARY DebugSymbols PATHS<br>
+ "/System/Library/PrivateFrameworks")<br>
+<br>
+ add_definitions( -DLIBXML2_DEFINED )<br>
+ list(APPEND system_libs xml2 ncurses panel) list(APPEND system_libs<br>
+ ${CARBON_LIBRARY} ${FOUNDATION_LIBRARY} ${CORE_FOUNDATION_LIBRARY}<br>
+ ${CORE_SERVICES_LIBRARY} ${SECURITY_LIBRARY}<br>
+ ${DEBUG_SYMBOLS_LIBRARY})<br>
+<br>
+else()<br>
+<br>
+ if (LIBXML2_FOUND)<br>
+ add_definitions( -DLIBXML2_DEFINED )<br>
+ list(APPEND system_libs ${LIBXML2_LIBRARIES})<br>
+ include_directories(${LIBXML2_INCLUDE_DIR})<br>
+ endif()<br>
+<br>
+endif()<br>
+<br>
+if(LLDB_REQUIRES_EH)<br>
set(LLDB_REQUIRES_RTTI ON)<br>
else()<br>
if(LLVM_COMPILER_IS_GCC_COMPATIBLE)<br>
<br>
Modified: lldb/trunk/source/Commands/CommandObjectRegister.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectRegister.cpp?rev=235109&r1=235108&r2=235109&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectRegister.cpp?rev=235109&r1=235108&r2=235109&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Commands/CommandObjectRegister.cpp (original)<br>
+++ lldb/trunk/source/Commands/CommandObjectRegister.cpp Thu Apr 16<br>
+++ 10:51:33 2015<br>
@@ -144,7 +144,7 @@ public:<br>
const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx);<br>
if (reg_set)<br>
{<br>
- strm.Printf ("%s:\n", reg_set->name);<br>
+ strm.Printf ("%s:\n", (reg_set->name ? reg_set->name :<br>
+ "unknown") );<br>
strm.IndentMore ();<br>
const size_t num_registers = reg_set->num_registers;<br>
for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)<br>
<br>
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=235109&r1=235108&r2=235109&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=235109&r1=235108&r2=235109&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original)<br>
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationC<br>
+++ lient.cpp Thu Apr 16 10:51:33 2015<br>
@@ -79,6 +79,7 @@ GDBRemoteCommunicationClient::GDBRemoteC<br>
m_supports_QSaveRegisterState (eLazyBoolCalculate),<br>
m_supports_qXfer_auxv_read (eLazyBoolCalculate),<br>
m_supports_qXfer_libraries_read (eLazyBoolCalculate),<br>
+ m_supports_qXfer_features_read (eLazyBoolCalculate),<br>
m_supports_qXfer_libraries_svr4_read (eLazyBoolCalculate),<br>
m_supports_augmented_libraries_svr4_read (eLazyBoolCalculate),<br>
m_supports_jThreadExtendedInfo (eLazyBoolCalculate), @@ -214,6 +215,16 @@ GDBRemoteCommunicationClient::GetQXferAu<br>
return (m_supports_qXfer_auxv_read == eLazyBoolYes); }<br>
<br>
+bool<br>
+GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported () {<br>
+ if (m_supports_qXfer_features_read == eLazyBoolCalculate)<br>
+ {<br>
+ GetRemoteQSupported();<br>
+ }<br>
+ return (m_supports_qXfer_features_read == eLazyBoolYes); }<br>
+<br>
uint64_t<br>
GDBRemoteCommunicationClient::GetRemoteMaxPacketSize()<br>
{<br>
@@ -335,6 +346,7 @@ GDBRemoteCommunicationClient::ResetDisco<br>
m_supports_qXfer_auxv_read = eLazyBoolCalculate;<br>
m_supports_qXfer_libraries_read = eLazyBoolCalculate;<br>
m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;<br>
+ m_supports_qXfer_features_read = eLazyBoolCalculate;<br>
m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;<br>
<br>
m_supports_qProcessInfoPID = true;<br>
@@ -373,10 +385,21 @@ GDBRemoteCommunicationClient::GetRemoteQ<br>
m_supports_qXfer_libraries_read = eLazyBoolNo;<br>
m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;<br>
m_supports_augmented_libraries_svr4_read = eLazyBoolNo;<br>
+ m_supports_qXfer_features_read = eLazyBoolNo;<br>
m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if not, we assume no limit<br>
<br>
+ // build the qSupported packet<br>
+ std::vector<std::string> features = {"xmlRegisters=i386,arm,mips"};<br>
+ StreamString packet;<br>
+ packet.PutCString( "qSupported" );<br>
+ for ( uint32_t i = 0; i < features.size( ); ++i )<br>
+ {<br>
+ packet.PutCString( i==0 ? ":" : ";");<br>
+ packet.PutCString( features[i].c_str( ) );<br>
+ }<br>
+<br>
StringExtractorGDBRemote response;<br>
- if (SendPacketAndWaitForResponse("qSupported",<br>
+ if (SendPacketAndWaitForResponse(packet.GetData(),<br>
response,<br>
/*send_async=*/false) == PacketResult::Success)<br>
{<br>
@@ -392,6 +415,8 @@ GDBRemoteCommunicationClient::GetRemoteQ<br>
}<br>
if (::strstr (response_cstr, "qXfer:libraries:read+"))<br>
m_supports_qXfer_libraries_read = eLazyBoolYes;<br>
+ if (::strstr (response_cstr, "qXfer:features:read+"))<br>
+ m_supports_qXfer_features_read = eLazyBoolYes;<br>
<br>
const char *packet_size_str = ::strstr (response_cstr, "PacketSize=");<br>
if (packet_size_str)<br>
@@ -3776,3 +3801,74 @@ GDBRemoteCommunicationClient::GetModuleI<br>
<br>
return true;<br>
}<br>
+<br>
+// query the target remote for extended information using the qXfer<br>
+packet // // example: object='features', annex='target.xml', out=<xml<br>
+output> // return: 'true' on success<br>
+// 'false' on failure (err set)<br>
+bool<br>
+GDBRemoteCommunicationClient::ReadExtFeature (const lldb_private::ConstString object,<br>
+ const lldb_private::ConstString annex,<br>
+ std::string & out,<br>
+ lldb_private::Error &<br>
+err) {<br>
+<br>
+ std::stringstream output;<br>
+ StringExtractorGDBRemote chunk;<br>
+<br>
+ const int size = 0xfff;<br>
+ int offset = 0;<br>
+ bool active = true;<br>
+<br>
+ // loop until all data has been read<br>
+ while ( active ) {<br>
+<br>
+ // send query extended feature packet<br>
+ std::stringstream packet;<br>
+ packet << "qXfer:"<br>
+ << object.AsCString( ) << ":read:"<br>
+ << annex.AsCString( ) << ":"<br>
+ << std::hex << offset << ","<br>
+ << std::hex << size;<br>
+<br>
+ GDBRemoteCommunication::PacketResult res =<br>
+ SendPacketAndWaitForResponse( packet.str().c_str(),<br>
+ chunk,<br>
+ false );<br>
+<br>
+ if ( res != GDBRemoteCommunication::PacketResult::Success ) {<br>
+ err.SetErrorString( "Error sending $qXfer packet" );<br>
+ return false;<br>
+ }<br>
+<br>
+ const std::string & str = chunk.GetStringRef( );<br>
+ if ( str.length() == 0 ) {<br>
+ // should have some data in chunk<br>
+ err.SetErrorString( "Empty response from $qXfer packet" );<br>
+ return false;<br>
+ }<br>
+<br>
+ // check packet code<br>
+ switch ( str[0] ) {<br>
+ // last chunk<br>
+ case ( 'l' ):<br>
+ active = false;<br>
+ // fall through intensional<br>
+<br>
+ // more chunks<br>
+ case ( 'm' ) :<br>
+ if ( str.length() > 1 )<br>
+ output << &str[1];<br>
+ break;<br>
+<br>
+ // unknown chunk<br>
+ default:<br>
+ err.SetErrorString( "Invalid continuation code from $qXfer packet" );<br>
+ return false;<br>
+ }<br>
+ }<br>
+<br>
+ out = output.str( );<br>
+ err.Success( );<br>
+ return true;<br>
+}<br>
<br>
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h?rev=235109&r1=235108&r2=235109&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h?rev=235109&r1=235108&r2=235109&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h (original)<br>
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationC<br>
+++ lient.h Thu Apr 16 10:51:33 2015<br>
@@ -426,6 +426,9 @@ public:<br>
bool<br>
GetAugmentedLibrariesSVR4ReadSupported ();<br>
<br>
+ bool<br>
+ GetQXferFeaturesReadSupported ();<br>
+<br>
LazyBool<br>
SupportsAllocDeallocMemory () // const<br>
{<br>
@@ -533,6 +536,12 @@ public:<br>
const ArchSpec& arch_spec,<br>
ModuleSpec &module_spec);<br>
<br>
+ bool<br>
+ ReadExtFeature (const lldb_private::ConstString object,<br>
+ const lldb_private::ConstString annex,<br>
+ std::string & out,<br>
+ lldb_private::Error & err);<br>
+<br>
protected:<br>
<br>
PacketResult<br>
@@ -576,6 +585,7 @@ protected:<br>
LazyBool m_supports_qXfer_auxv_read;<br>
LazyBool m_supports_qXfer_libraries_read;<br>
LazyBool m_supports_qXfer_libraries_svr4_read;<br>
+ LazyBool m_supports_qXfer_features_read;<br>
LazyBool m_supports_augmented_libraries_svr4_read;<br>
LazyBool m_supports_jThreadExtendedInfo;<br>
<br>
<br>
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=235109&r1=235108&r2=235109&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=235109&r1=235108&r2=235109&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)<br>
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp<br>
+++ Thu Apr 16 10:51:33 2015<br>
@@ -27,6 +27,9 @@<br>
#include <mutex><br>
<br>
// Other libraries and framework includes<br>
+#if defined( LIBXML2_DEFINED )<br>
+#include <libxml/xmlreader.h><br>
+#endif<br>
<br>
#include "lldb/Breakpoint/Watchpoint.h"<br>
#include "lldb/Interpreter/Args.h"<br>
@@ -571,6 +574,10 @@ ProcessGDBRemote::BuildDynamicRegisterIn<br>
<br>
if (reg_num == 0)<br>
{<br>
+ // try to extract information from servers target.xml<br>
+ if ( GetGDBServerInfo( ) )<br>
+ return;<br>
+<br>
FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();<br>
<br>
if (target_definition_fspec)<br>
@@ -3429,6 +3436,465 @@ ProcessGDBRemote::GetModuleSpec(const Fi<br>
return true;<br>
}<br>
<br>
+#if defined( LIBXML2_DEFINED )<br>
+namespace {<br>
+<br>
+typedef std::vector<std::string> stringVec; typedef<br>
+std::vector<xmlNodePtr> xmlNodePtrVec;<br>
+<br>
+struct GdbServerRegisterInfo {<br>
+<br>
+ struct {<br>
+ bool m_has_name : 1;<br>
+ bool m_has_bitSize : 1;<br>
+ bool m_has_type : 1;<br>
+ bool m_has_group : 1;<br>
+ bool m_has_regNum : 1;<br>
+ }<br>
+ m_flags;<br>
+<br>
+ std::string m_name;<br>
+ std::string m_group;<br>
+ uint32_t m_bitSize;<br>
+ uint32_t m_regNum;<br>
+<br>
+ enum RegType {<br>
+ eUnknown ,<br>
+ eCodePtr ,<br>
+ eDataPtr ,<br>
+ eInt32 ,<br>
+ eI387Ext ,<br>
+ }<br>
+ m_type;<br>
+<br>
+ void clear( ) {<br>
+ memset( &m_flags, 0, sizeof( m_flags ) );<br>
+ }<br>
+};<br>
+<br>
+typedef std::vector<struct GdbServerRegisterInfo> GDBServerRegisterVec;<br>
+<br>
+struct GdbServerTargetInfo {<br>
+<br>
+ std::string m_arch;<br>
+ std::string m_osabi;<br>
+};<br>
+<br>
+// conversion table between gdb register type and enum struct {<br>
+ const char * m_name;<br>
+ GdbServerRegisterInfo::RegType m_type; } RegTypeTable[] = {<br>
+ { "int32" , GdbServerRegisterInfo::eInt32 },<br>
+ { "int" , GdbServerRegisterInfo::eInt32 },<br>
+ { "data_ptr", GdbServerRegisterInfo::eDataPtr },<br>
+ { "code_ptr", GdbServerRegisterInfo::eCodePtr },<br>
+ { "i387_ext", GdbServerRegisterInfo::eI387Ext }, // 80bit fpu<br>
+ { nullptr } // sentinel<br>
+};<br>
+<br>
+// find the first sibling with a matching name xmlNodePtr<br>
+xmlExFindSibling (xmlNodePtr node,<br>
+ const std::string & name) {<br>
+<br>
+ if ( !node ) return nullptr;<br>
+ // iterate through all siblings<br>
+ for ( xmlNodePtr temp = node; temp; temp=temp->next ) {<br>
+ // we are looking for elements<br>
+ if ( temp->type != XML_ELEMENT_NODE )<br>
+ continue;<br>
+ // check element name matches<br>
+ if ( !temp->name ) continue;<br>
+ if ( std::strcmp((const char*)temp->name, name.c_str() ) == 0 )<br>
+ return temp;<br>
+ }<br>
+ // no sibling found<br>
+ return nullptr;<br>
+}<br>
+<br>
+// find an element from a given element path xmlNodePtr<br>
+xmlExFindElement (xmlNodePtr node,<br>
+ const stringVec & path) {<br>
+<br>
+ if ( !node ) return nullptr;<br>
+ xmlNodePtr temp = node;<br>
+ // iterate all elements in path<br>
+ for ( uint32_t i = 0; i < path.size( ); i++ ) {<br>
+<br>
+ // search for a sibling with this name<br>
+ temp = xmlExFindSibling( temp, path[i] );<br>
+ if ( !temp )<br>
+ return nullptr;<br>
+ // enter this node if we still need to search<br>
+ if ( (i+1) < path.size() )<br>
+ // enter the node we have found<br>
+ temp = temp->children;<br>
+ }<br>
+ // note: node may still be nullptr at this step<br>
+ return temp;<br>
+}<br>
+<br>
+// locate a specific attribute in an element xmlAttr *<br>
+xmlExFindAttribute (xmlNodePtr node,<br>
+ const std::string & name) {<br>
+<br>
+ if ( !node )<br>
+ return nullptr;<br>
+ if ( node->type != XML_ELEMENT_NODE )<br>
+ return nullptr;<br>
+ // iterate over all attributes<br>
+ for ( xmlAttrPtr attr = node->properties; attr != nullptr; attr=attr->next ) {<br>
+ // check if name matches<br>
+ if ( !attr->name ) continue;<br>
+ if ( std::strcmp( (const char*)attr->name, name.c_str( ) ) == 0 )<br>
+ return attr;<br>
+ }<br>
+ return nullptr;<br>
+}<br>
+<br>
+// find all child elements with given name and add them to a vector //<br>
+// input: node = xml element to search<br>
+// name = name used when matching child elements<br>
+// output: out = list of matches<br>
+// return: number of children added to 'out'<br>
+int<br>
+xmlExFindChildren (xmlNodePtr node,<br>
+ const std::string & name,<br>
+ xmlNodePtrVec & out) {<br>
+<br>
+ if ( !node ) return 0;<br>
+ int count = 0;<br>
+ // iterate over all children<br>
+ for ( xmlNodePtr child = node->children; child; child = child->next ) {<br>
+ // if name matches<br>
+ if ( !child->name ) continue;<br>
+ if ( std::strcmp( (const char*)child->name, name.c_str( ) ) == 0 ) {<br>
+ // add to output list<br>
+ out.push_back( child );<br>
+ ++count;<br>
+ }<br>
+ }<br>
+ return count;<br>
+}<br>
+<br>
+// get the text content from an attribute std::string<br>
+xmlExGetTextContent (xmlAttrPtr attr) {<br>
+<br>
+ if ( !attr )<br>
+ return std::string( );<br>
+ if ( attr->type != XML_ATTRIBUTE_NODE )<br>
+ return std::string( );<br>
+ // check child is a text node<br>
+ xmlNodePtr child = attr->children;<br>
+ if ( child->type != XML_TEXT_NODE )<br>
+ return std::string( );<br>
+ // access the content<br>
+ assert( child->content != nullptr );<br>
+ return std::string( (const char*) child->content ); }<br>
+<br>
+// get the text content from an node<br>
+std::string<br>
+xmlExGetTextContent (xmlNodePtr node) {<br>
+<br>
+ if ( !node )<br>
+ return std::string( );<br>
+ if ( node->type != XML_ELEMENT_NODE )<br>
+ return std::string( );<br>
+ // check child is a text node<br>
+ xmlNodePtr child = node->children;<br>
+ if ( child->type != XML_TEXT_NODE )<br>
+ return std::string( );<br>
+ // access the content<br>
+ assert( child->content != nullptr );<br>
+ return std::string( (const char*) child->content ); }<br>
+<br>
+// compile a list of xml includes from the target file<br>
+// input: doc = target.xml<br>
+// output: includes = list of .xml names specified in target.xml //<br>
+return: number of .xml files specified in target.xml and added to<br>
+includes int parseTargetIncludes (xmlDocPtr doc, stringVec & includes)<br>
+{<br>
+<br>
+ if ( !doc ) return 0;<br>
+ int count = 0;<br>
+ xmlNodePtr elm = xmlExFindElement( doc->children, { "target" } );<br>
+ if (! elm ) return 0;<br>
+ xmlNodePtrVec nodes;<br>
+ xmlExFindChildren( elm, "xi:include", nodes );<br>
+ // iterate over all includes<br>
+ for ( uint32_t i = 0; i < nodes.size(); i++ ) {<br>
+ xmlAttrPtr attr = xmlExFindAttribute( nodes[i], "href" );<br>
+ if ( attr != nullptr ) {<br>
+ std::string text = xmlExGetTextContent( attr );<br>
+ includes.push_back( text );<br>
+ ++count;<br>
+ }<br>
+ }<br>
+ return count;<br>
+}<br>
+<br>
+// extract target arch information from the target.xml file<br>
+// input: doc = target.xml document<br>
+// output: out = remote target information // return: 'true' on<br>
+success<br>
+// 'false' on failure<br>
+bool<br>
+parseTargetInfo (xmlDocPtr doc, GdbServerTargetInfo & out) {<br>
+<br>
+ if ( !doc ) return false;<br>
+ xmlNodePtr e1 = xmlExFindElement( doc->children, { "target", "architecture" } );<br>
+ if ( !e1 ) return false;<br>
+ out.m_arch = xmlExGetTextContent( e1 );<br>
+<br>
+ xmlNodePtr e2 = xmlExFindElement( doc->children, { "target", "osabi" } );<br>
+ if ( !e2 ) return false;<br>
+ out.m_osabi = xmlExGetTextContent( e2 );<br>
+<br>
+ return true;<br>
+}<br>
+<br>
+// extract register information from one of the xml files specified in target.xml<br>
+// input: doc = xml document<br>
+// output: regList = list of extracted register info // return:<br>
+'true' on success<br>
+// 'false' on failure<br>
+bool<br>
+parseRegisters (xmlDocPtr doc, GDBServerRegisterVec & regList) {<br>
+<br>
+ if ( !doc ) return false;<br>
+ xmlNodePtr elm = xmlExFindElement( doc->children, { "feature" } );<br>
+ if ( !elm ) return false;<br>
+<br>
+ xmlAttrPtr attr = nullptr;<br>
+<br>
+ xmlNodePtrVec regs;<br>
+ xmlExFindChildren( elm, "reg", regs );<br>
+ for ( int i = 0; i < regs.size( ); i++ ) {<br>
+<br>
+ GdbServerRegisterInfo reg;<br>
+ reg.clear( );<br>
+<br>
+ if ( attr = xmlExFindAttribute( regs[i], "name" ) ) {<br>
+ reg.m_name = xmlExGetTextContent( attr ).c_str();<br>
+ reg.m_flags.m_has_name = true;<br>
+ }<br>
+<br>
+ if ( attr = xmlExFindAttribute( regs[i], "bitsize" ) ) {<br>
+ const std::string v = xmlExGetTextContent( attr );<br>
+ reg.m_bitSize = atoi( v.c_str( ) );<br>
+ reg.m_flags.m_has_bitSize = true;<br>
+ }<br>
+<br>
+ if ( attr = xmlExFindAttribute( regs[i], "type" ) ) {<br>
+ const std::string v = xmlExGetTextContent( attr );<br>
+ reg.m_type = GdbServerRegisterInfo::eUnknown;<br>
+<br>
+ // search the type table for a match<br>
+ for ( int j = 0; RegTypeTable[j].m_name !=nullptr ;++j ) {<br>
+ if (RegTypeTable[j].m_name == v) {<br>
+ reg.m_type = RegTypeTable[j].m_type;<br>
+ break;<br>
+ }<br>
+ }<br>
+<br>
+ reg.m_flags.m_has_type = (reg.m_type != GdbServerRegisterInfo::eUnknown);<br>
+ }<br>
+<br>
+ if ( attr = xmlExFindAttribute( regs[i], "group" ) ) {<br>
+ reg.m_group = xmlExGetTextContent( attr );<br>
+ reg.m_flags.m_has_group = true;<br>
+ }<br>
+<br>
+ if ( attr = xmlExFindAttribute( regs[i], "regnum" ) ) {<br>
+ const std::string v = xmlExGetTextContent( attr );<br>
+ reg.m_regNum = atoi( v.c_str( ) );<br>
+ reg.m_flags.m_has_regNum = true;<br>
+ }<br>
+<br>
+ regList.push_back( reg );<br>
+ }<br>
+<br>
+ //TODO: there is also a "vector" element to parse<br>
+ //TODO: there is also eflags to parse<br>
+<br>
+ return true;<br>
+}<br>
+<br>
+// build lldb gdb-remote's dynamic register info from a vector of gdb provided registers<br>
+// input: regList = register information provided by gdbserver<br>
+// output: regInfo = dynamic register information required by<br>
+gdb-remote void BuildRegisters (const GDBServerRegisterVec & regList,<br>
+ GDBRemoteDynamicRegisterInfo & regInfo) {<br>
+<br>
+ using namespace lldb_private;<br>
+<br>
+ const uint32_t defSize = 32;<br>
+ uint32_t regNum = 0;<br>
+ uint32_t byteOffset = 0;<br>
+<br>
+ for ( uint32_t i = 0; i < regList.size( ); ++i ) {<br>
+<br>
+ const GdbServerRegisterInfo & gdbReg = regList[i];<br>
+<br>
+ std::string name = gdbReg.m_flags.m_has_name ? gdbReg.m_name : "unknown";<br>
+ std::string group = gdbReg.m_flags.m_has_group ? gdbReg.m_group : "general";<br>
+ uint32_t byteSize = gdbReg.m_flags.m_has_bitSize ? (gdbReg.m_bitSize/8) : defSize;<br>
+<br>
+ if ( gdbReg.m_flags.m_has_regNum )<br>
+ regNum = gdbReg.m_regNum;<br>
+<br>
+ uint32_t regNumGcc = LLDB_INVALID_REGNUM;<br>
+ uint32_t regNumDwarf = LLDB_INVALID_REGNUM;<br>
+ uint32_t regNumGeneric = LLDB_INVALID_REGNUM;<br>
+ uint32_t regNumGdb = regNum;<br>
+ uint32_t regNumNative = regNum;<br>
+<br>
+ if ( name == "eip" || name == "pc" ) {<br>
+ regNumGeneric = LLDB_REGNUM_GENERIC_PC;<br>
+ }<br>
+ if ( name == "esp" || name == "sp" ) {<br>
+ regNumGeneric = LLDB_REGNUM_GENERIC_SP;<br>
+ }<br>
+ if ( name == "ebp") {<br>
+ regNumGeneric = LLDB_REGNUM_GENERIC_FP;<br>
+ }<br>
+ if ( name == "lr" ) {<br>
+ regNumGeneric = LLDB_REGNUM_GENERIC_RA;<br>
+ }<br>
+<br>
+ RegisterInfo info = {<br>
+ name.c_str(),<br>
+ nullptr ,<br>
+ byteSize ,<br>
+ byteOffset ,<br>
+ lldb::Encoding::eEncodingUint,<br>
+ lldb::Format::eFormatDefault,<br>
+ { regNumGcc ,<br>
+ regNumDwarf ,<br>
+ regNumGeneric,<br>
+ regNumGdb ,<br>
+ regNumNative },<br>
+ nullptr,<br>
+ nullptr<br>
+ };<br>
+<br>
+ ConstString regName = ConstString( gdbReg.m_name );<br>
+ ConstString regAltName = ConstString( );<br>
+ ConstString regGroup = ConstString( group );<br>
+ regInfo.AddRegister( info, regName, regAltName, regGroup );<br>
+<br>
+ // advance register info<br>
+ byteOffset += byteSize;<br>
+ regNum += 1;<br>
+ }<br>
+<br>
+ regInfo.Finalize ();<br>
+}<br>
+<br>
+} // namespace {}<br>
+<br>
+void XMLCDECL<br>
+libxml2NullErrorFunc (void *ctx, const char *msg, ...) {<br>
+ // do nothing currently<br>
+}<br>
+<br>
+// query the target of gdb-remote for extended target information //<br>
+return: 'true' on success<br>
+// 'false' on failure<br>
+bool<br>
+ProcessGDBRemote::GetGDBServerInfo ()<br>
+{<br>
+<br>
+ // redirect libxml2's error handler since the default prints to stdout<br>
+ xmlGenericErrorFunc func = libxml2NullErrorFunc;<br>
+ initGenericErrorDefaultFunc( &func );<br>
+<br>
+ GDBRemoteCommunicationClient & comm = m_gdb_comm;<br>
+ GDBRemoteDynamicRegisterInfo & regInfo = m_register_info;<br>
+<br>
+ // check that we have extended feature read support<br>
+ if ( !comm.GetQXferFeaturesReadSupported( ) )<br>
+ return false;<br>
+<br>
+ // request the target xml file<br>
+ std::string raw;<br>
+ lldb_private::Error lldberr;<br>
+ if (! comm.ReadExtFeature( ConstString( "features" ),<br>
+ ConstString( "target.xml" ),<br>
+ raw,<br>
+ lldberr ) ) {<br>
+ return false;<br>
+ }<br>
+<br>
+ // parse the xml file in memory<br>
+ xmlDocPtr doc = xmlReadMemory( raw.c_str( ), raw.size( ), "noname.xml", nullptr, 0 );<br>
+ if ( doc == nullptr )<br>
+ return false;<br>
+<br>
+ // extract target info from target.xml<br>
+ GdbServerTargetInfo gdbInfo;<br>
+ if ( parseTargetInfo( doc, gdbInfo ) ) {<br>
+ // NOTE: We could deduce triple from gdbInfo if lldb doesn't already have one set<br>
+ }<br>
+<br>
+ // collect registers from all of the includes<br>
+ GDBServerRegisterVec regList;<br>
+ stringVec includes;<br>
+ if ( parseTargetIncludes( doc, includes ) > 0 ) {<br>
+<br>
+ for ( uint32_t i = 0; i < includes.size( ); ++i ) {<br>
+<br>
+ // request register file<br>
+ if ( !comm.ReadExtFeature( ConstString( "features" ),<br>
+ ConstString( includes[i] ),<br>
+ raw,<br>
+ lldberr ) )<br>
+ continue;<br>
+<br>
+ // parse register file<br>
+ xmlDocPtr regXml = xmlReadMemory( raw.c_str(),<br>
+ raw.size( ),<br>
+ includes[i].c_str(),<br>
+ nullptr,<br>
+ 0 );<br>
+ if ( !regXml )<br>
+ continue;<br>
+<br>
+ // pass registers to lldb<br>
+ parseRegisters( regXml, regList );<br>
+ }<br>
+ }<br>
+<br>
+ // pass all of these registers to lldb<br>
+ BuildRegisters( regList, regInfo );<br>
+<br>
+ return true;<br>
+}<br>
+<br>
+#else // if defined( LIBXML2_DEFINED )<br>
+<br>
+using namespace lldb_private::process_gdb_remote;<br>
+<br>
+bool<br>
+ProcessGDBRemote::GetGDBServerInfo ()<br>
+{<br>
+ // stub (libxml2 not present)<br>
+ return false;<br>
+}<br>
+<br>
+#endif // if defined( LIBXML2_DEFINED )<br>
+<br>
+<br>
class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed {<br>
private:<br>
<br>
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=235109&r1=235108&r2=235109&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=235109&r1=235108&r2=235109&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)<br>
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Thu<br>
+++ Apr 16 10:51:33 2015<br>
@@ -241,6 +241,10 @@ public:<br>
const ArchSpec& arch,<br>
ModuleSpec &module_spec) override;<br>
<br>
+ // query remote gdbserver for information<br>
+ bool<br>
+ GetGDBServerInfo ( );<br>
+<br>
protected:<br>
friend class ThreadGDBRemote;<br>
friend class GDBRemoteCommunicationClient;<br>
<br>
<br>
_______________________________________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@cs.uiuc.edu">lldb-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits</a><br>
<br>
_______________________________________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@cs.uiuc.edu">lldb-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits</a><br>
</blockquote></div>