diff options
author | Tamas Berghammer <tberghammer@google.com> | 2015-06-18 20:43:56 +0000 |
---|---|---|
committer | Tamas Berghammer <tberghammer@google.com> | 2015-06-18 20:43:56 +0000 |
commit | 783bfc8caa4c50c0248f90ea7adf2dbd1e48f4e7 (patch) | |
tree | 694f259f810cd5047c9525287ec609d39d78fede | |
parent | d2158755eb718da05fc0ba817b9b7fb64d74a54f (diff) | |
download | bcm5719-llvm-783bfc8caa4c50c0248f90ea7adf2dbd1e48f4e7.tar.gz bcm5719-llvm-783bfc8caa4c50c0248f90ea7adf2dbd1e48f4e7.zip |
Fetch object file load address if it isn't specified by the linker
Differential revision: http://reviews.llvm.org/D10490
llvm-svn: 240052
12 files changed, 176 insertions, 2 deletions
diff --git a/lldb/docs/lldb-gdb-remote.txt b/lldb/docs/lldb-gdb-remote.txt index 2b89c3451f0..b471b245f85 100644 --- a/lldb/docs/lldb-gdb-remote.txt +++ b/lldb/docs/lldb-gdb-remote.txt @@ -988,6 +988,24 @@ for this region. //---------------------------------------------------------------------- //---------------------------------------------------------------------- +// qFileLoadAddress:<file_path> +// +// BRIEF +// Get the load address of a memory mapped file. +// The load address is defined as the address of the first memory +// region what contains data mapped from the specified file. +// +// RESPONSE +// <unsinged-hex64> - Load address of the file in big endian encoding +// "E01" - the requested file isn't loaded +// "EXX" - for any other errors +// +// PRIORITY TO IMPLEMENT +// Low, required if dynamic linker don't fill in the load address of +// some object file in the rendezvous data structure. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- // qModuleInfo:<module_path>;<arch triple> // // BRIEF diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h index a1ddaec7f8a..f6a685aae14 100644 --- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -16,6 +16,7 @@ #include "lldb/lldb-types.h" #include "lldb/Core/Error.h" #include "lldb/Host/Mutex.h" +#include "llvm/ADT/StringRef.h" #include "NativeBreakpointList.h" #include "NativeWatchpointList.h" @@ -293,6 +294,9 @@ namespace lldb_private virtual Error GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) = 0; + virtual Error + GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr) = 0; + protected: lldb::pid_t m_pid; diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index 17bc88897a8..0e0838d4bc3 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -3036,6 +3036,28 @@ public: virtual bool GetModuleSpec(const FileSpec& module_file_spec, const ArchSpec& arch, ModuleSpec &module_spec); + //------------------------------------------------------------------ + /// Try to find the load address of a file. + /// The load address is defined as the address of the first memory + /// region what contains data mapped from the specified file. + /// + /// @param[in] file + /// The name of the file whose load address we are looking for + /// + /// @param[out] is_loaded + /// \b True if the file is loaded into the memory and false + /// otherwise. + /// + /// @param[out] load_addr + /// The load address of the file if it is loaded into the + /// processes address space, LLDB_INVALID_ADDRESS otherwise. + //------------------------------------------------------------------ + virtual Error + GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr) + { + return Error("Not supported"); + } + protected: //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 2d17fccd75a..b8cc286874c 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -412,6 +412,17 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) 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; + bool is_loaded = false; + Error error = m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr); + if (error.Success() && is_loaded) + entry.base_addr = load_addr; + } + return true; } diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index be07b436580..be4b3193050 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -3649,6 +3649,39 @@ NativeProcessLinux::GetLoadedModuleFileSpec(const char* module_path, FileSpec& f } Error +NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr) +{ + load_addr = 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) + { + // Return true to continue reading the proc file + return true; + } + + if (maps_columns[5] == file_name) + { + StringExtractor addr_extractor(maps_columns[0].str().c_str()); + load_addr = 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; + }); + return error; +} + +Error NativeProcessLinux::ResumeThread( lldb::tid_t tid, NativeThreadLinux::ResumeThreadFunction request_thread_resume_function, diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h index 137f7fdf8a9..1964aea6a19 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -152,6 +152,9 @@ namespace process_linux { Error GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) override; + Error + GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr) override; + // --------------------------------------------------------------------- // Interface used by NativeRegisterContext-derived classes. // --------------------------------------------------------------------- diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 8b31dbecec7..e8955ddbd6e 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -53,6 +53,7 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; +using namespace llvm; //---------------------------------------------------------------------- // GDBRemote Errors @@ -134,6 +135,8 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() &GDBRemoteCommunicationServerLLGS::Handle_qC); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qfThreadInfo, &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress, + &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo, @@ -2600,6 +2603,34 @@ GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo (StringExtractor 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 = m_debugged_process_sp->GetFileLoadAddress(file_name, file_load_address); + if (error.Fail()) + return SendErrorResponse(69); + + if (file_load_address == LLDB_INVALID_ADDRESS) + return SendErrorResponse(1); // File not loaded + + StreamGDBRemote response; + response.PutHex64(file_load_address); + return SendPacketNoLock(response.GetData(), response.GetSize()); +} + void GDBRemoteCommunicationServerLLGS::FlushInferiorOutput () { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index a5e2bbcc2be..1eda0b052bb 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -236,6 +236,9 @@ protected: PacketResult Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet); + PacketResult + Handle_qFileLoadAddress (StringExtractorGDBRemote &packet); + void SetCurrentThreadID (lldb::tid_t tid); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 355f052b786..64972dfda36 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -4121,6 +4121,47 @@ ProcessGDBRemote::LoadModules () return new_modules.GetSize(); } +Error +ProcessGDBRemote::GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr) +{ + is_loaded = false; + load_addr = LLDB_INVALID_ADDRESS; + + std::string file_path = file.GetPath(false); + if (file_path.empty ()) + return Error("Empty file name specified"); + + StreamString packet; + packet.PutCString("qFileLoadAddress:"); + packet.PutCStringAsRawHex8(file_path.c_str()); + + StringExtractorGDBRemote response; + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(), response, false) != GDBRemoteCommunication::PacketResult::Success) + return Error("Sending qFileLoadAddress packet failed"); + + if (response.IsErrorResponse()) + { + if (response.GetError() == 1) + { + // The file is not loaded into the inferior + is_loaded = false; + load_addr = LLDB_INVALID_ADDRESS; + return Error(); + } + + return Error("Fetching file load address from remote server returned an error"); + } + + if (response.IsNormalResponse()) + { + is_loaded = true; + load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); + return Error(); + } + + return Error("Unknown error happened during sending the load address packet"); +} + class CommandObjectProcessGDBRemoteSpeedTest: public CommandObjectParsed { public: diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 21e633301d0..02f449ffca4 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -238,8 +238,11 @@ public: const ArchSpec& arch, ModuleSpec &module_spec) override; - virtual size_t - LoadModules () override; + size_t + LoadModules() override; + + Error + GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr) override; protected: friend class ThreadGDBRemote; diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp index 718c8f6e996..aeceaa00fa1 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -144,6 +144,10 @@ StringExtractorGDBRemote::GetServerPacketType () const 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; diff --git a/lldb/source/Utility/StringExtractorGDBRemote.h b/lldb/source/Utility/StringExtractorGDBRemote.h index 78f60217d86..beb07e5b57e 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.h +++ b/lldb/source/Utility/StringExtractorGDBRemote.h @@ -61,6 +61,7 @@ public: eServerPacketType_qSpeedTest, eServerPacketType_qUserName, eServerPacketType_qGetWorkingDir, + eServerPacketType_qFileLoadAddress, eServerPacketType_QEnvironment, eServerPacketType_QLaunchArch, eServerPacketType_QSetDisableASLR, |