summaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/PECOFF/EdataPass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/PECOFF/EdataPass.cpp')
-rw-r--r--lib/ReaderWriter/PECOFF/EdataPass.cpp227
1 files changed, 0 insertions, 227 deletions
diff --git a/lib/ReaderWriter/PECOFF/EdataPass.cpp b/lib/ReaderWriter/PECOFF/EdataPass.cpp
deleted file mode 100644
index ad79f171f3c9f..0000000000000
--- a/lib/ReaderWriter/PECOFF/EdataPass.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/EdataPass.cpp ------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Pass.h"
-#include "EdataPass.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/Simple.h"
-#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;
-using llvm::object::export_address_table_entry;
-using llvm::object::export_directory_table_entry;
-
-namespace lld {
-namespace pecoff {
-
-typedef PECOFFLinkingContext::ExportDesc ExportDesc;
-
-// dedupExports removes duplicate export entries. If two exports are
-// referring the same symbol, they are considered duplicates.
-// This could happen if the same symbol name is specified as an argument
-// to /export more than once, or an unmangled and mangled name of the
-// same symbol are given to /export. In the latter case, we choose
-// unmangled (shorter) name.
-static void dedupExports(PECOFFLinkingContext &ctx) {
- std::vector<ExportDesc> &exports = ctx.getDllExports();
- // Pass 1: find duplicate entries
- std::set<const ExportDesc *> dup;
- std::map<StringRef, ExportDesc *> map;
- for (ExportDesc &exp : exports) {
- if (!exp.externalName.empty())
- continue;
- StringRef symbol = exp.getRealName();
- auto it = map.find(symbol);
- if (it == map.end()) {
- map[symbol] = &exp;
- } else if (symbol.size() < it->second->getRealName().size()) {
- map[symbol] = &exp;
- dup.insert(it->second);
- } else {
- dup.insert(&exp);
- }
- }
- // Pass 2: remove duplicate entries
- auto pred = [&](const ExportDesc &exp) {
- return dup.count(&exp) == 1;
- };
- exports.erase(std::remove_if(exports.begin(), exports.end(), pred),
- exports.end());
-}
-
-static void assignOrdinals(PECOFFLinkingContext &ctx) {
- std::vector<ExportDesc> &exports = ctx.getDllExports();
- int maxOrdinal = -1;
- for (ExportDesc &desc : exports)
- maxOrdinal = std::max(maxOrdinal, desc.ordinal);
-
- std::sort(exports.begin(), exports.end(),
- [](const ExportDesc &a, const ExportDesc &b) {
- return a.getExternalName().compare(b.getExternalName()) < 0;
- });
-
- int nextOrdinal = (maxOrdinal == -1) ? 1 : (maxOrdinal + 1);
- for (ExportDesc &desc : exports)
- if (desc.ordinal == -1)
- desc.ordinal = nextOrdinal++;
-}
-
-static bool getExportedAtoms(PECOFFLinkingContext &ctx, MutableFile *file,
- std::vector<TableEntry> &ret) {
- std::map<StringRef, const DefinedAtom *> definedAtoms;
- for (const DefinedAtom *atom : file->defined())
- definedAtoms[atom->name()] = atom;
-
- for (PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports()) {
- auto it = definedAtoms.find(desc.getRealName());
- if (it == definedAtoms.end()) {
- llvm::errs() << "Symbol <" << desc.name
- << "> is exported but not defined.\n";
- return false;
- }
- const DefinedAtom *atom = it->second;
-
- // One can export a symbol with a different name than the symbol
- // name used in DLL. If such name is specified, use it in the
- // .edata section.
- ret.push_back(TableEntry(ctx.undecorateSymbol(desc.getExternalName()),
- desc.ordinal, atom, desc.noname));
- }
- std::sort(ret.begin(), ret.end(),
- [](const TableEntry &a, const TableEntry &b) {
- return a.exportName.compare(b.exportName) < 0;
- });
-
- return true;
-}
-
-static std::pair<int, int> getOrdinalBase(std::vector<TableEntry> &entries) {
- int ordinalBase = INT_MAX;
- int maxOrdinal = -1;
- for (TableEntry &e : entries) {
- ordinalBase = std::min(ordinalBase, e.ordinal);
- maxOrdinal = std::max(maxOrdinal, e.ordinal);
- }
- return std::pair<int, int>(ordinalBase, maxOrdinal);
-}
-
-edata::EdataAtom *
-EdataPass::createAddressTable(const std::vector<TableEntry> &entries,
- 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 - ordinalBase;
- size_t offset = index * sizeof(export_address_table_entry);
- addDir32NBReloc(addressTable, e.atom, _ctx.getMachineType(), offset);
- }
- return addressTable;
-}
-
-edata::EdataAtom *
-EdataPass::createNamePointerTable(const PECOFFLinkingContext &ctx,
- const std::vector<TableEntry> &entries,
- MutableFile *file) {
- EdataAtom *table =
- new (_alloc) EdataAtom(_file, sizeof(uint32_t) * entries.size());
-
- size_t offset = 0;
- for (const TableEntry &e : entries) {
- auto *stringAtom = new (_alloc) COFFStringAtom(
- _file, _stringOrdinal++, ".edata", e.exportName);
- file->addAtom(*stringAtom);
- addDir32NBReloc(table, stringAtom, _ctx.getMachineType(), offset);
- offset += sizeof(uint32_t);
- }
- return table;
-}
-
-edata::EdataAtom *EdataPass::createExportDirectoryTable(
- const std::vector<edata::TableEntry> &namedEntries, 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 = ordinalBase;
- data->AddressTableEntries = maxOrdinal - ordinalBase + 1;
- data->NumberOfNamePointers = namedEntries.size();
- return ret;
-}
-
-edata::EdataAtom *
-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 - ordinalBase;
- return ret;
-}
-
-void EdataPass::perform(std::unique_ptr<MutableFile> &file) {
- dedupExports(_ctx);
- assignOrdinals(_ctx);
-
- std::vector<TableEntry> entries;
- if (!getExportedAtoms(_ctx, file.get(), entries))
- return;
- if (entries.empty())
- return;
-
- int ordinalBase, maxOrdinal;
- std::tie(ordinalBase, maxOrdinal) = getOrdinalBase(entries);
-
- std::vector<TableEntry> namedEntries;
- for (TableEntry &e : entries)
- if (!e.noname)
- namedEntries.push_back(e);
-
- EdataAtom *table =
- createExportDirectoryTable(namedEntries, ordinalBase, maxOrdinal);
- file->addAtom(*table);
-
- COFFStringAtom *dllName =
- new (_alloc) COFFStringAtom(_file, _stringOrdinal++, ".edata",
- llvm::sys::path::filename(_ctx.outputPath()));
- file->addAtom(*dllName);
- addDir32NBReloc(table, dllName, _ctx.getMachineType(),
- offsetof(export_directory_table_entry, NameRVA));
-
- EdataAtom *addressTable =
- createAddressTable(entries, ordinalBase, maxOrdinal);
- file->addAtom(*addressTable);
- addDir32NBReloc(
- table, addressTable, _ctx.getMachineType(),
- offsetof(export_directory_table_entry, ExportAddressTableRVA));
-
- EdataAtom *namePointerTable =
- createNamePointerTable(_ctx, namedEntries, file.get());
- file->addAtom(*namePointerTable);
- addDir32NBReloc(table, namePointerTable, _ctx.getMachineType(),
- offsetof(export_directory_table_entry, NamePointerRVA));
-
- EdataAtom *ordinalTable = createOrdinalTable(namedEntries, ordinalBase);
- file->addAtom(*ordinalTable);
- addDir32NBReloc(table, ordinalTable, _ctx.getMachineType(),
- offsetof(export_directory_table_entry, OrdinalTableRVA));
-}
-
-} // namespace pecoff
-} // namespace lld