diff --git a/lld/lib/ReaderWriter/PECOFF/EdataPass.cpp b/lld/lib/ReaderWriter/PECOFF/EdataPass.cpp index a72cca9f9f263ae45c9ab53b868913b0b6ac1ece..7fe6bae6f2235631b6c8a8a95fcf3820b510eeee 100644 --- a/lld/lib/ReaderWriter/PECOFF/EdataPass.cpp +++ b/lld/lib/ReaderWriter/PECOFF/EdataPass.cpp @@ -16,7 +16,9 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/Path.h" +#include #include +#include using lld::pecoff::edata::EdataAtom; using lld::pecoff::edata::TableEntry; @@ -26,8 +28,6 @@ using llvm::object::export_directory_table_entry; namespace lld { namespace pecoff { -static const int ORDINAL_BASE = 1; - static bool compare(const TableEntry &a, const TableEntry &b) { return a.exportName.compare(b.exportName) < 0; } @@ -52,31 +52,38 @@ static bool getExportedAtoms(const PECOFFLinkingContext &ctx, MutableFile *file, return true; } -static int assignOrdinals(std::vector &entries) { +static std::pair assignOrdinals(std::vector &entries) { + int ordinalBase = INT_MAX; int maxOrdinal = -1; - for (TableEntry &e : entries) + for (TableEntry &e : entries) { + if (e.ordinal > 0) + ordinalBase = std::min(ordinalBase, e.ordinal); maxOrdinal = std::max(maxOrdinal, e.ordinal); + } + if (ordinalBase == INT_MAX) + ordinalBase = 1; if (maxOrdinal == -1) { int ordinal = 0; for (TableEntry &e : entries) e.ordinal = ++ordinal; - return ordinal; + return std::pair(ordinalBase, ordinal); } for (TableEntry &e : entries) if (e.ordinal == -1) e.ordinal = ++maxOrdinal; - return maxOrdinal; + return std::pair(ordinalBase, maxOrdinal); } edata::EdataAtom * EdataPass::createAddressTable(const std::vector &entries, - int maxOrdinal) { - EdataAtom *addressTable = new (_alloc) - EdataAtom(_file, sizeof(export_address_table_entry) * maxOrdinal); + int ordinalBase, int maxOrdinal) { + EdataAtom *addressTable = + new (_alloc) EdataAtom(_file, sizeof(export_address_table_entry) * + (maxOrdinal - ordinalBase + 1)); for (const TableEntry &e : entries) { - int index = e.ordinal - ORDINAL_BASE; + int index = e.ordinal - ordinalBase; size_t offset = index * sizeof(export_address_table_entry); addDir32NBReloc(addressTable, e.atom, offset); } @@ -102,25 +109,27 @@ EdataPass::createNamePointerTable(const PECOFFLinkingContext &ctx, } edata::EdataAtom *EdataPass::createExportDirectoryTable( - const std::vector &entries, int maxOrdinal) { + const std::vector &entries, int ordinalBase, + int maxOrdinal) { EdataAtom *ret = new (_alloc) EdataAtom(_file, sizeof(export_directory_table_entry)); auto *data = ret->getContents(); data->TimeDateStamp = time(nullptr); - data->OrdinalBase = ORDINAL_BASE; - data->AddressTableEntries = maxOrdinal; + data->OrdinalBase = ordinalBase; + data->AddressTableEntries = maxOrdinal - ordinalBase + 1; data->NumberOfNamePointers = entries.size(); return ret; } edata::EdataAtom * -EdataPass::createOrdinalTable(const std::vector &entries) { +EdataPass::createOrdinalTable(const std::vector &entries, + int ordinalBase) { EdataAtom *ret = new (_alloc) EdataAtom(_file, sizeof(uint16_t) * entries.size()); uint16_t *data = ret->getContents(); int i = 0; for (const TableEntry &e : entries) - data[i++] = e.ordinal - ORDINAL_BASE; + data[i++] = e.ordinal - ordinalBase; return ret; } @@ -130,9 +139,12 @@ void EdataPass::perform(std::unique_ptr &file) { return; if (entries.empty()) return; - int maxOrdinal = assignOrdinals(entries); - EdataAtom *table = createExportDirectoryTable(entries, maxOrdinal); + int ordinalBase, maxOrdinal; + llvm::tie(ordinalBase, maxOrdinal) = assignOrdinals(entries); + + EdataAtom *table = + createExportDirectoryTable(entries, ordinalBase, maxOrdinal); file->addAtom(*table); COFFStringAtom *dllName = @@ -142,7 +154,8 @@ void EdataPass::perform(std::unique_ptr &file) { addDir32NBReloc(table, dllName, offsetof(export_directory_table_entry, NameRVA)); - EdataAtom *addressTable = createAddressTable(entries, maxOrdinal); + EdataAtom *addressTable = + createAddressTable(entries, ordinalBase, maxOrdinal); file->addAtom(*addressTable); addDir32NBReloc(table, addressTable, offsetof(export_directory_table_entry, ExportAddressTableRVA)); @@ -153,7 +166,7 @@ void EdataPass::perform(std::unique_ptr &file) { addDir32NBReloc(table, namePointerTable, offsetof(export_directory_table_entry, NamePointerRVA)); - EdataAtom *ordinalTable = createOrdinalTable(entries); + EdataAtom *ordinalTable = createOrdinalTable(entries, ordinalBase); file->addAtom(*ordinalTable); addDir32NBReloc(table, ordinalTable, offsetof(export_directory_table_entry, OrdinalTableRVA)); diff --git a/lld/lib/ReaderWriter/PECOFF/EdataPass.h b/lld/lib/ReaderWriter/PECOFF/EdataPass.h index 8ca87ab87489423ee2cbd6e6bf034f38af9b5d3a..66d0315191917fd6897bceac71454157923ff144 100644 --- a/lld/lib/ReaderWriter/PECOFF/EdataPass.h +++ b/lld/lib/ReaderWriter/PECOFF/EdataPass.h @@ -72,11 +72,11 @@ public: private: edata::EdataAtom * createExportDirectoryTable(const std::vector &entries, - int maxOrdinal); + int ordinalBase, int maxOrdinal); edata::EdataAtom * createAddressTable(const std::vector &entries, - int maxOrdinal); + int ordinalBase, int maxOrdinal); edata::EdataAtom * createNamePointerTable(const PECOFFLinkingContext &ctx, @@ -84,7 +84,8 @@ private: MutableFile *file); edata::EdataAtom * - createOrdinalTable(const std::vector &entries); + createOrdinalTable(const std::vector &entries, + int ordinalBase); const PECOFFLinkingContext &_ctx; VirtualFile _file; diff --git a/lld/test/pecoff/export.test b/lld/test/pecoff/export.test index c790ed1936932a98f6967e61a33537d2b550feff..2578764e6c5b4411a95ccc8ccd38650f46357ac5 100644 --- a/lld/test/pecoff/export.test +++ b/lld/test/pecoff/export.test @@ -18,11 +18,10 @@ CHECK1-NEXT: 1060 74666e32 00 # RUN: llvm-objdump -s %t2.dll | FileCheck -check-prefix=CHECK2 %s CHECK2: Contents of section .edata: -CHECK2-NEXT: 1000 00000000 {{........}} 00000000 4c100000 -CHECK2-NEXT: 1010 01000000 06000000 02000000 28100000 -CHECK2-NEXT: 1020 40100000 48100000 00000000 00000000 -CHECK2-NEXT: 1030 00000000 00000000 08200000 10200000 -CHECK2-NEXT: 1040 61100000 6b100000 04000500 6578706f -CHECK2-NEXT: 1050 72742e74 6573742e 746d7032 2e646c6c -CHECK2-NEXT: 1060 00657870 6f727466 6e310065 78706f72 -CHECK2-NEXT: 1070 74666e32 00 +CHECK2-NEXT: 1000 00000000 {{........}} 00000000 3c100000 +CHECK2-NEXT: 1010 05000000 02000000 02000000 28100000 +CHECK2-NEXT: 1020 30100000 38100000 08200000 10200000 +CHECK2-NEXT: 1030 51100000 5b100000 00000100 6578706f +CHECK2-NEXT: 1040 72742e74 6573742e 746d7032 2e646c6c +CHECK2-NEXT: 1050 00657870 6f727466 6e310065 78706f72 +CHECK2-NEXT: 1060 74666e32 00