diff options
| -rw-r--r-- | lld/lib/ReaderWriter/PECOFF/EdataPass.cpp | 51 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/PECOFF/EdataPass.h | 7 | ||||
| -rw-r--r-- | lld/test/pecoff/export.test | 15 |
3 files changed, 43 insertions, 30 deletions
diff --git a/lld/lib/ReaderWriter/PECOFF/EdataPass.cpp b/lld/lib/ReaderWriter/PECOFF/EdataPass.cpp index a72cca9f9f2..7fe6bae6f22 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 <climits> #include <ctime> +#include <utility> 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<TableEntry> &entries) { +static std::pair<int, int> assignOrdinals(std::vector<TableEntry> &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<int, int>(ordinalBase, ordinal); } for (TableEntry &e : entries) if (e.ordinal == -1) e.ordinal = ++maxOrdinal; - return maxOrdinal; + return std::pair<int, int>(ordinalBase, maxOrdinal); } edata::EdataAtom * EdataPass::createAddressTable(const std::vector<TableEntry> &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<edata::TableEntry> &entries, int maxOrdinal) { + const std::vector<edata::TableEntry> &entries, int ordinalBase, + int maxOrdinal) { EdataAtom *ret = new (_alloc) EdataAtom(_file, sizeof(export_directory_table_entry)); auto *data = ret->getContents<export_directory_table_entry>(); 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<TableEntry> &entries) { +EdataPass::createOrdinalTable(const std::vector<TableEntry> &entries, + int ordinalBase) { EdataAtom *ret = new (_alloc) EdataAtom(_file, sizeof(uint16_t) * entries.size()); uint16_t *data = ret->getContents<uint16_t>(); 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<MutableFile> &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<MutableFile> &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<MutableFile> &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 8ca87ab8748..66d03151919 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<edata::TableEntry> &entries, - int maxOrdinal); + int ordinalBase, int maxOrdinal); edata::EdataAtom * createAddressTable(const std::vector<edata::TableEntry> &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<edata::TableEntry> &entries); + createOrdinalTable(const std::vector<edata::TableEntry> &entries, + int ordinalBase); const PECOFFLinkingContext &_ctx; VirtualFile _file; diff --git a/lld/test/pecoff/export.test b/lld/test/pecoff/export.test index c790ed19369..2578764e6c5 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 |

