forked from OSchip/llvm-project
[PECOFF] Set OrdinalBase field in the export table.
OrdinalBase is an addend to the ordinals. We used to always set 1 to the field. Although it produced a valid a DLL export table, it'd be a waste if the first ordinal does not start with 1 -- we had to have NULL fields at the beginning of the export address table. By setting the ordinal base, we can eliminate the NULL fields. llvm-svn: 197367
This commit is contained in:
parent
a1df6379a6
commit
69b899a127
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue