diff options
author | Greg Clayton <gclayton@apple.com> | 2015-06-08 21:53:11 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2015-06-08 21:53:11 +0000 |
commit | 8b3357926d9017a8681525ab9034ae74296c2684 (patch) | |
tree | afb10bd34825b609530183dfabaa6a2f51731fec | |
parent | 6f083d89030e202080a1daee7b8d639f2043edb7 (diff) | |
download | lldb-8b3357926d9017a8681525ab9034ae74296c2684.tar.gz |
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>
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@239354 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp | 137 | ||||
-rw-r--r-- | source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h | 8 |
2 files changed, 92 insertions, 53 deletions
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 7c78246bb..c61f871cd 100644 --- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -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; } } diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h index c0d57a3f2..eb8c7073d 100644 --- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -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(); |