diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h @@ -268,10 +268,12 @@ private: bool CreateBinary(); + typedef std::vector> rva_symbol_list_t; void AppendFromCOFFSymbolTable(lldb_private::SectionList *sect_list, - lldb_private::Symtab &symtab); - void AppendFromExportTable(lldb_private::SectionList *sect_list, - lldb_private::Symtab &symtab); + lldb_private::Symtab &symtab, + const rva_symbol_list_t &sorted_exports); + rva_symbol_list_t AppendFromExportTable(lldb_private::SectionList *sect_list, + lldb_private::Symtab &symtab); dos_header_t m_dos_header; coff_header_t m_coff_header; diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -761,12 +761,18 @@ void ObjectFilePECOFF::ParseSymtab(Symtab &symtab) { SectionList *sect_list = GetSectionList(); - AppendFromExportTable(sect_list, symtab); - AppendFromCOFFSymbolTable(sect_list, symtab); + rva_symbol_list_t sorted_exports = AppendFromExportTable(sect_list, symtab); + AppendFromCOFFSymbolTable(sect_list, symtab, sorted_exports); } -void ObjectFilePECOFF::AppendFromCOFFSymbolTable(SectionList *sect_list, - Symtab &symtab) { +static bool RVASymbolListCompareRVA(const std::pair &a, + const std::pair &b) { + return a.first < b.first; +} + +void ObjectFilePECOFF::AppendFromCOFFSymbolTable( + SectionList *sect_list, Symtab &symtab, + const ObjectFilePECOFF::rva_symbol_list_t &sorted_exports) { const uint32_t num_syms = m_binary->getNumberOfSymbols(); if (num_syms == 0) return; @@ -795,22 +801,51 @@ if (section_number >= 1) { symbol.GetAddressRef() = Address( sect_list->FindSectionByID(section_number), coff_sym_ref.getValue()); - symbol.SetType(MapSymbolType(coff_sym_ref.getType())); + const auto symbol_type = MapSymbolType(coff_sym_ref.getType()); + symbol.SetType(symbol_type); + + // Check for duplicate of exported symbols: + const uint32_t symbol_rva = symbol.GetAddressRef().GetFileAddress() - + m_coff_header_opt.image_base; + const auto &first_match = std::lower_bound( + sorted_exports.begin(), sorted_exports.end(), + std::make_pair(symbol_rva, 0), RVASymbolListCompareRVA); + for (auto it = first_match; + it != sorted_exports.end() && it->first == symbol_rva; ++it) { + Symbol *exported = symtab.SymbolAtIndex(it->second); + if (symbol_type != lldb::eSymbolTypeInvalid) + exported->SetType(symbol_type); + if (exported->GetMangled() == symbol.GetMangled()) { + symbol.SetExternal(true); + // We don't want the symbol to be duplicated (e.g. when running + // `disas -n func`), but we also don't want to erase this entry (to + // preserve the original symbol order), so we mark it as additional. + symbol.SetType(lldb::eSymbolTypeAdditional); + } else { + // It is possible for a symbol to be exported in a different name + // from its original. In this case keep both entries so lookup using + // either names will work. Only synchronize the symbol type. + if (symbol.GetType() == lldb::eSymbolTypeInvalid) + symbol.SetType(exported->GetType()); + } + } } symtab.AddSymbol(symbol); } } -void ObjectFilePECOFF::AppendFromExportTable(SectionList *sect_list, - Symtab &symtab) { +ObjectFilePECOFF::rva_symbol_list_t +ObjectFilePECOFF::AppendFromExportTable(SectionList *sect_list, + Symtab &symtab) { const auto *export_table = m_binary->getExportTable(); if (!export_table) - return; + return {}; const uint32_t num_syms = export_table->AddressTableEntries; if (num_syms == 0) - return; + return {}; Log *log = GetLog(LLDBLog::Object); + rva_symbol_list_t export_list; symtab.Reserve(symtab.GetNumSymbols() + num_syms); // Read each export table entry, ordered by ordinal instead of by name. for (const auto &entry : m_binary->export_directories()) { @@ -851,8 +886,11 @@ if (section_sp->GetPermissions() & ePermissionsExecutable) symbol.SetType(lldb::eSymbolTypeCode); symbol.SetExternal(true); - symtab.AddSymbol(symbol); + uint32_t idx = symtab.AddSymbol(symbol); + export_list.push_back(std::make_pair(function_rva, idx)); } + std::sort(export_list.begin(), export_list.end(), RVASymbolListCompareRVA); + return export_list; } std::unique_ptr ObjectFilePECOFF::CreateCallFrameInfo() { diff --git a/lldb/test/Shell/ObjectFile/PECOFF/symbols-export-table.yaml b/lldb/test/Shell/ObjectFile/PECOFF/symbols-export-table.yaml --- a/lldb/test/Shell/ObjectFile/PECOFF/symbols-export-table.yaml +++ b/lldb/test/Shell/ObjectFile/PECOFF/symbols-export-table.yaml @@ -6,20 +6,28 @@ # CHECK: UserID DSX Type File Address/Value {{.*}} Size Flags Name # CHECK-NEXT: ------ -# CHECK-NEXT: 1 X Code 0x0000000180001010 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportFunc -# CHECK-NEXT: 2 X Data 0x0000000180003000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportInt -# CHECK-NEXT: 4294967295 Code 0x0000000180001000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} entry -# CHECK-NEXT: 4294967295 Code 0x0000000180001010 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportFunc -# CHECK-NEXT: 4294967295 Invalid 0x0000000180003000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportInt +# CHECK-NEXT: 1 X Code 0x0000000180001020 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportFnAlias +# CHECK-NEXT: 2 X Code 0x0000000180001010 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportFunc +# CHECK-NEXT: 3 X Data 0x0000000180003000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportInt +# CHECK-NEXT: 4 X Data 0x0000000180003004 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportIntAlias +# CHECK-NEXT: 4294967295 Code 0x0000000180001000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} entry +# CHECK-NEXT: 4294967295 X Additional 0x0000000180001010 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportFunc +# CHECK-NEXT: 4294967295 Code 0x0000000180001020 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} aliasFunc +# CHECK-NEXT: 4294967295 X Additional 0x0000000180003000 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} exportInt +# CHECK-NEXT: 4294967295 Data 0x0000000180003004 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} aliasInt +# CHECK-NEXT: 4294967295 Invalid 0x0000000180003008 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}} internalInt # CHECK-EMPTY: # Test file generated with: # clang -O2 --target=x86_64-windows-gnu test.c -nostdlib -c -o test.obj -# lld-link -lldmingw -debug:symtab -dll -out:test.dll -entry:entry test.obj +# lld-link -lldmingw -debug:symtab -dll -out:test.dll -entry:entry -export:exportFnAlias=aliasFn -export:exportIntAlias=aliasInt test.obj # test.c: # __attribute__((dllexport)) int exportInt; +# int internalInt; +# int aliasInt; # void entry(void) {} # __attribute__((dllexport)) void exportFunc(void) {} +# void aliasFunc(void) {} --- !COFF OptionalHeader: @@ -41,7 +49,7 @@ SizeOfHeapCommit: 4096 ExportTable: RelativeVirtualAddress: 8224 - Size: 107 + Size: 156 header: Machine: IMAGE_FILE_MACHINE_AMD64 Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE, IMAGE_FILE_DLL ] @@ -49,17 +57,17 @@ - Name: .text Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] VirtualAddress: 4096 - VirtualSize: 17 - SectionData: C36666666666662E0F1F840000000000C3 + VirtualSize: 33 + SectionData: C36666666666662E0F1F840000000000C36666666666662E0F1F840000000000C3 - Name: .rdata Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] VirtualAddress: 8192 - VirtualSize: 139 - SectionData: FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF000000000000000000000000000000000000000048200000010000000200000002000000622000006A2000007220000073796D626F6C732D6578706F7274732E632E746D702E646C6C0010100000003000007620000081200000000001006578706F727446756E63006578706F7274496E7400 + VirtualSize: 188 + SectionData: FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000004820000001000000040000000400000062200000722000008220000073796D626F6C732D6578706F7274732E632E746D702E646C6C00201000001010000000300000043000008A20000098200000A3200000AD20000000000100020003006578706F7274466E416C696173006578706F727446756E63006578706F7274496E74006578706F7274496E74416C69617300 - Name: .data Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] VirtualAddress: 12288 - VirtualSize: 4 + VirtualSize: 12 SectionData: '' symbols: - Name: entry @@ -74,10 +82,28 @@ SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_FUNCTION StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: aliasFunc + Value: 32 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL - Name: exportInt Value: 0 SectionNumber: 3 SimpleType: IMAGE_SYM_TYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: aliasInt + Value: 4 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: internalInt + Value: 8 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL ...