Skip to content

Commit 20c2f94

Browse files
alvinhochunmstorsjo
authored andcommitted
[lldb][COFF] Match symbols from COFF symbol table to export symbols
If a symbol is the same as an export symbol, mark it as 'Additional' to prevent the duplicated symbol from being repeated in some commands (e.g. `disas -n func`). If the RVA is the same but exported with a different name, only synchronize the symbol types. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D134426
1 parent 0870afc commit 20c2f94

File tree

3 files changed

+66
-24
lines changed

3 files changed

+66
-24
lines changed

lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -761,12 +761,18 @@ llvm::StringRef ObjectFilePECOFF::GetSectionName(const section_header_t &sect) {
761761

762762
void ObjectFilePECOFF::ParseSymtab(Symtab &symtab) {
763763
SectionList *sect_list = GetSectionList();
764-
AppendFromExportTable(sect_list, symtab);
765-
AppendFromCOFFSymbolTable(sect_list, symtab);
764+
rva_symbol_list_t sorted_exports = AppendFromExportTable(sect_list, symtab);
765+
AppendFromCOFFSymbolTable(sect_list, symtab, sorted_exports);
766766
}
767767

768-
void ObjectFilePECOFF::AppendFromCOFFSymbolTable(SectionList *sect_list,
769-
Symtab &symtab) {
768+
static bool RVASymbolListCompareRVA(const std::pair<uint32_t, uint32_t> &a,
769+
const std::pair<uint32_t, uint32_t> &b) {
770+
return a.first < b.first;
771+
}
772+
773+
void ObjectFilePECOFF::AppendFromCOFFSymbolTable(
774+
SectionList *sect_list, Symtab &symtab,
775+
const ObjectFilePECOFF::rva_symbol_list_t &sorted_exports) {
770776
const uint32_t num_syms = m_binary->getNumberOfSymbols();
771777
if (num_syms == 0)
772778
return;
@@ -795,22 +801,52 @@ void ObjectFilePECOFF::AppendFromCOFFSymbolTable(SectionList *sect_list,
795801
if (section_number >= 1) {
796802
symbol.GetAddressRef() = Address(
797803
sect_list->FindSectionByID(section_number), coff_sym_ref.getValue());
798-
symbol.SetType(MapSymbolType(coff_sym_ref.getType()));
804+
const auto symbol_type = MapSymbolType(coff_sym_ref.getType());
805+
symbol.SetType(symbol_type);
806+
807+
// Check for duplicate of exported symbols:
808+
const uint32_t symbol_rva = symbol.GetAddressRef().GetFileAddress() -
809+
m_coff_header_opt.image_base;
810+
const auto &first_match = std::lower_bound(
811+
sorted_exports.begin(), sorted_exports.end(),
812+
std::make_pair(symbol_rva, 0), RVASymbolListCompareRVA);
813+
for (auto it = first_match;
814+
it != sorted_exports.end() && it->first == symbol_rva; ++it) {
815+
Symbol *exported = symtab.SymbolAtIndex(it->second);
816+
if (symbol_type != lldb::eSymbolTypeInvalid)
817+
exported->SetType(symbol_type);
818+
if (exported->GetMangled() == symbol.GetMangled()) {
819+
symbol.SetExternal(true);
820+
// We don't want the symbol to be duplicated (e.g. when running
821+
// `disas -n func`), but we also don't want to erase this entry (to
822+
// preserve the original symbol order), so we mark it as additional.
823+
symbol.SetType(lldb::eSymbolTypeAdditional);
824+
} else {
825+
// It is possible for a symbol to be exported in a different name
826+
// from its original. In this case keep both entries so lookup using
827+
// either names will work. If this symbol has an invalid type, replace
828+
// it with the type from the export symbol.
829+
if (symbol.GetType() == lldb::eSymbolTypeInvalid)
830+
symbol.SetType(exported->GetType());
831+
}
832+
}
799833
}
800834
symtab.AddSymbol(symbol);
801835
}
802836
}
803837

804-
void ObjectFilePECOFF::AppendFromExportTable(SectionList *sect_list,
805-
Symtab &symtab) {
838+
ObjectFilePECOFF::rva_symbol_list_t
839+
ObjectFilePECOFF::AppendFromExportTable(SectionList *sect_list,
840+
Symtab &symtab) {
806841
const auto *export_table = m_binary->getExportTable();
807842
if (!export_table)
808-
return;
843+
return {};
809844
const uint32_t num_syms = export_table->AddressTableEntries;
810845
if (num_syms == 0)
811-
return;
846+
return {};
812847

813848
Log *log = GetLog(LLDBLog::Object);
849+
rva_symbol_list_t export_list;
814850
symtab.Reserve(symtab.GetNumSymbols() + num_syms);
815851
// Read each export table entry, ordered by ordinal instead of by name.
816852
for (const auto &entry : m_binary->export_directories()) {
@@ -851,8 +887,12 @@ void ObjectFilePECOFF::AppendFromExportTable(SectionList *sect_list,
851887
if (section_sp->GetPermissions() & ePermissionsExecutable)
852888
symbol.SetType(lldb::eSymbolTypeCode);
853889
symbol.SetExternal(true);
854-
symtab.AddSymbol(symbol);
890+
uint32_t idx = symtab.AddSymbol(symbol);
891+
export_list.push_back(std::make_pair(function_rva, idx));
855892
}
893+
std::stable_sort(export_list.begin(), export_list.end(),
894+
RVASymbolListCompareRVA);
895+
return export_list;
856896
}
857897

858898
std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {

lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,12 @@ class ObjectFilePECOFF : public lldb_private::ObjectFile {
268268

269269
private:
270270
bool CreateBinary();
271+
typedef std::vector<std::pair<uint32_t, uint32_t>> rva_symbol_list_t;
271272
void AppendFromCOFFSymbolTable(lldb_private::SectionList *sect_list,
272-
lldb_private::Symtab &symtab);
273-
void AppendFromExportTable(lldb_private::SectionList *sect_list,
274-
lldb_private::Symtab &symtab);
273+
lldb_private::Symtab &symtab,
274+
const rva_symbol_list_t &sorted_exports);
275+
rva_symbol_list_t AppendFromExportTable(lldb_private::SectionList *sect_list,
276+
lldb_private::Symtab &symtab);
275277

276278
dos_header_t m_dos_header;
277279
coff_header_t m_coff_header;

lldb/test/Shell/ObjectFile/PECOFF/symbols-export-table.yaml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44
# Checks that the symtab contains both symbols from the export table and the
55
# COFF symbol table.
66

7-
# CHECK: UserID DSX Type File Address/Value {{.*}} Size Flags Name
7+
# CHECK: UserID DSX Type File Address/Value {{.*}} Size Flags Name
88
# CHECK-NEXT: ------
9-
# CHECK-NEXT: 1 X Code 0x0000000180001020 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportFnAlias
10-
# CHECK-NEXT: 2 X Code 0x0000000180001010 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportFunc
11-
# CHECK-NEXT: 3 X Data 0x0000000180003000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportInt
12-
# CHECK-NEXT: 4 X Data 0x0000000180003004 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportIntAlias
13-
# CHECK-NEXT: 4294967295 Code 0x0000000180001000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} entry
14-
# CHECK-NEXT: 4294967295 Code 0x0000000180001010 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportFunc
15-
# CHECK-NEXT: 4294967295 Code 0x0000000180001020 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} aliasFunc
16-
# CHECK-NEXT: 4294967295 Invalid 0x0000000180003000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportInt
17-
# CHECK-NEXT: 4294967295 Invalid 0x0000000180003004 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} aliasInt
18-
# CHECK-NEXT: 4294967295 Invalid 0x0000000180003008 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} internalInt
9+
# CHECK-NEXT: 1 X Code 0x0000000180001020 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportFnAlias
10+
# CHECK-NEXT: 2 X Code 0x0000000180001010 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportFunc
11+
# CHECK-NEXT: 3 X Data 0x0000000180003000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportInt
12+
# CHECK-NEXT: 4 X Data 0x0000000180003004 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportIntAlias
13+
# CHECK-NEXT: 4294967295 Code 0x0000000180001000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} entry
14+
# CHECK-NEXT: 4294967295 X Additional 0x0000000180001010 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportFunc
15+
# CHECK-NEXT: 4294967295 Code 0x0000000180001020 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} aliasFunc
16+
# CHECK-NEXT: 4294967295 X Additional 0x0000000180003000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportInt
17+
# CHECK-NEXT: 4294967295 Data 0x0000000180003004 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} aliasInt
18+
# CHECK-NEXT: 4294967295 Invalid 0x0000000180003008 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} internalInt
1919
# CHECK-EMPTY:
2020

2121
# Test file generated with:

0 commit comments

Comments
 (0)