[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:
Rui Ueyama 2013-12-16 07:14:40 +00:00
parent a1df6379a6
commit 69b899a127
3 changed files with 43 additions and 30 deletions

View File

@ -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));

View File

@ -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;

View 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