Revert "[NFC] Refactor symbol table parsing."

This reverts commit 951b107eed.

Buildbots were failing, there is a deadlock in /Users/gclayton/Documents/src/llvm/clean/llvm-project/lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s when ELF files try to relocate things.
This commit is contained in:
Greg Clayton
2021-11-17 18:07:28 -08:00
parent 92eaad2dd7
commit a68ccda203
20 changed files with 364 additions and 313 deletions

View File

@@ -322,26 +322,12 @@ public:
/// Gets the symbol table for the currently selected architecture (and
/// object for archives).
///
/// This function will manage when ParseSymtab(...) is called to actually do
/// the symbol table parsing in each plug-in. This function will take care of
/// taking all the necessary locks and finalizing the symbol table when the
/// symbol table does get parsed.
/// Symbol table parsing can be deferred by ObjectFile instances until this
/// accessor is called the first time.
///
/// \return
/// The symbol table for this object file.
Symtab *GetSymtab();
/// Parse the symbol table into the provides symbol table object.
///
/// Symbol table parsing will be done once when this function is called by
/// each object file plugin. All of the necessary locks will already be
/// acquired before this function is called and the symbol table object to
/// populate is supplied as an argument and doesn't need to be created by
/// each plug-in.
///
/// \param
/// The symbol table to populate.
virtual void ParseSymtab(Symtab &symtab) = 0;
virtual Symtab *GetSymtab() = 0;
/// Perform relocations on the section if necessary.
///

View File

@@ -119,13 +119,20 @@ public:
lldb::addr_t file_addr, std::function<bool(Symbol *)> const &callback);
void FindFunctionSymbols(ConstString name, uint32_t name_type_mask,
SymbolContextList &sc_list);
void CalculateSymbolSizes();
void SortSymbolIndexesByValue(std::vector<uint32_t> &indexes,
bool remove_duplicates) const;
static void DumpSymbolHeader(Stream *s);
void Finalize();
void Finalize() {
// Shrink to fit the symbols so we don't waste memory
if (m_symbols.capacity() > m_symbols.size()) {
collection new_symbols(m_symbols.begin(), m_symbols.end());
m_symbols.swap(new_symbols);
}
}
void AppendSymbolNamesToMap(const IndexCollection &indexes,
bool add_demangled, bool add_mangled,

View File

@@ -116,10 +116,9 @@ bool ObjectFileBreakpad::ParseHeader() {
return true;
}
void ObjectFileBreakpad::ParseSymtab(Symtab &symtab) {
// Nothing to do for breakpad files, all information is parsed as debug info
// which means "lldb_private::Function" objects are used, or symbols are added
// by the SymbolFileBreakpad::AddSymbols(...) function in the symbol file.
Symtab *ObjectFileBreakpad::GetSymtab() {
// TODO
return nullptr;
}
void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) {

View File

@@ -71,7 +71,7 @@ public:
return AddressClass::eInvalid;
}
void ParseSymtab(lldb_private::Symtab &symtab) override;
Symtab *GetSymtab() override;
bool IsStripped() override { return false; }

View File

@@ -2687,132 +2687,155 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr,
return 0;
}
void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
Symtab *ObjectFileELF::GetSymtab() {
ModuleSP module_sp(GetModule());
if (!module_sp)
return;
Progress progress(
llvm::formatv("Parsing symbol table for {0}",
m_file.GetFilename().AsCString("<Unknown>")));
ElapsedTime elapsed(module_sp->GetSymtabParseTime());
return nullptr;
// 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->ParseSymtab(lldb_symtab);
return module_obj_file->GetSymtab();
SectionList *section_list = module_sp->GetSectionList();
if (!section_list)
return;
if (m_symtab_up == nullptr) {
Progress progress(
llvm::formatv("Parsing symbol table for {0}",
m_file.GetFilename().AsCString("<Unknown>")));
ElapsedTime elapsed(module_sp->GetSymtabParseTime());
SectionList *section_list = module_sp->GetSectionList();
if (!section_list)
return nullptr;
uint64_t symbol_id = 0;
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
uint64_t symbol_id = 0;
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
// 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 *symtab =
section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get();
if (symtab)
symbol_id += ParseSymbolTable(&lldb_symtab, symbol_id, symtab);
// The symtab section is non-allocable and can be stripped, while the
// .dynsym section which should always be always be there. To support the
// minidebuginfo case we parse .dynsym when there's a .gnu_debuginfo
// section, nomatter if .symtab was already parsed or not. This is because
// minidebuginfo normally removes the .symtab symbols which have their
// matching .dynsym counterparts.
if (!symtab ||
GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) {
Section *dynsym =
section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true)
.get();
if (dynsym)
symbol_id += ParseSymbolTable(&lldb_symtab, symbol_id, dynsym);
}
// DT_JMPREL
// If present, this entry's d_ptr member holds the address of
// relocation
// entries associated solely with the procedure linkage table.
// Separating
// these relocation entries lets the dynamic linker ignore them during
// process initialization, if lazy binding is enabled. If this entry is
// present, the related entries of types DT_PLTRELSZ and DT_PLTREL must
// also be present.
const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL);
if (symbol) {
// Synthesize trampoline symbols to help navigate the PLT.
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 =
GetSectionHeaderByIndex(reloc_id);
if (reloc_header)
ParseTrampolineSymbols(&lldb_symtab, symbol_id, reloc_header, reloc_id);
// 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 *symtab =
section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get();
if (symtab) {
m_symtab_up = std::make_unique<Symtab>(symtab->GetObjectFile());
symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, symtab);
}
}
if (DWARFCallFrameInfo *eh_frame =
GetModule()->GetUnwindTable().GetEHFrameInfo()) {
ParseUnwindSymbols(&lldb_symtab, eh_frame);
}
// In the event that there's no symbol entry for the entry point we'll
// artificially create one. We delegate to the symtab object the figuring
// out of the proper size, this will usually make it span til the next
// symbol it finds in the section. This means that if there are missing
// symbols the entry point might span beyond its function definition.
// We're fine with this as it doesn't make it worse than not having a
// symbol entry at all.
if (CalculateType() == eTypeExecutable) {
ArchSpec arch = GetArchitecture();
auto entry_point_addr = GetEntryPointAddress();
bool is_valid_entry_point =
entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset();
addr_t entry_point_file_addr = entry_point_addr.GetFileAddress();
if (is_valid_entry_point && !lldb_symtab.FindSymbolContainingFileAddress(
entry_point_file_addr)) {
uint64_t symbol_id = lldb_symtab.GetNumSymbols();
// Don't set the name for any synthetic symbols, the Symbol
// object will generate one if needed when the name is accessed
// via accessors.
SectionSP section_sp = entry_point_addr.GetSection();
Symbol symbol(
/*symID=*/symbol_id,
/*name=*/llvm::StringRef(), // Name will be auto generated.
/*type=*/eSymbolTypeCode,
/*external=*/true,
/*is_debug=*/false,
/*is_trampoline=*/false,
/*is_artificial=*/true,
/*section_sp=*/section_sp,
/*offset=*/0,
/*size=*/0, // FDE can span multiple symbols so don't use its size.
/*size_is_valid=*/false,
/*contains_linker_annotations=*/false,
/*flags=*/0);
// When the entry point is arm thumb we need to explicitly set its
// class address to reflect that. This is important because expression
// evaluation relies on correctly setting a breakpoint at this
// address.
if (arch.GetMachine() == llvm::Triple::arm &&
(entry_point_file_addr & 1)) {
symbol.GetAddressRef().SetOffset(entry_point_addr.GetOffset() ^ 1);
m_address_class_map[entry_point_file_addr ^ 1] =
AddressClass::eCodeAlternateISA;
} else {
m_address_class_map[entry_point_file_addr] = AddressClass::eCode;
// The symtab section is non-allocable and can be stripped, while the
// .dynsym section which should always be always be there. To support the
// minidebuginfo case we parse .dynsym when there's a .gnu_debuginfo
// section, nomatter if .symtab was already parsed or not. This is because
// minidebuginfo normally removes the .symtab symbols which have their
// matching .dynsym counterparts.
if (!symtab ||
GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) {
Section *dynsym =
section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true)
.get();
if (dynsym) {
if (!m_symtab_up)
m_symtab_up = std::make_unique<Symtab>(dynsym->GetObjectFile());
symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, dynsym);
}
lldb_symtab.AddSymbol(symbol);
}
// DT_JMPREL
// If present, this entry's d_ptr member holds the address of
// relocation
// entries associated solely with the procedure linkage table.
// Separating
// these relocation entries lets the dynamic linker ignore them during
// process initialization, if lazy binding is enabled. If this entry is
// present, the related entries of types DT_PLTRELSZ and DT_PLTREL must
// also be present.
const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL);
if (symbol) {
// Synthesize trampoline symbols to help navigate the PLT.
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 =
GetSectionHeaderByIndex(reloc_id);
if (reloc_header) {
if (m_symtab_up == nullptr)
m_symtab_up =
std::make_unique<Symtab>(reloc_section->GetObjectFile());
ParseTrampolineSymbols(m_symtab_up.get(), symbol_id, reloc_header,
reloc_id);
}
}
}
if (DWARFCallFrameInfo *eh_frame =
GetModule()->GetUnwindTable().GetEHFrameInfo()) {
if (m_symtab_up == nullptr)
m_symtab_up = std::make_unique<Symtab>(this);
ParseUnwindSymbols(m_symtab_up.get(), eh_frame);
}
// If we still don't have any symtab then create an empty instance to avoid
// do the section lookup next time.
if (m_symtab_up == nullptr)
m_symtab_up = std::make_unique<Symtab>(this);
// In the event that there's no symbol entry for the entry point we'll
// artificially create one. We delegate to the symtab object the figuring
// out of the proper size, this will usually make it span til the next
// symbol it finds in the section. This means that if there are missing
// symbols the entry point might span beyond its function definition.
// We're fine with this as it doesn't make it worse than not having a
// symbol entry at all.
if (CalculateType() == eTypeExecutable) {
ArchSpec arch = GetArchitecture();
auto entry_point_addr = GetEntryPointAddress();
bool is_valid_entry_point =
entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset();
addr_t entry_point_file_addr = entry_point_addr.GetFileAddress();
if (is_valid_entry_point && !m_symtab_up->FindSymbolContainingFileAddress(
entry_point_file_addr)) {
uint64_t symbol_id = m_symtab_up->GetNumSymbols();
// Don't set the name for any synthetic symbols, the Symbol
// object will generate one if needed when the name is accessed
// via accessors.
SectionSP section_sp = entry_point_addr.GetSection();
Symbol symbol(
/*symID=*/symbol_id,
/*name=*/llvm::StringRef(), // Name will be auto generated.
/*type=*/eSymbolTypeCode,
/*external=*/true,
/*is_debug=*/false,
/*is_trampoline=*/false,
/*is_artificial=*/true,
/*section_sp=*/section_sp,
/*offset=*/0,
/*size=*/0, // FDE can span multiple symbols so don't use its size.
/*size_is_valid=*/false,
/*contains_linker_annotations=*/false,
/*flags=*/0);
// When the entry point is arm thumb we need to explicitly set its
// class address to reflect that. This is important because expression
// evaluation relies on correctly setting a breakpoint at this
// address.
if (arch.GetMachine() == llvm::Triple::arm &&
(entry_point_file_addr & 1)) {
symbol.GetAddressRef().SetOffset(entry_point_addr.GetOffset() ^ 1);
m_address_class_map[entry_point_file_addr ^ 1] =
AddressClass::eCodeAlternateISA;
} else {
m_address_class_map[entry_point_file_addr] = AddressClass::eCode;
}
m_symtab_up->AddSymbol(symbol);
}
}
m_symtab_up->CalculateSymbolSizes();
}
return m_symtab_up.get();
}
void ObjectFileELF::RelocateSection(lldb_private::Section *section)

