summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2013-07-10 01:23:25 +0000
committerGreg Clayton <gclayton@apple.com>2013-07-10 01:23:25 +0000
commit3046e668301ec9df4ead087fdc906877b9dcbf82 (patch)
treeff149c296cddf3415649f2571282ef53b3554fbd /lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
parent8978a9dd0a42139809f56b6df47a0663f341918b (diff)
downloadbcm5719-llvm-3046e668301ec9df4ead087fdc906877b9dcbf82.tar.gz
bcm5719-llvm-3046e668301ec9df4ead087fdc906877b9dcbf82.zip
Cleanup on the unified section list changes. Main changes are:
- ObjectFile::GetSymtab() and ObjectFile::ClearSymtab() no longer takes any flags - Module coordinates with the object files and contain a unified section list so that object file and symbol file can share sections when they need to, yet contain their own sections. Other cleanups: - Fixed Symbol::GetByteSize() to not have the symbol table compute the byte sizes on the fly - Modified the ObjectFileMachO class to compute symbol sizes all at once efficiently - Modified the Symtab class to store a file address lookup table for more efficient lookups - Removed Section::Finalize() and SectionList::Finalize() as they did nothing - Improved performance of the detection of symbol files that have debug maps by excluding stripped files and core files, debug files, object files and stubs - Added the ability to tell if an ObjectFile has been stripped with ObjectFile::IsStripped() (used this for the above performance improvement) llvm-svn: 185990
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp349
1 files changed, 159 insertions, 190 deletions
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 1045332f0fe..fde83fb43c1 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -513,22 +513,6 @@ ObjectFileELF::GetDependentModules(FileSpecList &files)
return num_specs;
}
-user_id_t
-ObjectFileELF::GetSectionIndexByType(unsigned type)
-{
- if (!ParseSectionHeaders())
- return 0;
-
- for (SectionHeaderCollIter sh_pos = m_section_headers.begin();
- sh_pos != m_section_headers.end(); ++sh_pos)
- {
- if (sh_pos->sh_type == type)
- return SectionIndex(sh_pos);
- }
-
- return 0;
-}
-
Address
ObjectFileELF::GetImageInfoAddress()
{
@@ -539,28 +523,27 @@ ObjectFileELF::GetImageInfoAddress()
if (!section_list)
return Address();
- user_id_t dynsym_id = GetSectionIndexByType(SHT_DYNAMIC);
- if (!dynsym_id)
+ // Find the SHT_DYNAMIC (.dynamic) section.
+ SectionSP dynsym_section_sp (section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true));
+ if (!dynsym_section_sp)
return Address();
+ assert (dynsym_section_sp->GetObjectFile() == this);
+ user_id_t dynsym_id = dynsym_section_sp->GetID();
const ELFSectionHeaderInfo *dynsym_hdr = GetSectionHeaderByIndex(dynsym_id);
if (!dynsym_hdr)
return Address();
- SectionSP dynsym_section_sp (section_list->FindSectionByID(dynsym_id));
- if (dynsym_section_sp)
+ for (size_t i = 0; i < m_dynamic_symbols.size(); ++i)
{
- for (size_t i = 0; i < m_dynamic_symbols.size(); ++i)
- {
- ELFDynamic &symbol = m_dynamic_symbols[i];
+ ELFDynamic &symbol = m_dynamic_symbols[i];
- if (symbol.d_tag == DT_DEBUG)
- {
- // Compute the offset as the number of previous entries plus the
- // size of d_tag.
- addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
- return Address(dynsym_section_sp, offset);
- }
+ if (symbol.d_tag == DT_DEBUG)
+ {
+ // Compute the offset as the number of previous entries plus the
+ // size of d_tag.
+ addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
+ return Address(dynsym_section_sp, offset);
}
}
@@ -570,26 +553,19 @@ ObjectFileELF::GetImageInfoAddress()
lldb_private::Address
ObjectFileELF::GetEntryPointAddress ()
{
- SectionList *sections;
- addr_t offset;
-
if (m_entry_point_address.IsValid())
return m_entry_point_address;
if (!ParseHeader() || !IsExecutable())
return m_entry_point_address;
- sections = GetSectionList();
- offset = m_header.e_entry;
+ SectionList *section_list = GetSectionList();
+ addr_t offset = m_header.e_entry;
- if (!sections)
- {
+ if (!section_list)
m_entry_point_address.SetOffset(offset);
- return m_entry_point_address;
- }
-
- m_entry_point_address.ResolveAddressUsingFileSections(offset, sections);
-
+ else
+ m_entry_point_address.ResolveAddressUsingFileSections(offset, section_list);
return m_entry_point_address;
}
@@ -607,32 +583,22 @@ ObjectFileELF::ParseDependentModules()
if (!ParseSectionHeaders())
return 0;
- // Locate the dynamic table.
- user_id_t dynsym_id = 0;
- user_id_t dynstr_id = 0;
- for (SectionHeaderCollIter sh_pos = m_section_headers.begin();
- sh_pos != m_section_headers.end(); ++sh_pos)
- {
- if (sh_pos->sh_type == SHT_DYNAMIC)
- {
- dynsym_id = SectionIndex(sh_pos);
- dynstr_id = sh_pos->sh_link + 1; // Section ID's are 1 based.
- break;
- }
- }
-
- if (!(dynsym_id && dynstr_id))
- return 0;
-
SectionList *section_list = GetSectionList();
if (!section_list)
return 0;
- // Resolve and load the dynamic table entries and corresponding string
- // table.
- Section *dynsym = section_list->FindSectionByID(dynsym_id).get();
- Section *dynstr = section_list->FindSectionByID(dynstr_id).get();
- if (!(dynsym && dynstr))
+ // Find the SHT_DYNAMIC section.
+ Section *dynsym = section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true).get();
+ if (!dynsym)
+ return 0;
+ assert (dynsym->GetObjectFile() == this);
+
+ const ELFSectionHeaderInfo *header = GetSectionHeaderByIndex (dynsym->GetID());
+ if (!header)
+ return 0;
+ // sh_link: section header index of string table used by entries in the section.
+ Section *dynstr = section_list->FindSectionByID (header->sh_link + 1).get();
+ if (!dynstr)
return 0;
DataExtractor dynsym_data;
@@ -844,30 +810,6 @@ ObjectFileELF::ParseSectionHeaders()
return GetSectionHeaderInfo(m_section_headers, m_data, m_header, m_uuid, m_gnu_debuglink_file, m_gnu_debuglink_crc);
}
-lldb::user_id_t
-ObjectFileELF::GetSectionIndexByName(const char *name)
-{
- if (!ParseSectionHeaders())
- return 0;
-
- // Search the collection of section headers for one with a matching name.
- for (SectionHeaderCollIter I = m_section_headers.begin();
- I != m_section_headers.end(); ++I)
- {
- const char *sectionName = I->section_name.AsCString();
-
- if (!sectionName)
- return 0;
-
- if (strcmp(name, sectionName) != 0)
- continue;
-
- return SectionIndex(I);
- }
-
- return 0;
-}
-
const ObjectFileELF::ELFSectionHeaderInfo *
ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id)
{
@@ -880,14 +822,10 @@ ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id)
return NULL;
}
-
-SectionList *
-ObjectFileELF::GetSectionList()
+void
+ObjectFileELF::CreateSections(SectionList &unified_section_list)
{
- if (m_sections_ap.get())
- return m_sections_ap.get();
-
- if (ParseSectionHeaders())
+ if (!m_sections_ap.get() && ParseSectionHeaders())
{
m_sections_ap.reset(new SectionList());
@@ -982,40 +920,75 @@ ObjectFileELF::GetSectionList()
break;
}
- SectionSP section_sp(new Section(
- GetModule(), // Module to which this section belongs.
- this, // ObjectFile to which this section belongs and should read section data from.
- SectionIndex(I), // Section ID.
- name, // Section name.
- sect_type, // Section type.
- header.sh_addr, // VM address.
- vm_size, // VM size in bytes of this section.
- header.sh_offset, // Offset of this section in the file.
- file_size, // Size of the section as found in the file.
- header.sh_flags)); // Flags for this section.
+ SectionSP section_sp (new Section(GetModule(), // Module to which this section belongs.
+ this, // ObjectFile to which this section belongs and should read section data from.
+ SectionIndex(I), // Section ID.
+ name, // Section name.
+ sect_type, // Section type.
+ header.sh_addr, // VM address.
+ vm_size, // VM size in bytes of this section.
+ header.sh_offset, // Offset of this section in the file.
+ file_size, // Size of the section as found in the file.
+ header.sh_flags)); // Flags for this section.
if (is_thread_specific)
section_sp->SetIsThreadSpecific (is_thread_specific);
m_sections_ap->AddSection(section_sp);
}
-
- m_sections_ap->Finalize(); // Now that we're done adding sections, finalize to build fast-lookup caches
}
- return m_sections_ap.get();
+ if (m_sections_ap.get())
+ {
+ if (GetType() == eTypeDebugInfo)
+ {
+ static const SectionType g_sections[] =
+ {
+ eSectionTypeDWARFDebugAranges,
+ eSectionTypeDWARFDebugInfo,
+ eSectionTypeDWARFDebugAbbrev,
+ eSectionTypeDWARFDebugFrame,
+ eSectionTypeDWARFDebugLine,
+ eSectionTypeDWARFDebugStr,
+ eSectionTypeDWARFDebugLoc,
+ eSectionTypeDWARFDebugMacInfo,
+ eSectionTypeDWARFDebugPubNames,
+ eSectionTypeDWARFDebugPubTypes,
+ eSectionTypeDWARFDebugRanges,
+ eSectionTypeELFSymbolTable,
+ };
+ SectionList *elf_section_list = m_sections_ap.get();
+ for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); ++idx)
+ {
+ SectionType section_type = g_sections[idx];
+ SectionSP section_sp (elf_section_list->FindSectionByType (section_type, true));
+ if (section_sp)
+ {
+ SectionSP module_section_sp (unified_section_list.FindSectionByType (section_type, true));
+ if (module_section_sp)
+ unified_section_list.ReplaceSection (module_section_sp->GetID(), section_sp);
+ else
+ unified_section_list.AddSection (section_sp);
+ }
+ }
+ }
+ else
+ {
+ unified_section_list = *m_sections_ap;
+ }
+ }
}
+// private
unsigned
-ObjectFileELF::ParseSymbols(Symtab *symtab,
- user_id_t start_id,
- SectionList *section_list,
- const ELFSectionHeaderInfo *symtab_shdr,
- const DataExtractor &symtab_data,
- const DataExtractor &strtab_data)
+ObjectFileELF::ParseSymbols (Symtab *symtab,
+ user_id_t start_id,
+ SectionList *section_list,
+ const size_t num_symbols,
+ const DataExtractor &symtab_data,
+ const DataExtractor &strtab_data)
{
ELFSymbol symbol;
lldb::offset_t offset = 0;
- const size_t num_symbols = symtab_data.GetByteSize() / symtab_shdr->sh_entsize;
static ConstString text_section_name(".text");
static ConstString init_section_name(".init");
@@ -1128,21 +1101,18 @@ ObjectFileELF::ParseSymbols(Symtab *symtab,
}
}
- // If the symbol section we've found has no data (SHT_NOBITS), then check the module
- // for the main object file and use the section there if it has data. This can happen
- // if we're parsing the debug file and the it has no .text section, for example.
+ // If the symbol section we've found has no data (SHT_NOBITS), then check the module section
+ // list. This can happen if we're parsing the debug file and it has no .text section, for example.
if (symbol_section_sp && (symbol_section_sp->GetFileSize() == 0))
{
ModuleSP module_sp(GetModule());
if (module_sp)
{
- ObjectFile *obj_file = module_sp->GetObjectFile();
- // Check if we've got a different object file than ourselves.
- if (obj_file && (obj_file != this))
+ SectionList *module_section_list = module_sp->GetSectionList();
+ if (module_section_list && module_section_list != section_list)
{
const ConstString &sect_name = symbol_section_sp->GetName();
- SectionList *obj_file_section_list = obj_file->GetSectionList();
- lldb::SectionSP section_sp (obj_file_section_list->FindSectionByName (sect_name));
+ lldb::SectionSP section_sp (module_section_list->FindSectionByName (sect_name));
if (section_sp && section_sp->GetFileSize())
{
symbol_section_sp = section_sp;
@@ -1178,32 +1148,46 @@ ObjectFileELF::ParseSymbols(Symtab *symtab,
}
unsigned
-ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id, user_id_t symtab_id)
+ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id, lldb_private::Section *symtab)
{
- // Parse in the section list if needed.
- SectionList *section_list = GetSectionList();
+ if (symtab->GetObjectFile() != this)
+ {
+ // If the symbol table section is owned by a different object file, have it do the
+ // parsing.
+ ObjectFileELF *obj_file_elf = static_cast<ObjectFileELF *>(symtab->GetObjectFile());
+ return obj_file_elf->ParseSymbolTable (symbol_table, start_id, symtab);
+ }
+
+ // Get section list for this object file.
+ SectionList *section_list = m_sections_ap.get();
if (!section_list)
return 0;
- const ELFSectionHeaderInfo *symtab_hdr = &m_section_headers[symtab_id - 1];
+ user_id_t symtab_id = symtab->GetID();
+ const ELFSectionHeaderInfo *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
assert(symtab_hdr->sh_type == SHT_SYMTAB ||
symtab_hdr->sh_type == SHT_DYNSYM);
+ // sh_link: section header index of associated string table.
// Section ID's are ones based.
user_id_t strtab_id = symtab_hdr->sh_link + 1;
-
- Section *symtab = section_list->FindSectionByID(symtab_id).get();
Section *strtab = section_list->FindSectionByID(strtab_id).get();
+
unsigned num_symbols = 0;
if (symtab && strtab)
{
+ assert (symtab->GetObjectFile() == this);
+ assert (strtab->GetObjectFile() == this);
+
DataExtractor symtab_data;
DataExtractor strtab_data;
if (ReadSectionData(symtab, symtab_data) &&
ReadSectionData(strtab, strtab_data))
{
+ size_t num_symbols = symtab_data.GetByteSize() / symtab_hdr->sh_entsize;
+
num_symbols = ParseSymbols(symbol_table, start_id,
- section_list, symtab_hdr,
+ section_list, num_symbols,
symtab_data, strtab_data);
}
}
@@ -1217,17 +1201,15 @@ ObjectFileELF::ParseDynamicSymbols()
if (m_dynamic_symbols.size())
return m_dynamic_symbols.size();
- user_id_t dyn_id = GetSectionIndexByType(SHT_DYNAMIC);
- if (!dyn_id)
- return 0;
-
SectionList *section_list = GetSectionList();
if (!section_list)
return 0;
- Section *dynsym = section_list->FindSectionByID(dyn_id).get();
+ // Find the SHT_DYNAMIC section.
+ Section *dynsym = section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true).get();
if (!dynsym)
return 0;
+ assert (dynsym->GetObjectFile() == this);
ELFDynamic symbol;
DataExtractor dynsym_data;
@@ -1360,7 +1342,7 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
{
assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);
- // The link field points to the associated symbol table. The info field
+ // The link field points to the associated symbol table. The info field
// points to the section holding the plt.
user_id_t symtab_id = rel_hdr->sh_link;
user_id_t plt_id = rel_hdr->sh_info;
@@ -1380,7 +1362,7 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
if (!sym_hdr)
return 0;
- SectionList *section_list = GetSectionList();
+ SectionList *section_list = m_sections_ap.get();
if (!section_list)
return 0;
@@ -1396,6 +1378,7 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
if (!symtab)
return 0;
+ // sh_link points to associated string table.
Section *strtab = section_list->FindSectionByID(sym_hdr->sh_link + 1).get();
if (!strtab)
return 0;
@@ -1430,82 +1413,68 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
}
Symtab *
-ObjectFileELF::GetSymtab(uint32_t flags)
+ObjectFileELF::GetSymtab()
{
ModuleSP module_sp(GetModule());
- if (module_sp)
- {
- lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (!module_sp)
+ return NULL;
- bool from_unified_section_list = !!(flags & eSymtabFromUnifiedSectionList);
- SectionList *section_list = from_unified_section_list ? module_sp->GetUnifiedSectionList() : GetSectionList();
+ // We always want to use the main object file so we (hopefully) only have one cached copy
+ // of our symtab, dynamic sections, etc.
+ ObjectFile *module_obj_file = module_sp->GetObjectFile();
+ if (module_obj_file && module_obj_file != this)
+ return module_obj_file->GetSymtab();
+
+ if (m_symtab_ap.get() == NULL)
+ {
+ SectionList *section_list = GetSectionList();
if (!section_list)
return NULL;
- // If we're doing the unified section list and it has been modified, then clear our
- // cache and reload the symbols. If needed, we could check on only the sections that
- // we use to create the symbol table...
- std::unique_ptr<lldb_private::Symtab> &symtab_ap = from_unified_section_list ? m_symtab_unified_ap : m_symtab_ap;
- if (from_unified_section_list && (m_symtab_unified_revisionid != section_list->GetRevisionID()))
- {
- symtab_ap.reset();
- m_symtab_unified_revisionid = section_list->GetRevisionID();
- }
- else if (symtab_ap.get())
- {
- return symtab_ap.get();
- }
+ uint64_t symbol_id = 0;
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
- Symtab *symbol_table = new Symtab(this);
- symtab_ap.reset(symbol_table);
+ m_symtab_ap.reset(new Symtab(this));
// Sharable objects and dynamic executables usually have 2 distinct symbol
// tables, one named ".symtab", and the other ".dynsym". The dynsym is a smaller
// version of the symtab that only contains global symbols. The information found
// in the dynsym is therefore also found in the symtab, while the reverse is not
// necessarily true.
- Section *section_sym = section_list->FindSectionByType (eSectionTypeELFSymbolTable, true).get();
- if (!section_sym)
+ Section *symtab = section_list->FindSectionByType (eSectionTypeELFSymbolTable, true).get();
+ if (!symtab)
{
// The symtab section is non-allocable and can be stripped, so if it doesn't exist
// then use the dynsym section which should always be there.
- section_sym = section_list->FindSectionByType (eSectionTypeELFDynamicSymbols, true).get();
+ symtab = section_list->FindSectionByType (eSectionTypeELFDynamicSymbols, true).get();
}
+ if (symtab)
+ symbol_id += ParseSymbolTable (m_symtab_ap.get(), symbol_id, symtab);
- uint64_t symbol_id = 0;
- if (section_sym)
+ // Synthesize trampoline symbols to help navigate the PLT.
+ const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL);
+ if (symbol)
{
- user_id_t section_id = section_sym->GetID();
- ObjectFileELF *obj_file_elf = static_cast<ObjectFileELF *>(section_sym->GetObjectFile());
-
- symbol_id += obj_file_elf->ParseSymbolTable (symbol_table, symbol_id, section_id);
- }
-
- Section *section = section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true).get();
- if (section)
- {
- ObjectFileELF *obj_file_elf = static_cast<ObjectFileELF *>(section->GetObjectFile());
-
- // Synthesize trampoline symbols to help navigate the PLT.
- const ELFDynamic *symbol = obj_file_elf->FindDynamicSymbol(DT_JMPREL);
- if (symbol)
+ addr_t addr = symbol->d_ptr;
+ Section *reloc_section = section_list->FindSectionContainingFileAddress(addr).get();
+ if (reloc_section)
{
- addr_t addr = symbol->d_ptr;
- Section *reloc_section = section_list->FindSectionContainingFileAddress(addr).get();
- if (reloc_section)
- {
- user_id_t reloc_id = reloc_section->GetID();
- const ELFSectionHeaderInfo *reloc_header = obj_file_elf->GetSectionHeaderByIndex(reloc_id);
- assert(reloc_header);
+ user_id_t reloc_id = reloc_section->GetID();
+ const ELFSectionHeaderInfo *reloc_header = GetSectionHeaderByIndex(reloc_id);
+ assert(reloc_header);
- obj_file_elf->ParseTrampolineSymbols(symbol_table, symbol_id, reloc_header, reloc_id);
- }
+ ParseTrampolineSymbols (m_symtab_ap.get(), symbol_id, reloc_header, reloc_id);
}
}
-
- return symbol_table;
}
- return NULL;
+ return m_symtab_ap.get();
+}
+
+bool
+ObjectFileELF::IsStripped ()
+{
+ // TODO: determine this for ELF
+ return false;
}
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud