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

Differential revision: http://reviews.llvm.org/D10490

llvm-svn: 240052
This commit is contained in:
Tamas Berghammer 2015-06-18 20:43:56 +00:00
parent d2158755eb
commit 783bfc8caa
12 changed files with 176 additions and 2 deletions

View File

@ -987,6 +987,24 @@ for this region.
// for the QSaveRegisterState is added.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// 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>
//

View File

@ -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;

View File

@ -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:
//------------------------------------------------------------------

View File

@ -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;
}

View File

@ -3648,6 +3648,39 @@ NativeProcessLinux::GetLoadedModuleFileSpec(const char* module_path, FileSpec& f
module_file_spec.GetFilename().AsCString(), GetID());
}
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,

View File

@ -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.
// ---------------------------------------------------------------------

View File

@ -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 ()
{

View File

@ -236,6 +236,9 @@ protected:
PacketResult
Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qFileLoadAddress (StringExtractorGDBRemote &packet);
void
SetCurrentThreadID (lldb::tid_t tid);

View File

@ -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:

View File

@ -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;

View File

@ -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;

View File

@ -61,6 +61,7 @@ public:
eServerPacketType_qSpeedTest,
eServerPacketType_qUserName,
eServerPacketType_qGetWorkingDir,
eServerPacketType_qFileLoadAddress,
eServerPacketType_QEnvironment,
eServerPacketType_QLaunchArch,
eServerPacketType_QSetDisableASLR,