Hi ovyalov,

Fetch object file load address if it isn't specified by the linker

On Android the load address for the linker isn't specified in the rendezvous 
data structure. This patch add a new GDB packet to fetch this information from 
the inferior based on /proc/<pid>/maps if it happens.

http://reviews.llvm.org/D10490

Files:
  include/lldb/Target/Process.h
  source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
  source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
  source/Utility/StringExtractorGDBRemote.cpp
  source/Utility/StringExtractorGDBRemote.h

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/lldb/Target/Process.h
===================================================================
--- include/lldb/Target/Process.h
+++ include/lldb/Target/Process.h
@@ -3036,6 +3036,12 @@
     virtual bool
     GetModuleSpec(const FileSpec& module_file_spec, const ArchSpec& arch, ModuleSpec &module_spec);
 
+    virtual Error
+    GetFileLoadAddress(const FileSpec& file, lldb::addr_t& load_addr)
+    {
+        return Error("Not supported");
+    }
+
 protected:
 
     //------------------------------------------------------------------
Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
===================================================================
--- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -409,6 +409,17 @@
 
     entry.file_spec.SetFile(ReadStringFromMemory(entry.path_addr), false);
 
+    // The base_addr is not filled in for some case.
+    // Try to figure it out based on the load address of the object file.
+    if (entry.base_addr == 0)
+    {
+        lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
+        Error error = m_process.GetFileLoadAddress(entry.file_spec, load_addr);
+        if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS)
+            return false;
+        entry.base_addr = load_addr;
+    }
+
     return true;
 }
 
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -2600,6 +2600,54 @@
     return SendPacketNoLock(response.GetData(), response.GetSize());
 }
 
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress (StringExtractorGDBRemote &packet)
+{
+    // Fail if we don't have a current process.
+    if (!m_debugged_process_sp ||
+            m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)
+        return SendErrorResponse(67);
+
+    packet.SetFilePos(strlen("qFileLoadAddress:"));
+    if (packet.GetBytesLeft() == 0)
+        return SendErrorResponse(68);
+
+    std::string file_name;
+    packet.GetHexByteString(file_name);
+
+    lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS;
+    Error error = ProcFileReader::ProcessLineByLine (GetID (), "maps",
+        [&] (const std::string &line) -> bool
+        {
+            StringRef maps_row(line);
+ 
+            SmallVector<StringRef, 16> maps_columns;
+            maps_row.split(maps_columns, StringRef(" "), -1, false);
+ 
+            if (maps_columns.size() >= 6)
+            {
+                if (maps_columns[5] == file_name)
+                {
+                    StringExtractor addr_extractor(maps_columns[0].str().c_str());
+                    file_load_address = addr_extractor.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); 
+
+                    // Return false to stop reading the proc file further
+                    return false;
+                }
+            }
+ 
+            // Return true to continue reading the proc file
+            return true;
+        });
+ 
+    if (error.Fail())
+        return SendErrorResponse(69);
+
+    StreamGDBRemote response;
+    response.PutHex64(file_load_address);
+    return SendPacketNoLock(response.GetData(), response.GetSize());
+}
+
 void
 GDBRemoteCommunicationServerLLGS::FlushInferiorOutput ()
 {
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -236,6 +236,9 @@
     PacketResult
     Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet);
 
+    PacketResult
+    Handle_qFileLoadAddress (StringExtractorGDBRemote &packet);
+
     void
     SetCurrentThreadID (lldb::tid_t tid);
 
Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -4115,6 +4115,30 @@
     return new_modules.GetSize();
 }
 
+Error
+ProcessGDBRemote::GetFileLoadAddress(const FileSpec& file, lldb::addr_t& load_addr)
+{
+    load_addr = LLDB_INVALID_ADDRESS;
+
+    std::string file_path = file.GetPath(false);
+    if (file_path.empty ())
+        return Error("Empty file path");
+
+    StreamString packet;
+    packet.PutCString("qFileLoadAddress:");
+    packet.PutCStringAsRawHex8(file_path.c_str());
+
+    StringExtractorGDBRemote response;
+    if (m_gdb_comm.SendPacketAndWaitForResponse(packet.c_str(), response, false) != GDBRemoteCommunication::PacketResult::Success)
+        return Error("Fetching file load address from remote server failed").
+
+    if (!response.IsNormalResponse())
+        return Error("Fetching file load address from remote server returned an error").
+
+    load_addr = GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
+    return Error();
+}
+
 class CommandObjectProcessGDBRemoteSpeedTest: public CommandObjectParsed
 {
 public:
Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
===================================================================
--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -238,8 +238,11 @@
                   const ArchSpec& arch,
                   ModuleSpec &module_spec) override;
 
-    virtual size_t
-    LoadModules () override;
+    size_t
+    LoadModules() override;
+
+    Error
+    GetFileLoadAddress(const FileSpec& file, lldb::addr_t& load_addr) override;
 
 protected:
     friend class ThreadGDBRemote;
Index: source/Utility/StringExtractorGDBRemote.cpp
===================================================================
--- source/Utility/StringExtractorGDBRemote.cpp
+++ source/Utility/StringExtractorGDBRemote.cpp
@@ -144,6 +144,10 @@
             if (PACKET_STARTS_WITH ("qEcho:"))                  return eServerPacketType_qEcho;
             break;
 
+        case 'F':
+            if (PACKET_STARTS_WITH ("qFileLoadAddress:"))       return eServerPacketType_qFileLoadAddress;
+            break;
+
         case 'G':
             if (PACKET_STARTS_WITH ("qGroupName:"))             return eServerPacketType_qGroupName;
             if (PACKET_MATCHES ("qGetWorkingDir"))              return eServerPacketType_qGetWorkingDir;
Index: source/Utility/StringExtractorGDBRemote.h
===================================================================
--- source/Utility/StringExtractorGDBRemote.h
+++ source/Utility/StringExtractorGDBRemote.h
@@ -61,6 +61,7 @@
         eServerPacketType_qSpeedTest,
         eServerPacketType_qUserName,
         eServerPacketType_qGetWorkingDir,
+        eServerPacketType_qFileLoadAddress,
         eServerPacketType_QEnvironment,
         eServerPacketType_QLaunchArch,
         eServerPacketType_QSetDisableASLR,
_______________________________________________
lldb-commits mailing list
lldb-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to