summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTamas Berghammer <tberghammer@google.com>2015-08-24 10:21:55 +0000
committerTamas Berghammer <tberghammer@google.com>2015-08-24 10:21:55 +0000
commit42ecef3b15e9b74fe6bf8dca6bae76650e095726 (patch)
treea4592ace7d88f818a589866232d7b724ece2c053
parent71ad47f81fb33bbbf0a0713006691ed0c0550b3f (diff)
downloadbcm5719-llvm-42ecef3b15e9b74fe6bf8dca6bae76650e095726.tar.gz
bcm5719-llvm-42ecef3b15e9b74fe6bf8dca6bae76650e095726.zip
Add absolute load address support for the DynamicLoader plugins
The POSIX linker generally reports the load bias for the loaded libraries but in some case it is useful to handle a library based on absolute load address. Example usecases: * Windows linker uses absolute addresses * Library list came from different source (e.g. /proc/<pid>/maps) Differential revision: http://reviews.llvm.org/D12233 llvm-svn: 245834
-rw-r--r--lldb/include/lldb/Target/DynamicLoader.h13
-rw-r--r--lldb/source/Core/DynamicLoader.cpp46
-rw-r--r--lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp20
-rw-r--r--lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h8
-rw-r--r--lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp20
-rw-r--r--lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h13
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp64
7 files changed, 110 insertions, 74 deletions
diff --git a/lldb/include/lldb/Target/DynamicLoader.h b/lldb/include/lldb/Target/DynamicLoader.h
index fc476a9dc9d..5eada0342a2 100644
--- a/lldb/include/lldb/Target/DynamicLoader.h
+++ b/lldb/include/lldb/Target/DynamicLoader.h
@@ -263,12 +263,14 @@ protected:
virtual void
UpdateLoadedSections(lldb::ModuleSP module,
lldb::addr_t link_map_addr,
- lldb::addr_t base_addr);
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset);
// Utility method so base classes can share implementation of UpdateLoadedSections
void
UpdateLoadedSectionsCommon(lldb::ModuleSP module,
- lldb::addr_t base_addr);
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset);
/// Removes the loaded sections from the target in @p module.
///
@@ -282,8 +284,11 @@ protected:
/// Locates or creates a module given by @p file and updates/loads the
/// resulting module at the virtual base address @p base_addr.
- lldb::ModuleSP
- LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr);
+ virtual lldb::ModuleSP
+ LoadModuleAtAddress(const lldb_private::FileSpec &file,
+ lldb::addr_t link_map_addr,
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset);
const lldb_private::SectionList *
GetSectionListFromModule(const lldb::ModuleSP module) const;
diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp
index ffd7425f523..4d2824c5f33 100644
--- a/lldb/source/Core/DynamicLoader.cpp
+++ b/lldb/source/Core/DynamicLoader.cpp
@@ -119,16 +119,20 @@ DynamicLoader::GetTargetExecutable()
}
void
-DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
+DynamicLoader::UpdateLoadedSections(ModuleSP module,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
- UpdateLoadedSectionsCommon(module, base_addr);
+ UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
}
void
-DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module, addr_t base_addr)
+DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
bool changed;
- const bool base_addr_is_offset = true;
module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset, changed);
}
@@ -171,7 +175,10 @@ DynamicLoader::GetSectionListFromModule(const ModuleSP module) const
}
ModuleSP
-DynamicLoader::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr)
+DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
Target &target = m_process->GetTarget();
ModuleList &modules = target.GetImages();
@@ -180,27 +187,28 @@ DynamicLoader::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, a
ModuleSpec module_spec (file, target.GetArchitecture());
if ((module_sp = modules.FindFirstModule (module_spec)))
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset);
}
else if ((module_sp = target.GetSharedModule(module_spec)))
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset);
}
else
{
- // Try to fetch the load address of the file from the process. It can be different from the
- // address reported by the linker in case of a file with fixed load address because the
- // linker reports the bias between the load address specified in the file and the actual
- // load address it loaded the file.
- bool is_loaded;
- lldb::addr_t load_addr;
- Error error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
- if (error.Fail() || !is_loaded)
- load_addr = base_addr;
-
- if ((module_sp = m_process->ReadModuleFromMemory(file, load_addr)))
+ if (base_addr_is_offset)
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ // Try to fetch the load address of the file from the process as we need absolute load
+ // address to read the file out of the memory instead of a load bias.
+ bool is_loaded;
+ lldb::addr_t load_addr;
+ Error error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
+ if (error.Success() && is_loaded)
+ base_addr = load_addr;
+ }
+
+ if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr)))
+ {
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
target.GetImages().AppendIfNeeded(module_sp);
}
}
diff --git a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
index 2308129b8ca..dd2a436299e 100644
--- a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
@@ -177,7 +177,7 @@ DynamicLoaderHexagonDYLD::DidAttach()
// Map the loaded sections of this executable
if ( load_offset != LLDB_INVALID_ADDRESS )
- UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);
// AD: confirm this?
// Load into LLDB all of the currently loaded executables in the stub
@@ -268,7 +268,10 @@ DynamicLoaderHexagonDYLD::CanLoadImage()
}
void
-DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
+DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
Target &target = m_process->GetTarget();
const SectionList *sections = GetSectionListFromModule(module);
@@ -442,7 +445,7 @@ DynamicLoaderHexagonDYLD::RefreshModules()
for (I = m_rendezvous.loaded_begin(); I != E; ++I)
{
FileSpec file(I->path.c_str(), true);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
loaded_modules.AppendIfNeeded( module_sp );
@@ -571,7 +574,7 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules()
{
const char *module_path = I->path.c_str();
FileSpec file(module_path, false);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
module_list.Append(module_sp);
@@ -591,7 +594,10 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules()
/// Helper for the entry breakpoint callback. Resolves the load addresses
/// of all dependent modules.
ModuleSP
-DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr)
+DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
Target &target = m_process->GetTarget();
ModuleList &modules = target.GetImages();
@@ -602,12 +608,12 @@ DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_
// check if module is currently loaded
if ((module_sp = modules.FindFirstModule (module_spec)))
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, true);
}
// try to load this module from disk
else if ((module_sp = target.GetSharedModule(module_spec)))
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, true);
}
return module_sp;
diff --git a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
index aafa385c0fc..29abb20a4fb 100644
--- a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
+++ b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
@@ -124,7 +124,8 @@ protected:
void
UpdateLoadedSections(lldb::ModuleSP module,
lldb::addr_t link_map_addr,
- lldb::addr_t base_addr);
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset) override;
/// Removes the loaded sections from the target in @p module.
///
@@ -135,7 +136,10 @@ protected:
/// Locates or creates a module given by @p file and updates/loads the
/// resulting module at the virtual base address @p base_addr.
lldb::ModuleSP
- LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr);
+ LoadModuleAtAddress(const lldb_private::FileSpec &file,
+ lldb::addr_t link_map_addr,
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset) override;
/// Callback routine invoked when we hit the breakpoint on process entry.
///
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 8724fc039cb..37cc4a58721 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -165,7 +165,7 @@ DynamicLoaderPOSIXDYLD::DidAttach()
m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID,
executable_sp->GetFileSpec().GetPath().c_str ());
- UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset);
+ UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, true);
// When attaching to a target, there are two possible states:
// (1) We already crossed the entry point and therefore the rendezvous
@@ -223,7 +223,7 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
{
ModuleList module_list;
module_list.Append(executable);
- UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);
if (log)
log->Printf ("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", __FUNCTION__);
@@ -252,11 +252,13 @@ DynamicLoaderPOSIXDYLD::CanLoadImage()
}
void
-DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
+DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
m_loaded_modules[module] = link_map_addr;
-
- UpdateLoadedSectionsCommon(module, base_addr);
+ UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
}
void
@@ -414,7 +416,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
E = m_rendezvous.loaded_end();
for (I = m_rendezvous.loaded_begin(); I != E; ++I)
{
- ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
loaded_modules.AppendIfNeeded(module_sp);
@@ -432,8 +434,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
{
ModuleSpec module_spec{I->file_spec};
- ModuleSP module_sp =
- loaded_modules.FindFirstModule (module_spec);
+ ModuleSP module_sp = loaded_modules.FindFirstModule (module_spec);
if (module_sp.get())
{
@@ -520,10 +521,9 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
ModuleSP executable = GetTargetExecutable();
m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
-
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
{
- ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
module_list.Append(module_sp);
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index 68d3059cb4b..c9445726b0d 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -103,7 +103,7 @@ protected:
/// Enables a breakpoint on a function called by the runtime
/// linker each time a module is loaded or unloaded.
- void
+ virtual void
SetRendezvousBreakpoint();
/// Callback routine which updates the current list of loaded modules based
@@ -126,16 +126,17 @@ protected:
/// @param link_map_addr The virtual address of the link map for the @p module.
///
/// @param base_addr The virtual base address @p module is loaded at.
- virtual void
+ void
UpdateLoadedSections(lldb::ModuleSP module,
lldb::addr_t link_map_addr,
- lldb::addr_t base_addr);
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset) override;
/// Removes the loaded sections from the target in @p module.
///
/// @param module The module to traverse.
- virtual void
- UnloadSections(const lldb::ModuleSP module);
+ void
+ UnloadSections(const lldb::ModuleSP module) override;
/// Resolves the entry point for the current inferior process and sets a
/// breakpoint at that address.
@@ -155,7 +156,7 @@ protected:
/// Helper for the entry breakpoint callback. Resolves the load addresses
/// of all dependent modules.
- void
+ virtual void
LoadAllCurrentModules();
/// Computes a value for m_load_offset returning the computed address on
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 6cfc23a30b9..c5930b48a86 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -847,40 +847,52 @@ ObjectFileELF::SetLoadAddress (Target &target,
SectionList *section_list = GetSectionList ();
if (section_list)
{
- if (value_is_offset)
+ if (!value_is_offset)
{
- const size_t num_sections = section_list->GetSize();
- size_t sect_idx = 0;
-
- for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
+ bool found_offset = false;
+ for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i)
{
- // Iterate through the object file sections to find all
- // of the sections that have SHF_ALLOC in their flag bits.
- SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
- // if (section_sp && !section_sp->IsThreadSpecific())
- if (section_sp && section_sp->Test(SHF_ALLOC))
- {
- lldb::addr_t load_addr = section_sp->GetFileAddress() + value;
-
- // On 32-bit systems the load address have to fit into 4 bytes. The rest of
- // the bytes are the overflow from the addition.
- if (GetAddressByteSize() == 4)
- load_addr &= 0xFFFFFFFF;
-
- if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr))
- ++num_loaded_sections;
- }
+ const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i);
+ if (header == nullptr)
+ continue;
+
+ if (header->p_type != PT_LOAD || header->p_offset != 0)
+ continue;
+
+ value = value - header->p_vaddr;
+ found_offset = true;
+ break;
}
- return num_loaded_sections > 0;
+ if (!found_offset)
+ return false;
}
- else
+
+ const size_t num_sections = section_list->GetSize();
+ size_t sect_idx = 0;
+
+ for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
{
- // Not sure how to slide an ELF file given the base address
- // of the ELF file in memory
+ // Iterate through the object file sections to find all
+ // of the sections that have SHF_ALLOC in their flag bits.
+ SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
+ // if (section_sp && !section_sp->IsThreadSpecific())
+ if (section_sp && section_sp->Test(SHF_ALLOC))
+ {
+ lldb::addr_t load_addr = section_sp->GetFileAddress() + value;
+
+ // On 32-bit systems the load address have to fit into 4 bytes. The rest of
+ // the bytes are the overflow from the addition.
+ if (GetAddressByteSize() == 4)
+ load_addr &= 0xFFFFFFFF;
+
+ if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr))
+ ++num_loaded_sections;
+ }
}
+ return num_loaded_sections > 0;
}
}
- return false; // If it changed
+ return false;
}
ByteOrder
OpenPOWER on IntegriCloud