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