Fix [vdso] handling on Android (x86 and aarch64)
* Add in-memory object file handling to the core dynamic loader * Fix in memory object file handling in ObjectFileELF (previously only part of the file was loaded before parsing) * Fix load address setting in ObjectFileELF for 32-bit targets when the load bias is negative * Change hack in DYLDRendezvous.cpp to be more specific and not to interfere with object files with fixed load address Differential revision: http://reviews.llvm.org/D10800 llvm-svn: 241057
This commit is contained in:
parent
cd4994e925
commit
f256184693
|
@ -186,6 +186,24 @@ DynamicLoader::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, a
|
|||
{
|
||||
UpdateLoadedSections(module_sp, link_map_addr, base_addr);
|
||||
}
|
||||
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)))
|
||||
{
|
||||
UpdateLoadedSections(module_sp, link_map_addr, base_addr);
|
||||
target.GetImages().AppendIfNeeded(module_sp);
|
||||
}
|
||||
}
|
||||
|
||||
return module_sp;
|
||||
}
|
||||
|
|
|
@ -410,12 +410,14 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
|
|||
if (!(addr = ReadPointer(addr, &entry.prev)))
|
||||
return false;
|
||||
|
||||
entry.file_spec.SetFile(ReadStringFromMemory(entry.path_addr), false);
|
||||
std::string file_path = ReadStringFromMemory(entry.path_addr);
|
||||
entry.file_spec.SetFile(file_path, 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.
|
||||
// The issue observed for '/system/bin/linker' on Android L (5.0, 5.1)
|
||||
if (entry.base_addr == 0)
|
||||
// On Android L (5.0, 5.1) the load address of the "/system/bin/linker" isn't filled in
|
||||
// correctly. To get the correct load address we fetch the load address of the file from the
|
||||
// proc file system.
|
||||
if (arch.GetTriple().getEnvironment() == llvm::Triple::Android && entry.base_addr == 0 &&
|
||||
(file_path == "/system/bin/linker" || file_path == "/system/bin/linker64"))
|
||||
{
|
||||
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
|
||||
bool is_loaded = false;
|
||||
|
|
|
@ -807,10 +807,10 @@ ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
|
|||
}
|
||||
|
||||
ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
|
||||
DataBufferSP& data_sp,
|
||||
DataBufferSP& header_data_sp,
|
||||
const lldb::ProcessSP &process_sp,
|
||||
addr_t header_addr) :
|
||||
ObjectFile(module_sp, process_sp, LLDB_INVALID_ADDRESS, data_sp),
|
||||
ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
|
||||
m_header(),
|
||||
m_uuid(),
|
||||
m_gnu_debuglink_file(),
|
||||
|
@ -860,7 +860,14 @@ ObjectFileELF::SetLoadAddress (Target &target,
|
|||
// if (section_sp && !section_sp->IsThreadSpecific())
|
||||
if (section_sp && section_sp->Test(SHF_ALLOC))
|
||||
{
|
||||
if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + value))
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -933,7 +940,28 @@ bool
|
|||
ObjectFileELF::ParseHeader()
|
||||
{
|
||||
lldb::offset_t offset = 0;
|
||||
return m_header.Parse(m_data, &offset);
|
||||
if (!m_header.Parse(m_data, &offset))
|
||||
return false;
|
||||
|
||||
if (!IsInMemory())
|
||||
return true;
|
||||
|
||||
// For in memory object files m_data might not contain the full object file. Try to load it
|
||||
// until the end of the "Section header table" what is at the end of the ELF file.
|
||||
addr_t file_size = m_header.e_shoff + m_header.e_shnum * m_header.e_shentsize;
|
||||
if (m_data.GetByteSize() < file_size)
|
||||
{
|
||||
ProcessSP process_sp (m_process_wp.lock());
|
||||
if (!process_sp)
|
||||
return false;
|
||||
|
||||
DataBufferSP data_sp = ReadMemory(process_sp, m_memory_addr, file_size);
|
||||
if (!data_sp)
|
||||
return false;
|
||||
m_data.SetData(data_sp, 0, file_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -199,7 +199,7 @@ private:
|
|||
lldb::offset_t length);
|
||||
|
||||
ObjectFileELF (const lldb::ModuleSP &module_sp,
|
||||
lldb::DataBufferSP& data_sp,
|
||||
lldb::DataBufferSP& header_data_sp,
|
||||
const lldb::ProcessSP &process_sp,
|
||||
lldb::addr_t header_addr);
|
||||
|
||||
|
|
Loading…
Reference in New Issue