diff --git a/test/tools/llvm-readobj/Inputs/export-arm.dll b/test/tools/llvm-readobj/Inputs/export-arm.dll new file mode 100755 index 00000000000..a5555628afc Binary files /dev/null and b/test/tools/llvm-readobj/Inputs/export-arm.dll differ diff --git a/test/tools/llvm-readobj/Inputs/export-x64.dll b/test/tools/llvm-readobj/Inputs/export-x64.dll new file mode 100755 index 00000000000..10b14e8fff9 Binary files /dev/null and b/test/tools/llvm-readobj/Inputs/export-x64.dll differ diff --git a/test/tools/llvm-readobj/Inputs/export-x86.dll b/test/tools/llvm-readobj/Inputs/export-x86.dll new file mode 100755 index 00000000000..9efcd3131fe Binary files /dev/null and b/test/tools/llvm-readobj/Inputs/export-x86.dll differ diff --git a/test/tools/llvm-readobj/coff-exports.test b/test/tools/llvm-readobj/coff-exports.test new file mode 100644 index 00000000000..54b42fef84b --- /dev/null +++ b/test/tools/llvm-readobj/coff-exports.test @@ -0,0 +1,11 @@ +RUN: llvm-readobj -coff-exports %p/Inputs/export-x86.dll | FileCheck %s -check-prefix CHECK -check-prefix CHECK-X86 +RUN: llvm-readobj -coff-exports %p/Inputs/export-x64.dll | FileCheck %s -check-prefix CHECK -check-prefix CHECK-X64 +RUN: llvm-readobj -coff-exports %p/Inputs/export-arm.dll | FileCheck %s -check-prefix CHECK -check-prefix CHECK-ARM + +CHECK: Export { +CHECK: Ordinal: 1 +CHECK: Name: function +CHECK-X86: RVA: 0x1000 +CHECK-X64: RVA: 0x1000 +CHECK-ARM: RVA: 0x1001 +CHECK: } diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index 5276428c511..156e39a35fd 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -57,6 +57,7 @@ public: void printDynamicSymbols() override; void printUnwindInfo() override; void printCOFFImports() override; + void printCOFFExports() override; void printCOFFDirectives() override; void printCOFFBaseReloc() override; @@ -1062,6 +1063,26 @@ void COFFDumper::printCOFFImports() { } } +void COFFDumper::printCOFFExports() { + for (const ExportDirectoryEntryRef &E : Obj->export_directories()) { + DictScope Export(W, "Export"); + + StringRef Name; + uint32_t Ordinal, RVA; + + if (error(E.getSymbolName(Name))) + continue; + if (error(E.getOrdinal(Ordinal))) + continue; + if (error(E.getExportRVA(RVA))) + continue; + + W.printNumber("Ordinal", Ordinal); + W.printString("Name", Name); + W.printHex("RVA", RVA); + } +} + void COFFDumper::printCOFFDirectives() { for (const SectionRef &Section : Obj->sections()) { StringRef Contents; diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index a34e0912728..27e658fc731 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -45,6 +45,7 @@ public: // Only implemented for PE/COFF. virtual void printCOFFImports() { } + virtual void printCOFFExports() { } virtual void printCOFFDirectives() { } virtual void printCOFFBaseReloc() { } diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index d08f18608ed..f95fea8ec3e 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -146,6 +146,10 @@ namespace opts { cl::opt COFFImports("coff-imports", cl::desc("Display the PE/COFF import table")); + // -coff-exports + cl::opt + COFFExports("coff-exports", cl::desc("Display the PE/COFF export table")); + // -coff-directives cl::opt COFFDirectives("coff-directives", @@ -282,6 +286,8 @@ static void dumpObject(const ObjectFile *Obj) { Dumper->printMipsPLTGOT(); if (opts::COFFImports) Dumper->printCOFFImports(); + if (opts::COFFExports) + Dumper->printCOFFExports(); if (opts::COFFDirectives) Dumper->printCOFFDirectives(); if (opts::COFFBaseRelocs)