View File

@@ -110,7 +110,7 @@ public:
lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
void ParseSymtab(lldb_private::Symtab &symtab) override;
lldb_private::Symtab *GetSymtab() override;
bool IsStripped() override;
@@ -123,7 +123,7 @@ public:
lldb_private::UUID GetUUID() override;
/// Return the contents of the .gnu_debuglink section, if the object file
/// contains it.
/// contains it.
llvm::Optional<lldb_private::FileSpec> GetDebugLink();
uint32_t GetDependentModules(lldb_private::FileSpecList &files) override;
@@ -384,7 +384,7 @@ private:
lldb_private::UUID &uuid);
bool AnySegmentHasPhysicalAddress();
/// Takes the .gnu_debugdata and returns the decompressed object file that is
/// stored within that section.
///

View File

@@ -106,10 +106,23 @@ uint32_t ObjectFileJIT::GetAddressByteSize() const {
return m_data.GetAddressByteSize();
}
void ObjectFileJIT::ParseSymtab(Symtab &symtab) {
ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
if (delegate_sp)
delegate_sp->PopulateSymtab(this, symtab);
Symtab *ObjectFileJIT::GetSymtab() {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_symtab_up == nullptr) {
ElapsedTime elapsed(module_sp->GetSymtabParseTime());
m_symtab_up = std::make_unique<Symtab>(this);
std::lock_guard<std::recursive_mutex> symtab_guard(
m_symtab_up->GetMutex());
ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
if (delegate_sp)
delegate_sp->PopulateSymtab(this, *m_symtab_up);
// TODO: get symbols from delegate
m_symtab_up->Finalize();
}
}
return m_symtab_up.get();
}
bool ObjectFileJIT::IsStripped() {

View File

@@ -67,7 +67,7 @@ public:
uint32_t GetAddressByteSize() const override;
void ParseSymtab(lldb_private::Symtab &symtab) override;
lldb_private::Symtab *GetSymtab() override;
bool IsStripped() override;

View File

@@ -1311,6 +1311,22 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
return AddressClass::eUnknown;
}
Symtab *ObjectFileMachO::GetSymtab() {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_symtab_up == nullptr) {
ElapsedTime elapsed(module_sp->GetSymtabParseTime());
m_symtab_up = std::make_unique<Symtab>(this);
std::lock_guard<std::recursive_mutex> symtab_guard(
m_symtab_up->GetMutex());
ParseSymtab();
m_symtab_up->Finalize();
}
}
return m_symtab_up.get();
}
bool ObjectFileMachO::IsStripped() {
if (m_dysymtab.cmd == 0) {
ModuleSP module_sp(GetModule());
@@ -2217,12 +2233,12 @@ ParseNList(DataExtractor &nlist_data, lldb::offset_t &nlist_data_offset,
enum { DebugSymbols = true, NonDebugSymbols = false };
void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
size_t ObjectFileMachO::ParseSymtab() {
LLDB_SCOPED_TIMERF("ObjectFileMachO::ParseSymtab () module = %s",
m_file.GetFilename().AsCString(""));
ModuleSP module_sp(GetModule());
if (!module_sp)
return;
return 0;
Progress progress(llvm::formatv("Parsing symbol table for {0}",
m_file.GetFilename().AsCString("<Unknown>")));
@@ -2272,7 +2288,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// Read in the rest of the symtab load command
if (m_data.GetU32(&offset, &symtab_load_command.symoff, 4) ==
nullptr) // fill in symoff, nsyms, stroff, strsize fields
return;
return 0;
break;
case LC_DYLD_INFO:
@@ -2331,11 +2347,12 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
}
if (!symtab_load_command.cmd)
return;
return 0;
Symtab *symtab = m_symtab_up.get();
SectionList *section_list = GetSectionList();
if (section_list == nullptr)
return;
return 0;
const uint32_t addr_byte_size = m_data.GetAddressByteSize();
const ByteOrder byte_order = m_data.GetByteOrder();
@@ -2472,7 +2489,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// We shouldn't have exports data from both the LC_DYLD_INFO command
// AND the LC_DYLD_EXPORTS_TRIE command in the same binary:
lldbassert(!((dyld_info.export_size > 0)
lldbassert(!((dyld_info.export_size > 0)
&& (exports_trie_load_command.datasize > 0)));
if (dyld_info.export_size > 0) {
dyld_trie_data.SetData(m_data, dyld_info.export_off,
@@ -2864,10 +2881,10 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// The normal nlist code cannot correctly size the Symbols
// array, we need to allocate it here.
sym = symtab.Resize(
sym = symtab->Resize(
symtab_load_command.nsyms + m_dysymtab.nindirectsyms +
unmapped_local_symbols_found - m_dysymtab.nlocalsym);
num_syms = symtab.GetNumSymbols();
num_syms = symtab->GetNumSymbols();
nlist_data_offset =
local_symbols_info.nlistOffset +
@@ -2999,7 +3016,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// original
// STAB entry so we don't have
// to hunt for it later
symtab.SymbolAtIndex(N_FUN_indexes.back())
symtab->SymbolAtIndex(N_FUN_indexes.back())
->SetByteSize(nlist.n_value);
N_FUN_indexes.pop_back();
// We don't really need the end function STAB as
@@ -3079,7 +3096,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// index of this N_SO so that we can always skip
// the entire N_SO if we need to navigate more
// quickly at the source level when parsing STABS
symbol_ptr = symtab.SymbolAtIndex(N_SO_index);
symbol_ptr = symtab->SymbolAtIndex(N_SO_index);
symbol_ptr->SetByteSize(sym_idx);
symbol_ptr->SetSizeIsSibling(true);
}
@@ -3186,7 +3203,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// quickly at the source level when parsing STABS
if (!N_INCL_indexes.empty()) {
symbol_ptr =
symtab.SymbolAtIndex(N_INCL_indexes.back());
symtab->SymbolAtIndex(N_INCL_indexes.back());
symbol_ptr->SetByteSize(sym_idx + 1);
symbol_ptr->SetSizeIsSibling(true);
N_INCL_indexes.pop_back();
@@ -3251,7 +3268,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
nlist.n_value);
if (!N_BRAC_indexes.empty()) {
symbol_ptr =
symtab.SymbolAtIndex(N_BRAC_indexes.back());
symtab->SymbolAtIndex(N_BRAC_indexes.back());
symbol_ptr->SetByteSize(sym_idx + 1);
symbol_ptr->SetSizeIsSibling(true);
N_BRAC_indexes.pop_back();
@@ -3289,7 +3306,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// parsing STABS
if (!N_COMM_indexes.empty()) {
symbol_ptr =
symtab.SymbolAtIndex(N_COMM_indexes.back());
symtab->SymbolAtIndex(N_COMM_indexes.back());
symbol_ptr->SetByteSize(sym_idx + 1);
symbol_ptr->SetSizeIsSibling(true);
N_COMM_indexes.pop_back();
@@ -3789,8 +3806,8 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// symbols, create it now.
if (sym == nullptr) {
sym =
symtab.Resize(symtab_load_command.nsyms + m_dysymtab.nindirectsyms);
num_syms = symtab.GetNumSymbols();
symtab->Resize(symtab_load_command.nsyms + m_dysymtab.nindirectsyms);
num_syms = symtab->GetNumSymbols();
}
if (unmapped_local_symbols_found) {
@@ -3924,7 +3941,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
if (!N_FUN_indexes.empty()) {
// Copy the size of the function into the original STAB entry
// so we don't have to hunt for it later
symtab.SymbolAtIndex(N_FUN_indexes.back())
symtab->SymbolAtIndex(N_FUN_indexes.back())
->SetByteSize(nlist.n_value);
N_FUN_indexes.pop_back();
// We don't really need the end function STAB as it contains
@@ -3998,7 +4015,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// N_SO so that we can always skip the entire N_SO if we need
// to navigate more quickly at the source level when parsing
// STABS
symbol_ptr = symtab.SymbolAtIndex(N_SO_index);
symbol_ptr = symtab->SymbolAtIndex(N_SO_index);
symbol_ptr->SetByteSize(sym_idx);
symbol_ptr->SetSizeIsSibling(true);
}
@@ -4092,7 +4109,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// N_EINCL so that we can always skip the entire symbol if we need
// to navigate more quickly at the source level when parsing STABS
if (!N_INCL_indexes.empty()) {
symbol_ptr = symtab.SymbolAtIndex(N_INCL_indexes.back());
symbol_ptr = symtab->SymbolAtIndex(N_INCL_indexes.back());
symbol_ptr->SetByteSize(sym_idx + 1);
symbol_ptr->SetSizeIsSibling(true);
N_INCL_indexes.pop_back();
@@ -4151,7 +4168,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// quickly at the source level when parsing STABS
symbol_section = section_info.GetSection(nlist.n_sect, nlist.n_value);
if (!N_BRAC_indexes.empty()) {
symbol_ptr = symtab.SymbolAtIndex(N_BRAC_indexes.back());
symbol_ptr = symtab->SymbolAtIndex(N_BRAC_indexes.back());
symbol_ptr->SetByteSize(sym_idx + 1);
symbol_ptr->SetSizeIsSibling(true);
N_BRAC_indexes.pop_back();
@@ -4185,7 +4202,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// we need to navigate more quickly at the source level when
// parsing STABS
if (!N_COMM_indexes.empty()) {
symbol_ptr = symtab.SymbolAtIndex(N_COMM_indexes.back());
symbol_ptr = symtab->SymbolAtIndex(N_COMM_indexes.back());
symbol_ptr->SetByteSize(sym_idx + 1);
symbol_ptr->SetSizeIsSibling(true);
N_COMM_indexes.pop_back();
@@ -4641,7 +4658,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
if (num_syms < sym_idx + trie_symbol_table_augment_count) {
num_syms = sym_idx + trie_symbol_table_augment_count;
sym = symtab.Resize(num_syms);
sym = symtab->Resize(num_syms);
}
uint32_t synthetic_sym_id = symtab_load_command.nsyms;
@@ -4690,7 +4707,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
if (num_synthetic_function_symbols > 0) {
if (num_syms < sym_idx + num_synthetic_function_symbols) {
num_syms = sym_idx + num_synthetic_function_symbols;
sym = symtab.Resize(num_syms);
sym = symtab->Resize(num_syms);
}
for (i = 0; i < function_starts_count; ++i) {
const FunctionStarts::Entry *func_start_entry =
@@ -4745,7 +4762,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// symbols.
if (sym_idx < num_syms) {
num_syms = sym_idx;
sym = symtab.Resize(num_syms);
sym = symtab->Resize(num_syms);
}
// Now synthesize indirect symbols
@@ -4790,11 +4807,11 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
if (index_pos != end_index_pos) {
// We have a remapping from the original nlist index to a
// current symbol index, so just look this up by index
stub_symbol = symtab.SymbolAtIndex(index_pos->second);
stub_symbol = symtab->SymbolAtIndex(index_pos->second);
} else {
// We need to lookup a symbol using the original nlist symbol
// index since this index is coming from the S_SYMBOL_STUBS
stub_symbol = symtab.FindSymbolByID(stub_sym_id);
stub_symbol = symtab->FindSymbolByID(stub_sym_id);
}
if (stub_symbol) {
@@ -4817,7 +4834,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
// Make a synthetic symbol to describe the trampoline stub
Mangled stub_symbol_mangled_name(stub_symbol->GetMangled());
if (sym_idx >= num_syms) {
sym = symtab.Resize(++num_syms);
sym = symtab->Resize(++num_syms);
stub_symbol = nullptr; // this pointer no longer valid
}
sym[sym_idx].SetID(synthetic_sym_id++);
@@ -4856,7 +4873,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
indirect_symbol_names.end()) {
// Make a synthetic symbol to describe re-exported symbol.
if (sym_idx >= num_syms)
sym = symtab.Resize(++num_syms);
sym = symtab->Resize(++num_syms);
sym[sym_idx].SetID(synthetic_sym_id++);
sym[sym_idx].GetMangled() = Mangled(e.entry.name);
sym[sym_idx].SetType(eSymbolTypeReExported);
@@ -4871,6 +4888,18 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
}
}
}
// StreamFile s(stdout, false);
// s.Printf ("Symbol table before CalculateSymbolSizes():\n");
// symtab->Dump(&s, NULL, eSortOrderNone);
// Set symbol byte sizes correctly since mach-o nlist entries don't have
// sizes
symtab->CalculateSymbolSizes();
// s.Printf ("Symbol table after CalculateSymbolSizes():\n");
// symtab->Dump(&s, NULL, eSortOrderNone);
return symtab->GetNumSymbols();
}
void ObjectFileMachO::Dump(Stream *s) {

View File

@@ -92,7 +92,7 @@ public:
lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
void ParseSymtab(lldb_private::Symtab &symtab) override;
lldb_private::Symtab *GetSymtab() override;
bool IsStripped() override;

View File

@@ -68,7 +68,7 @@ public:
bool IsExecutable() const override { return false; }
void ParseSymtab(lldb_private::Symtab &symtab) override {}
Symtab *GetSymtab() override { return nullptr; }
bool IsStripped() override { return false; }

View File

@@ -589,125 +589,139 @@ llvm::StringRef ObjectFilePECOFF::GetSectionName(const section_header_t &sect) {
return hdr_name;
}
void ObjectFilePECOFF::ParseSymtab(Symtab &symtab) {
SectionList *sect_list = GetSectionList();
const uint32_t num_syms = m_coff_header.nsyms;
if (m_file && num_syms > 0 && m_coff_header.symoff > 0) {
const uint32_t symbol_size = 18;
const size_t symbol_data_size = num_syms * symbol_size;
// Include the 4-byte string table size at the end of the symbols
DataExtractor symtab_data =
ReadImageData(m_coff_header.symoff, symbol_data_size + 4);
lldb::offset_t offset = symbol_data_size;
const uint32_t strtab_size = symtab_data.GetU32(&offset);
if (strtab_size > 0) {
DataExtractor strtab_data = ReadImageData(
m_coff_header.symoff + symbol_data_size, strtab_size);
// GetNListSymtab
Symtab *ObjectFilePECOFF::GetSymtab() {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_symtab_up == nullptr) {
ElapsedTime elapsed(module_sp->GetSymtabParseTime());
SectionList *sect_list = GetSectionList();
m_symtab_up = std::make_unique<Symtab>(this);
std::lock_guard<std::recursive_mutex> guard(m_symtab_up->GetMutex());
offset = 0;
std::string symbol_name;
Symbol *symbols = symtab.Resize(num_syms);
for (uint32_t i = 0; i < num_syms; ++i) {
coff_symbol_t symbol;
const uint32_t symbol_offset = offset;
const char *symbol_name_cstr = nullptr;
// If the first 4 bytes of the symbol string are zero, then they
// are followed by a 4-byte string table offset. Else these
// 8 bytes contain the symbol name
if (symtab_data.GetU32(&offset) == 0) {
// Long string that doesn't fit into the symbol table name, so
// now we must read the 4 byte string table offset
uint32_t strtab_offset = symtab_data.GetU32(&offset);
symbol_name_cstr = strtab_data.PeekCStr(strtab_offset);
symbol_name.assign(symbol_name_cstr);
} else {
// Short string that fits into the symbol table name which is 8
// bytes
offset += sizeof(symbol.name) - 4; // Skip remaining
symbol_name_cstr = symtab_data.PeekCStr(symbol_offset);
if (symbol_name_cstr == nullptr)
break;
symbol_name.assign(symbol_name_cstr, sizeof(symbol.name));
}
symbol.value = symtab_data.GetU32(&offset);
symbol.sect = symtab_data.GetU16(&offset);
symbol.type = symtab_data.GetU16(&offset);
symbol.storage = symtab_data.GetU8(&offset);
symbol.naux = symtab_data.GetU8(&offset);
symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
if ((int16_t)symbol.sect >= 1) {
Address symbol_addr(sect_list->FindSectionByID(symbol.sect),
symbol.value);
symbols[i].GetAddressRef() = symbol_addr;
symbols[i].SetType(MapSymbolType(symbol.type));
}
const uint32_t num_syms = m_coff_header.nsyms;
if (symbol.naux > 0) {
i += symbol.naux;
offset += symbol.naux * symbol_size;
if (m_file && num_syms > 0 && m_coff_header.symoff > 0) {
const uint32_t symbol_size = 18;
const size_t symbol_data_size = num_syms * symbol_size;
// Include the 4-byte string table size at the end of the symbols
DataExtractor symtab_data =
ReadImageData(m_coff_header.symoff, symbol_data_size + 4);
lldb::offset_t offset = symbol_data_size;
const uint32_t strtab_size = symtab_data.GetU32(&offset);
if (strtab_size > 0) {
DataExtractor strtab_data = ReadImageData(
m_coff_header.symoff + symbol_data_size, strtab_size);
offset = 0;
std::string symbol_name;
Symbol *symbols = m_symtab_up->Resize(num_syms);
for (uint32_t i = 0; i < num_syms; ++i) {
coff_symbol_t symbol;
const uint32_t symbol_offset = offset;
const char *symbol_name_cstr = nullptr;
// If the first 4 bytes of the symbol string are zero, then they
// are followed by a 4-byte string table offset. Else these
// 8 bytes contain the symbol name
if (symtab_data.GetU32(&offset) == 0) {
// Long string that doesn't fit into the symbol table name, so
// now we must read the 4 byte string table offset
uint32_t strtab_offset = symtab_data.GetU32(&offset);
symbol_name_cstr = strtab_data.PeekCStr(strtab_offset);
symbol_name.assign(symbol_name_cstr);
} else {
// Short string that fits into the symbol table name which is 8
// bytes
offset += sizeof(symbol.name) - 4; // Skip remaining
symbol_name_cstr = symtab_data.PeekCStr(symbol_offset);
if (symbol_name_cstr == nullptr)
break;
symbol_name.assign(symbol_name_cstr, sizeof(symbol.name));
}
symbol.value = symtab_data.GetU32(&offset);
symbol.sect = symtab_data.GetU16(&offset);
symbol.type = symtab_data.GetU16(&offset);
symbol.storage = symtab_data.GetU8(&offset);
symbol.naux = symtab_data.GetU8(&offset);
symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
if ((int16_t)symbol.sect >= 1) {
Address symbol_addr(sect_list->FindSectionByID(symbol.sect),
symbol.value);
symbols[i].GetAddressRef() = symbol_addr;
symbols[i].SetType(MapSymbolType(symbol.type));
}
if (symbol.naux > 0) {
i += symbol.naux;
offset += symbol.naux * symbol_size;
}
}
}
}
// Read export header
if (coff_data_dir_export_table < m_coff_header_opt.data_dirs.size() &&
m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmsize > 0 &&
m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr > 0) {
export_directory_entry export_table;
uint32_t data_start =
m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr;
DataExtractor symtab_data = ReadImageDataByRVA(
data_start, m_coff_header_opt.data_dirs[0].vmsize);
lldb::offset_t offset = 0;
// Read export_table header
export_table.characteristics = symtab_data.GetU32(&offset);
export_table.time_date_stamp = symtab_data.GetU32(&offset);
export_table.major_version = symtab_data.GetU16(&offset);
export_table.minor_version = symtab_data.GetU16(&offset);
export_table.name = symtab_data.GetU32(&offset);
export_table.base = symtab_data.GetU32(&offset);
export_table.number_of_functions = symtab_data.GetU32(&offset);
export_table.number_of_names = symtab_data.GetU32(&offset);
export_table.address_of_functions = symtab_data.GetU32(&offset);
export_table.address_of_names = symtab_data.GetU32(&offset);
export_table.address_of_name_ordinals = symtab_data.GetU32(&offset);
bool has_ordinal = export_table.address_of_name_ordinals != 0;
lldb::offset_t name_offset = export_table.address_of_names - data_start;
lldb::offset_t name_ordinal_offset =
export_table.address_of_name_ordinals - data_start;
Symbol *symbols = m_symtab_up->Resize(export_table.number_of_names);
std::string symbol_name;
// Read each export table entry
for (size_t i = 0; i < export_table.number_of_names; ++i) {
uint32_t name_ordinal =
has_ordinal ? symtab_data.GetU16(&name_ordinal_offset) : i;
uint32_t name_address = symtab_data.GetU32(&name_offset);
const char *symbol_name_cstr =
symtab_data.PeekCStr(name_address - data_start);
symbol_name.assign(symbol_name_cstr);
lldb::offset_t function_offset = export_table.address_of_functions -
data_start +
sizeof(uint32_t) * name_ordinal;
uint32_t function_rva = symtab_data.GetU32(&function_offset);
Address symbol_addr(m_coff_header_opt.image_base + function_rva,
sect_list);
symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
symbols[i].GetAddressRef() = symbol_addr;
symbols[i].SetType(lldb::eSymbolTypeCode);
symbols[i].SetDebug(true);
}
}
m_symtab_up->CalculateSymbolSizes();
}
}
// Read export header
if (coff_data_dir_export_table < m_coff_header_opt.data_dirs.size() &&
m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmsize > 0 &&
m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr > 0) {
export_directory_entry export_table;
uint32_t data_start =
m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr;
DataExtractor symtab_data = ReadImageDataByRVA(
data_start, m_coff_header_opt.data_dirs[0].vmsize);
lldb::offset_t offset = 0;
// Read export_table header
export_table.characteristics = symtab_data.GetU32(&offset);
export_table.time_date_stamp = symtab_data.GetU32(&offset);
export_table.major_version = symtab_data.GetU16(&offset);
export_table.minor_version = symtab_data.GetU16(&offset);
export_table.name = symtab_data.GetU32(&offset);
export_table.base = symtab_data.GetU32(&offset);
export_table.number_of_functions = symtab_data.GetU32(&offset);
export_table.number_of_names = symtab_data.GetU32(&offset);
export_table.address_of_functions = symtab_data.GetU32(&offset);
export_table.address_of_names = symtab_data.GetU32(&offset);
export_table.address_of_name_ordinals = symtab_data.GetU32(&offset);
bool has_ordinal = export_table.address_of_name_ordinals != 0;
lldb::offset_t name_offset = export_table.address_of_names - data_start;
lldb::offset_t name_ordinal_offset =
export_table.address_of_name_ordinals - data_start;
Symbol *symbols = symtab.Resize(export_table.number_of_names);
std::string symbol_name;
// Read each export table entry
for (size_t i = 0; i < export_table.number_of_names; ++i) {
uint32_t name_ordinal =
has_ordinal ? symtab_data.GetU16(&name_ordinal_offset) : i;
uint32_t name_address = symtab_data.GetU32(&name_offset);
const char *symbol_name_cstr =
symtab_data.PeekCStr(name_address - data_start);
symbol_name.assign(symbol_name_cstr);
lldb::offset_t function_offset = export_table.address_of_functions -
data_start +
sizeof(uint32_t) * name_ordinal;
uint32_t function_rva = symtab_data.GetU32(&function_offset);
Address symbol_addr(m_coff_header_opt.image_base + function_rva,
sect_list);
symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
symbols[i].GetAddressRef() = symbol_addr;
symbols[i].SetType(lldb::eSymbolTypeCode);
symbols[i].SetDebug(true);
}
}
return m_symtab_up.get();
}
std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {

View File

@@ -107,7 +107,7 @@ public:
// virtual lldb_private::AddressClass
// GetAddressClass (lldb::addr_t file_addr);
void ParseSymtab(lldb_private::Symtab &symtab) override;
lldb_private::Symtab *GetSymtab() override;
bool IsStripped() override;

View File

@@ -246,7 +246,7 @@ bool ObjectFileWasm::ParseHeader() {
return true;
}
void ObjectFileWasm::ParseSymtab(Symtab &symtab) {}
Symtab *ObjectFileWasm::GetSymtab() { return nullptr; }
static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
if (Name.consume_front(".debug_") || Name.consume_front(".zdebug_")) {

View File

@@ -78,7 +78,7 @@ public:
return AddressClass::eInvalid;
}
void ParseSymtab(lldb_private::Symtab &symtab) override;
Symtab *GetSymtab() override;
bool IsStripped() override { return !!GetExternalDebugInfoFileSpec(); }

View File

@@ -73,7 +73,7 @@ public:
bool IsExecutable() const override { return false; }
ArchSpec GetArchitecture() override { return m_arch; }
UUID GetUUID() override { return m_uuid; }
void ParseSymtab(lldb_private::Symtab &symtab) override {}
Symtab *GetSymtab() override { return m_symtab_up.get(); }
bool IsStripped() override { return true; }
ByteOrder GetByteOrder() const override { return m_arch.GetByteOrder(); }

View File

@@ -500,7 +500,7 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {
for (Symbol &symbol : symbols)
symtab.AddSymbol(std::move(symbol));
symtab.Finalize();
symtab.CalculateSymbolSizes();
}
llvm::Expected<lldb::addr_t>
@@ -927,3 +927,4 @@ uint64_t SymbolFileBreakpad::GetDebugInfoSize() {
// Breakpad files are all debug info.
return m_objfile_sp->GetByteSize();
}

View File

@@ -1421,6 +1421,7 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) {
));
}
symtab.CalculateSymbolSizes();
symtab.Finalize();
}

View File

@@ -715,20 +715,3 @@ void llvm::format_provider<ObjectFile::Strata>::format(
break;
}
}
Symtab *ObjectFile::GetSymtab() {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (!m_symtab_up) {
ElapsedTime elapsed(module_sp->GetSymtabParseTime());
m_symtab_up = std::make_unique<Symtab>(this);
std::lock_guard<std::recursive_mutex> symtab_guard(
m_symtab_up->GetMutex());
ParseSymtab(*m_symtab_up);
m_symtab_up->Finalize();
}
}
return m_symtab_up.get();
}

View File

@@ -997,15 +997,10 @@ void Symtab::InitAddressIndexes() {
}
}
void Symtab::Finalize() {
void Symtab::CalculateSymbolSizes() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
// Calculate the size of symbols inside InitAddressIndexes.
// Size computation happens inside InitAddressIndexes.
InitAddressIndexes();
// Shrink to fit the symbols so we don't waste memory
if (m_symbols.capacity() > m_symbols.size()) {
collection new_symbols(m_symbols.begin(), m_symbols.end());
m_symbols.swap(new_symbols);
}
}
Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) {