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:
Greg Clayton 2015-06-08 21:53:11 +00:00
parent 10511a493e
commit 0734737b65
2 changed files with 92 additions and 53 deletions

View File

@ -2283,7 +2283,15 @@ ObjectFileMachO::ParseSymtab ()
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 symoff_addr = linkedit_load_addr + symtab_load_command.symoff - 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
ObjectFileMachO::SetLoadAddress (Target &target,
lldb::addr_t value,
@ -5526,12 +5600,8 @@ ObjectFileMachO::SetLoadAddress (Target &target,
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();
const bool is_memory_image = (bool)m_process_wp.lock();
const Strata strata = GetStrata();
static ConstString g_linkedit_segname ("__LINKEDIT");
if (value_is_offset)
{
// "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())
{
// 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
// 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)
continue;
}
@ -5564,58 +5636,17 @@ ObjectFileMachO::SetLoadAddress (Target &target,
// "value" is the new base address of the mach_header, adjust each
// section accordingly
// First find the address of the mach header which is the first non-zero
// file sized section whose file offset is zero as this will be subtracted
// 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)
Section *mach_header_section = GetMachHeaderSection();
if (mach_header_section)
{
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));
if (section_sp &&
section_sp->GetFileSize() > 0 &&
section_sp->IsThreadSpecific() == false &&
module_sp.get() == section_sp->GetModule().get())
lldb::addr_t section_load_addr = CalculateSectionLoadAddressForMemoryImage(value, mach_header_section, section_sp.get());
if (section_load_addr != LLDB_INVALID_ADDRESS)
{
// Ignore __LINKEDIT and __DWARF segments
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))
if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_load_addr))
++num_loaded_sections;
}
}

View File

@ -212,6 +212,14 @@ protected:
lldb_private::UUID
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;
static const lldb_private::ConstString &GetSegmentNameTEXT();
static const lldb_private::ConstString &GetSegmentNameDATA();