std::vector<ImportTableEntryAtom *> ImportDirectoryAtom::createImportTableAtoms( Context &context, const std::vector<COFFSharedLibraryAtom *> &sharedAtoms, bool shouldAddReference, StringRef sectionName) const { std::vector<ImportTableEntryAtom *> ret; for (COFFSharedLibraryAtom *atom : sharedAtoms) { ImportTableEntryAtom *entry = nullptr; if (atom->importName().empty()) { // Import by ordinal uint32_t hint = (1U << 31) | atom->hint(); entry = new (_alloc) ImportTableEntryAtom(context, hint, sectionName); } else { // Import by name entry = new (_alloc) ImportTableEntryAtom(context, 0, sectionName); HintNameAtom *hintName = new (_alloc) HintNameAtom(context, atom->hint(), atom->importName()); addDir32NBReloc(entry, hintName); } ret.push_back(entry); if (shouldAddReference) atom->setImportTableEntry(entry); } // Add the NULL entry. ret.push_back(new (_alloc) ImportTableEntryAtom(context, 0, sectionName)); 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)); }
// Creates atoms for an import lookup table. The import lookup table is an // array of pointers to hint/name atoms. The array needs to be terminated with // the NULL entry. void ImportDirectoryAtom::addRelocations( Context &context, StringRef loadName, const std::vector<COFFSharedLibraryAtom *> &sharedAtoms) { // Create parallel arrays. The contents of the two are initially the // same. The PE/COFF loader overwrites the import address tables with the // pointers to the referenced items after loading the executable into // memory. std::vector<ImportTableEntryAtom *> importLookupTables = createImportTableAtoms(context, sharedAtoms, false, ".idata.t"); std::vector<ImportTableEntryAtom *> importAddressTables = createImportTableAtoms(context, sharedAtoms, true, ".idata.a"); addDir32NBReloc(this, importLookupTables[0], offsetof(ImportDirectoryTableEntry, ImportLookupTableRVA)); addDir32NBReloc(this, importAddressTables[0], offsetof(ImportDirectoryTableEntry, ImportAddressTableRVA)); auto *atom = new (_alloc) COFFStringAtom(context.dummyFile, context.dummyFile.getNextOrdinal(), ".idata", loadName); context.file.addAtom(*atom); addDir32NBReloc(this, atom, offsetof(ImportDirectoryTableEntry, NameRVA)); }
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, 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", ctx.undecorateSymbol(e.exportName)); file->addAtom(*stringAtom); addDir32NBReloc(table, stringAtom, offset); offset += sizeof(uint32_t); } return table; }