diff options
Diffstat (limited to 'lib/ReaderWriter/PECOFF/EdataPass.cpp')
| -rw-r--r-- | lib/ReaderWriter/PECOFF/EdataPass.cpp | 227 |
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 |
