forked from OSchip/llvm-project
If we have a MachO file loaded from memory, make sure we can always get the symbol table even if we don't have the __LINKEDIT load address set in the target.
<rdar://problem/21208168> llvm-svn: 239354
This commit is contained in:
parent
10511a493e
commit
0734737b65
|
@ -2283,7 +2283,15 @@ ObjectFileMachO::ParseSymtab ()
|
||||||
|
|
||||||
if (linkedit_section_sp)
|
if (linkedit_section_sp)
|
||||||
{
|
{
|
||||||
const addr_t linkedit_load_addr = linkedit_section_sp->GetLoadBaseAddress(&target);
|
addr_t linkedit_load_addr = linkedit_section_sp->GetLoadBaseAddress(&target);
|
||||||
|
if (linkedit_load_addr == LLDB_INVALID_ADDRESS)
|
||||||
|
{
|
||||||
|
// We might be trying to access the symbol table before the __LINKEDIT's load
|
||||||
|
// address has been set in the target. We can't fail to read the symbol table,
|
||||||
|
// so calculate the right address manually
|
||||||
|
linkedit_load_addr = CalculateSectionLoadAddressForMemoryImage(m_memory_addr, GetMachHeaderSection(), linkedit_section_sp.get());
|
||||||
|
}
|
||||||
|
|
||||||
const addr_t linkedit_file_offset = linkedit_section_sp->GetFileOffset();
|
const addr_t linkedit_file_offset = linkedit_section_sp->GetFileOffset();
|
||||||
const addr_t symoff_addr = linkedit_load_addr + symtab_load_command.symoff - linkedit_file_offset;
|
const addr_t symoff_addr = linkedit_load_addr + symtab_load_command.symoff - linkedit_file_offset;
|
||||||
strtab_addr = linkedit_load_addr + symtab_load_command.stroff - linkedit_file_offset;
|
strtab_addr = linkedit_load_addr + symtab_load_command.stroff - linkedit_file_offset;
|
||||||
|
@ -5514,6 +5522,72 @@ ObjectFileMachO::GetPluginVersion()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Section *
|
||||||
|
ObjectFileMachO::GetMachHeaderSection()
|
||||||
|
{
|
||||||
|
// Find the first address of the mach header which is the first non-zero
|
||||||
|
// file sized section whose file offset is zero. This is the base file address
|
||||||
|
// of the mach-o file which can be subtracted from the vmaddr of the other
|
||||||
|
// segments found in memory and added to the load address
|
||||||
|
ModuleSP module_sp = GetModule();
|
||||||
|
if (module_sp)
|
||||||
|
{
|
||||||
|
SectionList *section_list = GetSectionList ();
|
||||||
|
if (section_list)
|
||||||
|
{
|
||||||
|
lldb::addr_t mach_base_file_addr = LLDB_INVALID_ADDRESS;
|
||||||
|
const size_t num_sections = section_list->GetSize();
|
||||||
|
|
||||||
|
for (size_t sect_idx = 0;
|
||||||
|
sect_idx < num_sections && mach_base_file_addr == LLDB_INVALID_ADDRESS;
|
||||||
|
++sect_idx)
|
||||||
|
{
|
||||||
|
Section *section = section_list->GetSectionAtIndex (sect_idx).get();
|
||||||
|
if (section &&
|
||||||
|
section->GetFileSize() > 0 &&
|
||||||
|
section->GetFileOffset() == 0 &&
|
||||||
|
section->IsThreadSpecific() == false &&
|
||||||
|
module_sp.get() == section->GetModule().get())
|
||||||
|
{
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
lldb::addr_t
|
||||||
|
ObjectFileMachO::CalculateSectionLoadAddressForMemoryImage(lldb::addr_t mach_header_load_address, const Section *mach_header_section, const Section *section)
|
||||||
|
{
|
||||||
|
ModuleSP module_sp = GetModule();
|
||||||
|
if (module_sp && mach_header_section && section && mach_header_load_address != LLDB_INVALID_ADDRESS)
|
||||||
|
{
|
||||||
|
lldb::addr_t mach_header_file_addr = mach_header_section->GetFileAddress();
|
||||||
|
if (mach_header_file_addr != LLDB_INVALID_ADDRESS)
|
||||||
|
{
|
||||||
|
if (section &&
|
||||||
|
section->GetFileSize() > 0 &&
|
||||||
|
section->IsThreadSpecific() == false &&
|
||||||
|
module_sp.get() == section->GetModule().get())
|
||||||
|
{
|
||||||
|
// Ignore __LINKEDIT and __DWARF segments
|
||||||
|
if (section->GetName() == GetSegmentNameLINKEDIT())
|
||||||
|
{
|
||||||
|
// Only map __LINKEDIT if we have an in memory image and this isn't
|
||||||
|
// a kernel binary like a kext or mach_kernel.
|
||||||
|
const bool is_memory_image = (bool)m_process_wp.lock();
|
||||||
|
const Strata strata = GetStrata();
|
||||||
|
if (is_memory_image == false || strata == eStrataKernel)
|
||||||
|
return LLDB_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
return section->GetFileAddress() - mach_header_file_addr + mach_header_load_address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LLDB_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ObjectFileMachO::SetLoadAddress (Target &target,
|
ObjectFileMachO::SetLoadAddress (Target &target,
|
||||||
lldb::addr_t value,
|
lldb::addr_t value,
|
||||||
|
@ -5526,12 +5600,8 @@ ObjectFileMachO::SetLoadAddress (Target &target,
|
||||||
SectionList *section_list = GetSectionList ();
|
SectionList *section_list = GetSectionList ();
|
||||||
if (section_list)
|
if (section_list)
|
||||||
{
|
{
|
||||||
lldb::addr_t mach_base_file_addr = LLDB_INVALID_ADDRESS;
|
|
||||||
const size_t num_sections = section_list->GetSize();
|
const size_t num_sections = section_list->GetSize();
|
||||||
|
|
||||||
const bool is_memory_image = (bool)m_process_wp.lock();
|
|
||||||
const Strata strata = GetStrata();
|
|
||||||
static ConstString g_linkedit_segname ("__LINKEDIT");
|
|
||||||
if (value_is_offset)
|
if (value_is_offset)
|
||||||
{
|
{
|
||||||
// "value" is an offset to apply to each top level segment
|
// "value" is an offset to apply to each top level segment
|
||||||
|
@ -5547,10 +5617,12 @@ ObjectFileMachO::SetLoadAddress (Target &target,
|
||||||
module_sp.get() == section_sp->GetModule().get())
|
module_sp.get() == section_sp->GetModule().get())
|
||||||
{
|
{
|
||||||
// Ignore __LINKEDIT and __DWARF segments
|
// Ignore __LINKEDIT and __DWARF segments
|
||||||
if (section_sp->GetName() == g_linkedit_segname)
|
if (section_sp->GetName() == GetSegmentNameLINKEDIT())
|
||||||
{
|
{
|
||||||
// Only map __LINKEDIT if we have an in memory image and this isn't
|
// Only map __LINKEDIT if we have an in memory image and this isn't
|
||||||
// a kernel binary like a kext or mach_kernel.
|
// a kernel binary like a kext or mach_kernel.
|
||||||
|
const bool is_memory_image = (bool)m_process_wp.lock();
|
||||||
|
const Strata strata = GetStrata();
|
||||||
if (is_memory_image == false || strata == eStrataKernel)
|
if (is_memory_image == false || strata == eStrataKernel)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -5564,58 +5636,17 @@ ObjectFileMachO::SetLoadAddress (Target &target,
|
||||||
// "value" is the new base address of the mach_header, adjust each
|
// "value" is the new base address of the mach_header, adjust each
|
||||||
// section accordingly
|
// section accordingly
|
||||||
|
|
||||||
// First find the address of the mach header which is the first non-zero
|
Section *mach_header_section = GetMachHeaderSection();
|
||||||
// file sized section whose file offset is zero as this will be subtracted
|
if (mach_header_section)
|
||||||
// from each other valid section's vmaddr and then get "base_addr" added to
|
|
||||||
// it when loading the module in the target
|
|
||||||
for (size_t sect_idx = 0;
|
|
||||||
sect_idx < num_sections && mach_base_file_addr == LLDB_INVALID_ADDRESS;
|
|
||||||
++sect_idx)
|
|
||||||
{
|
|
||||||
// Iterate through the object file sections to find all
|
|
||||||
// of the sections that size on disk (to avoid __PAGEZERO)
|
|
||||||
// and load them
|
|
||||||
Section *section = section_list->GetSectionAtIndex (sect_idx).get();
|
|
||||||
if (section &&
|
|
||||||
section->GetFileSize() > 0 &&
|
|
||||||
section->GetFileOffset() == 0 &&
|
|
||||||
section->IsThreadSpecific() == false &&
|
|
||||||
module_sp.get() == section->GetModule().get())
|
|
||||||
{
|
|
||||||
// Ignore __LINKEDIT and __DWARF segments
|
|
||||||
if (section->GetName() == g_linkedit_segname)
|
|
||||||
{
|
|
||||||
// Only map __LINKEDIT if we have an in memory image and this isn't
|
|
||||||
// a kernel binary like a kext or mach_kernel.
|
|
||||||
if (is_memory_image == false || strata == eStrataKernel)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
mach_base_file_addr = section->GetFileAddress();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mach_base_file_addr != LLDB_INVALID_ADDRESS)
|
|
||||||
{
|
{
|
||||||
for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx)
|
for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx)
|
||||||
{
|
{
|
||||||
// Iterate through the object file sections to find all
|
|
||||||
// of the sections that size on disk (to avoid __PAGEZERO)
|
|
||||||
// and load them
|
|
||||||
SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
|
SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
|
||||||
if (section_sp &&
|
|
||||||
section_sp->GetFileSize() > 0 &&
|
lldb::addr_t section_load_addr = CalculateSectionLoadAddressForMemoryImage(value, mach_header_section, section_sp.get());
|
||||||
section_sp->IsThreadSpecific() == false &&
|
if (section_load_addr != LLDB_INVALID_ADDRESS)
|
||||||
module_sp.get() == section_sp->GetModule().get())
|
|
||||||
{
|
{
|
||||||
// Ignore __LINKEDIT and __DWARF segments
|
if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_load_addr))
|
||||||
if (section_sp->GetName() == g_linkedit_segname)
|
|
||||||
{
|
|
||||||
// Only map __LINKEDIT if we have an in memory image and this isn't
|
|
||||||
// a kernel binary like a kext or mach_kernel.
|
|
||||||
if (is_memory_image == false || strata == eStrataKernel)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() - mach_base_file_addr + value))
|
|
||||||
++num_loaded_sections;
|
++num_loaded_sections;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,14 @@ protected:
|
||||||
lldb_private::UUID
|
lldb_private::UUID
|
||||||
GetLLDBSharedCacheUUID ();
|
GetLLDBSharedCacheUUID ();
|
||||||
|
|
||||||
|
lldb_private::Section *
|
||||||
|
GetMachHeaderSection();
|
||||||
|
|
||||||
|
lldb::addr_t
|
||||||
|
CalculateSectionLoadAddressForMemoryImage(lldb::addr_t mach_header_load_address,
|
||||||
|
const lldb_private::Section *mach_header_section,
|
||||||
|
const lldb_private::Section *section);
|
||||||
|
|
||||||
llvm::MachO::mach_header m_header;
|
llvm::MachO::mach_header m_header;
|
||||||
static const lldb_private::ConstString &GetSegmentNameTEXT();
|
static const lldb_private::ConstString &GetSegmentNameTEXT();
|
||||||
static const lldb_private::ConstString &GetSegmentNameDATA();
|
static const lldb_private::ConstString &GetSegmentNameDATA();
|
||||||
|
|
Loading…
Reference in New Issue