[NFC] Refactor symbol table parsing.
Symbol table parsing has evolved over the years and many plug-ins contained duplicate code in the ObjectFile::GetSymtab() that used to be pure virtual. With this change, the "Symbtab *ObjectFile::GetSymtab()" is no longer virtual and will end up calling a new "void ObjectFile::ParseSymtab(Symtab &symtab)" pure virtual function to actually do the parsing. This helps centralize the code for parsing the symbol table and allows the ObjectFile base class to do all of the common work, like taking the necessary locks and creating the symbol table object itself. Plug-ins now just need to parse when they are asked to parse as the ParseSymtab function will only get called once. Differential Revision: https://reviews.llvm.org/D113965
This commit is contained in:
@@ -589,139 +589,125 @@ llvm::StringRef ObjectFilePECOFF::GetSectionName(const section_header_t §) {
|
||||
return hdr_name;
|
||||
}
|
||||
|
||||
// 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());
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
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()));
|
||||
} 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(lldb::eSymbolTypeCode);
|
||||
symbols[i].SetDebug(true);
|
||||
symbols[i].SetType(MapSymbolType(symbol.type));
|
||||
}
|
||||
|
||||
if (symbol.naux > 0) {
|
||||
i += symbol.naux;
|
||||
offset += symbol.naux * symbol_size;
|
||||
}
|
||||
}
|
||||
m_symtab_up->CalculateSymbolSizes();
|
||||
}
|
||||
}
|
||||
return m_symtab_up.get();
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {
|
||||
|
||||
Reference in New Issue
Block a user