Path: blob/main/contrib/llvm-project/lld/COFF/InputFiles.h
34870 views
//===- InputFiles.h ---------------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLD_COFF_INPUT_FILES_H9#define LLD_COFF_INPUT_FILES_H1011#include "Config.h"12#include "lld/Common/LLVM.h"13#include "llvm/ADT/ArrayRef.h"14#include "llvm/ADT/DenseMap.h"15#include "llvm/ADT/DenseSet.h"16#include "llvm/ADT/StringSet.h"17#include "llvm/BinaryFormat/Magic.h"18#include "llvm/Object/Archive.h"19#include "llvm/Object/COFF.h"20#include "llvm/Support/StringSaver.h"21#include <memory>22#include <set>23#include <vector>2425namespace llvm {26struct DILineInfo;27namespace pdb {28class DbiModuleDescriptorBuilder;29class NativeSession;30}31namespace lto {32class InputFile;33}34}3536namespace lld {37class DWARFCache;3839namespace coff {40class COFFLinkerContext;4142std::vector<MemoryBufferRef> getArchiveMembers(llvm::object::Archive *file);4344using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;45using llvm::COFF::MachineTypes;46using llvm::object::Archive;47using llvm::object::COFFObjectFile;48using llvm::object::COFFSymbolRef;49using llvm::object::coff_import_header;50using llvm::object::coff_section;5152class Chunk;53class Defined;54class DefinedImportData;55class DefinedImportThunk;56class DefinedRegular;57class SectionChunk;58class Symbol;59class Undefined;60class TpiSource;6162// The root class of input files.63class InputFile {64public:65enum Kind {66ArchiveKind,67ObjectKind,68LazyObjectKind,69PDBKind,70ImportKind,71BitcodeKind,72DLLKind73};74Kind kind() const { return fileKind; }75virtual ~InputFile() {}7677// Returns the filename.78StringRef getName() const { return mb.getBufferIdentifier(); }7980// Reads a file (the constructor doesn't do that).81virtual void parse() = 0;8283// Returns the CPU type this file was compiled to.84virtual MachineTypes getMachineType() { return IMAGE_FILE_MACHINE_UNKNOWN; }8586MemoryBufferRef mb;8788// An archive file name if this file is created from an archive.89StringRef parentName;9091// Returns .drectve section contents if exist.92StringRef getDirectives() { return directives; }9394COFFLinkerContext &ctx;9596protected:97InputFile(COFFLinkerContext &c, Kind k, MemoryBufferRef m, bool lazy = false)98: mb(m), ctx(c), fileKind(k), lazy(lazy) {}99100StringRef directives;101102private:103const Kind fileKind;104105public:106// True if this is a lazy ObjFile or BitcodeFile.107bool lazy = false;108};109110// .lib or .a file.111class ArchiveFile : public InputFile {112public:113explicit ArchiveFile(COFFLinkerContext &ctx, MemoryBufferRef m);114static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }115void parse() override;116117// Enqueues an archive member load for the given symbol. If we've already118// enqueued a load for the same archive member, this function does nothing,119// which ensures that we don't load the same member more than once.120void addMember(const Archive::Symbol &sym);121122private:123std::unique_ptr<Archive> file;124llvm::DenseSet<uint64_t> seen;125};126127// .obj or .o file. This may be a member of an archive file.128class ObjFile : public InputFile {129public:130explicit ObjFile(COFFLinkerContext &ctx, MemoryBufferRef m, bool lazy = false)131: InputFile(ctx, ObjectKind, m, lazy) {}132static bool classof(const InputFile *f) { return f->kind() == ObjectKind; }133void parse() override;134void parseLazy();135MachineTypes getMachineType() override;136ArrayRef<Chunk *> getChunks() { return chunks; }137ArrayRef<SectionChunk *> getDebugChunks() { return debugChunks; }138ArrayRef<SectionChunk *> getSXDataChunks() { return sxDataChunks; }139ArrayRef<SectionChunk *> getGuardFidChunks() { return guardFidChunks; }140ArrayRef<SectionChunk *> getGuardIATChunks() { return guardIATChunks; }141ArrayRef<SectionChunk *> getGuardLJmpChunks() { return guardLJmpChunks; }142ArrayRef<SectionChunk *> getGuardEHContChunks() { return guardEHContChunks; }143ArrayRef<Symbol *> getSymbols() { return symbols; }144145MutableArrayRef<Symbol *> getMutableSymbols() { return symbols; }146147ArrayRef<uint8_t> getDebugSection(StringRef secName);148149// Returns a Symbol object for the symbolIndex'th symbol in the150// underlying object file.151Symbol *getSymbol(uint32_t symbolIndex) {152return symbols[symbolIndex];153}154155// Returns the underlying COFF file.156COFFObjectFile *getCOFFObj() { return coffObj.get(); }157158// Add a symbol for a range extension thunk. Return the new symbol table159// index. This index can be used to modify a relocation.160uint32_t addRangeThunkSymbol(Symbol *thunk) {161symbols.push_back(thunk);162return symbols.size() - 1;163}164165void includeResourceChunks();166167bool isResourceObjFile() const { return !resourceChunks.empty(); }168169// Flags in the absolute @feat.00 symbol if it is present. These usually170// indicate if an object was compiled with certain security features enabled171// like stack guard, safeseh, /guard:cf, or other things.172uint32_t feat00Flags = 0;173174// True if this object file is compatible with SEH. COFF-specific and175// x86-only. COFF spec 5.10.1. The .sxdata section.176bool hasSafeSEH() { return feat00Flags & 0x1; }177178// True if this file was compiled with /guard:cf.179bool hasGuardCF() { return feat00Flags & 0x800; }180181// True if this file was compiled with /guard:ehcont.182bool hasGuardEHCont() { return feat00Flags & 0x4000; }183184// Pointer to the PDB module descriptor builder. Various debug info records185// will reference object files by "module index", which is here. Things like186// source files and section contributions are also recorded here. Will be null187// if we are not producing a PDB.188llvm::pdb::DbiModuleDescriptorBuilder *moduleDBI = nullptr;189190const coff_section *addrsigSec = nullptr;191192const coff_section *callgraphSec = nullptr;193194// When using Microsoft precompiled headers, this is the PCH's key.195// The same key is used by both the precompiled object, and objects using the196// precompiled object. Any difference indicates out-of-date objects.197std::optional<uint32_t> pchSignature;198199// Whether this file was compiled with /hotpatch.200bool hotPatchable = false;201202// Whether the object was already merged into the final PDB.203bool mergedIntoPDB = false;204205// If the OBJ has a .debug$T stream, this tells how it will be handled.206TpiSource *debugTypesObj = nullptr;207208// The .debug$P or .debug$T section data if present. Empty otherwise.209ArrayRef<uint8_t> debugTypes;210211std::optional<std::pair<StringRef, uint32_t>>212getVariableLocation(StringRef var);213214std::optional<llvm::DILineInfo> getDILineInfo(uint32_t offset,215uint32_t sectionIndex);216217private:218const coff_section* getSection(uint32_t i);219const coff_section *getSection(COFFSymbolRef sym) {220return getSection(sym.getSectionNumber());221}222223void enqueuePdbFile(StringRef path, ObjFile *fromFile);224225void initializeChunks();226void initializeSymbols();227void initializeFlags();228void initializeDependencies();229void initializeECThunks();230231SectionChunk *232readSection(uint32_t sectionNumber,233const llvm::object::coff_aux_section_definition *def,234StringRef leaderName);235236void readAssociativeDefinition(237COFFSymbolRef coffSym,238const llvm::object::coff_aux_section_definition *def);239240void readAssociativeDefinition(241COFFSymbolRef coffSym,242const llvm::object::coff_aux_section_definition *def,243uint32_t parentSection);244245void recordPrevailingSymbolForMingw(246COFFSymbolRef coffSym,247llvm::DenseMap<StringRef, uint32_t> &prevailingSectionMap);248249void maybeAssociateSEHForMingw(250COFFSymbolRef sym, const llvm::object::coff_aux_section_definition *def,251const llvm::DenseMap<StringRef, uint32_t> &prevailingSectionMap);252253// Given a new symbol Sym with comdat selection Selection, if the new254// symbol is not (yet) Prevailing and the existing comdat leader set to255// Leader, emits a diagnostic if the new symbol and its selection doesn't256// match the existing symbol and its selection. If either old or new257// symbol have selection IMAGE_COMDAT_SELECT_LARGEST, Sym might replace258// the existing leader. In that case, Prevailing is set to true.259void260handleComdatSelection(COFFSymbolRef sym, llvm::COFF::COMDATType &selection,261bool &prevailing, DefinedRegular *leader,262const llvm::object::coff_aux_section_definition *def);263264std::optional<Symbol *>265createDefined(COFFSymbolRef sym,266std::vector<const llvm::object::coff_aux_section_definition *>267&comdatDefs,268bool &prevailingComdat);269Symbol *createRegular(COFFSymbolRef sym);270Symbol *createUndefined(COFFSymbolRef sym);271272std::unique_ptr<COFFObjectFile> coffObj;273274// List of all chunks defined by this file. This includes both section275// chunks and non-section chunks for common symbols.276std::vector<Chunk *> chunks;277278std::vector<SectionChunk *> resourceChunks;279280// CodeView debug info sections.281std::vector<SectionChunk *> debugChunks;282283// Chunks containing symbol table indices of exception handlers. Only used for284// 32-bit x86.285std::vector<SectionChunk *> sxDataChunks;286287// Chunks containing symbol table indices of address taken symbols, address288// taken IAT entries, longjmp and ehcont targets. These are not linked into289// the final binary when /guard:cf is set.290std::vector<SectionChunk *> guardFidChunks;291std::vector<SectionChunk *> guardIATChunks;292std::vector<SectionChunk *> guardLJmpChunks;293std::vector<SectionChunk *> guardEHContChunks;294295std::vector<SectionChunk *> hybmpChunks;296297// This vector contains a list of all symbols defined or referenced by this298// file. They are indexed such that you can get a Symbol by symbol299// index. Nonexistent indices (which are occupied by auxiliary300// symbols in the real symbol table) are filled with null pointers.301std::vector<Symbol *> symbols;302303// This vector contains the same chunks as Chunks, but they are304// indexed such that you can get a SectionChunk by section index.305// Nonexistent section indices are filled with null pointers.306// (Because section number is 1-based, the first slot is always a307// null pointer.) This vector is only valid during initialization.308std::vector<SectionChunk *> sparseChunks;309310DWARFCache *dwarf = nullptr;311};312313// This is a PDB type server dependency, that is not a input file per se, but314// needs to be treated like one. Such files are discovered from the debug type315// stream.316class PDBInputFile : public InputFile {317public:318explicit PDBInputFile(COFFLinkerContext &ctx, MemoryBufferRef m);319~PDBInputFile();320static bool classof(const InputFile *f) { return f->kind() == PDBKind; }321void parse() override;322323static PDBInputFile *findFromRecordPath(const COFFLinkerContext &ctx,324StringRef path, ObjFile *fromFile);325326// Record possible errors while opening the PDB file327std::optional<std::string> loadErrorStr;328329// This is the actual interface to the PDB (if it was opened successfully)330std::unique_ptr<llvm::pdb::NativeSession> session;331332// If the PDB has a .debug$T stream, this tells how it will be handled.333TpiSource *debugTypesObj = nullptr;334};335336// This type represents import library members that contain DLL names337// and symbols exported from the DLLs. See Microsoft PE/COFF spec. 7338// for details about the format.339class ImportFile : public InputFile {340public:341explicit ImportFile(COFFLinkerContext &ctx, MemoryBufferRef m);342343static bool classof(const InputFile *f) { return f->kind() == ImportKind; }344345Symbol *impSym = nullptr;346Symbol *thunkSym = nullptr;347std::string dllName;348349private:350void parse() override;351352public:353StringRef externalName;354const coff_import_header *hdr;355Chunk *location = nullptr;356357// We want to eliminate dllimported symbols if no one actually refers to them.358// These "Live" bits are used to keep track of which import library members359// are actually in use.360//361// If the Live bit is turned off by MarkLive, Writer will ignore dllimported362// symbols provided by this import library member. We also track whether the363// imported symbol is used separately from whether the thunk is used in order364// to avoid creating unnecessary thunks.365bool live;366bool thunkLive;367};368369// Used for LTO.370class BitcodeFile : public InputFile {371public:372explicit BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb,373StringRef archiveName, uint64_t offsetInArchive,374bool lazy);375~BitcodeFile();376static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }377ArrayRef<Symbol *> getSymbols() { return symbols; }378MachineTypes getMachineType() override;379void parseLazy();380std::unique_ptr<llvm::lto::InputFile> obj;381382private:383void parse() override;384385std::vector<Symbol *> symbols;386};387388// .dll file. MinGW only.389class DLLFile : public InputFile {390public:391explicit DLLFile(COFFLinkerContext &ctx, MemoryBufferRef m)392: InputFile(ctx, DLLKind, m) {}393static bool classof(const InputFile *f) { return f->kind() == DLLKind; }394void parse() override;395MachineTypes getMachineType() override;396397struct Symbol {398StringRef dllName;399StringRef symbolName;400llvm::COFF::ImportNameType nameType;401llvm::COFF::ImportType importType;402};403404void makeImport(Symbol *s);405406private:407std::unique_ptr<COFFObjectFile> coffObj;408llvm::StringSet<> seen;409};410411inline bool isBitcode(MemoryBufferRef mb) {412return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode;413}414415std::string replaceThinLTOSuffix(StringRef path, StringRef suffix,416StringRef repl);417} // namespace coff418419std::string toString(const coff::InputFile *file);420} // namespace lld421422#endif423424425