450 lines · c
1//===- InputFiles.h ---------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLD_COFF_INPUT_FILES_H10#define LLD_COFF_INPUT_FILES_H11 12#include "Config.h"13#include "lld/Common/LLVM.h"14#include "llvm/ADT/ArrayRef.h"15#include "llvm/ADT/DenseMap.h"16#include "llvm/ADT/DenseSet.h"17#include "llvm/ADT/StringSet.h"18#include "llvm/BinaryFormat/Magic.h"19#include "llvm/Object/Archive.h"20#include "llvm/Object/COFF.h"21#include "llvm/Support/StringSaver.h"22#include <memory>23#include <set>24#include <vector>25 26namespace llvm {27struct DILineInfo;28namespace pdb {29class DbiModuleDescriptorBuilder;30class NativeSession;31}32namespace lto {33class InputFile;34}35}36 37namespace lld {38class DWARFCache;39 40namespace coff {41class COFFLinkerContext;42 43const COFFSyncStream &operator<<(const COFFSyncStream &, const InputFile *);44 45std::vector<MemoryBufferRef> getArchiveMembers(COFFLinkerContext &,46 llvm::object::Archive *file);47 48using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;49using llvm::COFF::MachineTypes;50using llvm::object::Archive;51using llvm::object::COFFObjectFile;52using llvm::object::COFFSymbolRef;53using llvm::object::coff_import_header;54using llvm::object::coff_section;55 56class Chunk;57class Defined;58class DefinedImportData;59class DefinedImportThunk;60class DefinedRegular;61class ImportThunkChunk;62class ImportThunkChunkARM64EC;63class SectionChunk;64class Symbol;65class SymbolTable;66class Undefined;67class TpiSource;68 69// The root class of input files.70class InputFile {71public:72 enum Kind {73 ArchiveKind,74 ObjectKind,75 PDBKind,76 ImportKind,77 BitcodeKind,78 DLLKind79 };80 Kind kind() const { return fileKind; }81 virtual ~InputFile() {}82 83 // Returns the filename.84 StringRef getName() const { return mb.getBufferIdentifier(); }85 86 // Reads a file (the constructor doesn't do that).87 virtual void parse() = 0;88 89 // Returns the CPU type this file was compiled to.90 virtual MachineTypes getMachineType() const {91 return IMAGE_FILE_MACHINE_UNKNOWN;92 }93 94 MemoryBufferRef mb;95 96 // An archive file name if this file is created from an archive.97 StringRef parentName;98 99 // Returns .drectve section contents if exist.100 StringRef getDirectives() { return directives; }101 102 SymbolTable &symtab;103 104protected:105 InputFile(SymbolTable &s, Kind k, MemoryBufferRef m, bool lazy = false)106 : mb(m), symtab(s), fileKind(k), lazy(lazy) {}107 108 StringRef directives;109 110private:111 const Kind fileKind;112 113public:114 // True if this is a lazy ObjFile or BitcodeFile.115 bool lazy = false;116};117 118// .lib or .a file.119class ArchiveFile : public InputFile {120public:121 explicit ArchiveFile(COFFLinkerContext &ctx, MemoryBufferRef m);122 static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }123 void parse() override;124 125 // Enqueues an archive member load for the given symbol. If we've already126 // enqueued a load for the same archive member, this function does nothing,127 // which ensures that we don't load the same member more than once.128 void addMember(const Archive::Symbol &sym);129 130private:131 std::unique_ptr<Archive> file;132 llvm::DenseSet<uint64_t> seen;133};134 135// .obj or .o file. This may be a member of an archive file.136class ObjFile : public InputFile {137public:138 static ObjFile *create(COFFLinkerContext &ctx, MemoryBufferRef mb,139 bool lazy = false);140 explicit ObjFile(SymbolTable &symtab, COFFObjectFile *coffObj, bool lazy);141 142 static bool classof(const InputFile *f) { return f->kind() == ObjectKind; }143 void parse() override;144 void parseLazy();145 MachineTypes getMachineType() const override;146 ArrayRef<Chunk *> getChunks() { return chunks; }147 ArrayRef<SectionChunk *> getDebugChunks() { return debugChunks; }148 ArrayRef<SectionChunk *> getSXDataChunks() { return sxDataChunks; }149 ArrayRef<SectionChunk *> getGuardFidChunks() { return guardFidChunks; }150 ArrayRef<SectionChunk *> getGuardIATChunks() { return guardIATChunks; }151 ArrayRef<SectionChunk *> getGuardLJmpChunks() { return guardLJmpChunks; }152 ArrayRef<SectionChunk *> getGuardEHContChunks() { return guardEHContChunks; }153 ArrayRef<Symbol *> getSymbols() { return symbols; }154 155 MutableArrayRef<Symbol *> getMutableSymbols() { return symbols; }156 157 ArrayRef<uint8_t> getDebugSection(StringRef secName);158 159 // Returns a Symbol object for the symbolIndex'th symbol in the160 // underlying object file.161 Symbol *getSymbol(uint32_t symbolIndex) {162 return symbols[symbolIndex];163 }164 165 // Returns the underlying COFF file.166 COFFObjectFile *getCOFFObj() { return coffObj.get(); }167 168 // Add a symbol for a range extension thunk. Return the new symbol table169 // index. This index can be used to modify a relocation.170 uint32_t addRangeThunkSymbol(Symbol *thunk) {171 symbols.push_back(thunk);172 return symbols.size() - 1;173 }174 175 void includeResourceChunks();176 177 bool isResourceObjFile() const { return !resourceChunks.empty(); }178 179 // Flags in the absolute @feat.00 symbol if it is present. These usually180 // indicate if an object was compiled with certain security features enabled181 // like stack guard, safeseh, /guard:cf, or other things.182 uint32_t feat00Flags = 0;183 184 // True if this object file is compatible with SEH. COFF-specific and185 // x86-only. COFF spec 5.10.1. The .sxdata section.186 bool hasSafeSEH() { return feat00Flags & 0x1; }187 188 // True if this file was compiled with /guard:cf.189 bool hasGuardCF() { return feat00Flags & 0x800; }190 191 // True if this file was compiled with /guard:ehcont.192 bool hasGuardEHCont() { return feat00Flags & 0x4000; }193 194 // Pointer to the PDB module descriptor builder. Various debug info records195 // will reference object files by "module index", which is here. Things like196 // source files and section contributions are also recorded here. Will be null197 // if we are not producing a PDB.198 llvm::pdb::DbiModuleDescriptorBuilder *moduleDBI = nullptr;199 200 const coff_section *addrsigSec = nullptr;201 202 const coff_section *callgraphSec = nullptr;203 204 // When using Microsoft precompiled headers, this is the PCH's key.205 // The same key is used by both the precompiled object, and objects using the206 // precompiled object. Any difference indicates out-of-date objects.207 std::optional<uint32_t> pchSignature;208 209 // Whether this file was compiled with /hotpatch.210 bool hotPatchable = false;211 212 // Whether the object was already merged into the final PDB.213 bool mergedIntoPDB = false;214 215 // If the OBJ has a .debug$T stream, this tells how it will be handled.216 TpiSource *debugTypesObj = nullptr;217 218 // The .debug$P or .debug$T section data if present. Empty otherwise.219 ArrayRef<uint8_t> debugTypes;220 221 std::optional<std::pair<StringRef, uint32_t>>222 getVariableLocation(StringRef var);223 224 std::optional<llvm::DILineInfo> getDILineInfo(uint32_t offset,225 uint32_t sectionIndex);226 227private:228 const coff_section* getSection(uint32_t i);229 const coff_section *getSection(COFFSymbolRef sym) {230 return getSection(sym.getSectionNumber());231 }232 233 void enqueuePdbFile(StringRef path, ObjFile *fromFile);234 235 void initializeChunks();236 void initializeSymbols();237 void initializeFlags();238 void initializeDependencies();239 void initializeECThunks();240 241 SectionChunk *242 readSection(uint32_t sectionNumber,243 const llvm::object::coff_aux_section_definition *def,244 StringRef leaderName);245 246 void readAssociativeDefinition(247 COFFSymbolRef coffSym,248 const llvm::object::coff_aux_section_definition *def);249 250 void readAssociativeDefinition(251 COFFSymbolRef coffSym,252 const llvm::object::coff_aux_section_definition *def,253 uint32_t parentSection);254 255 void recordPrevailingSymbolForMingw(256 COFFSymbolRef coffSym,257 llvm::DenseMap<StringRef, uint32_t> &prevailingSectionMap);258 259 void maybeAssociateSEHForMingw(260 COFFSymbolRef sym, const llvm::object::coff_aux_section_definition *def,261 const llvm::DenseMap<StringRef, uint32_t> &prevailingSectionMap);262 263 // Given a new symbol Sym with comdat selection Selection, if the new264 // symbol is not (yet) Prevailing and the existing comdat leader set to265 // Leader, emits a diagnostic if the new symbol and its selection doesn't266 // match the existing symbol and its selection. If either old or new267 // symbol have selection IMAGE_COMDAT_SELECT_LARGEST, Sym might replace268 // the existing leader. In that case, Prevailing is set to true.269 void270 handleComdatSelection(COFFSymbolRef sym, llvm::COFF::COMDATType &selection,271 bool &prevailing, DefinedRegular *leader,272 const llvm::object::coff_aux_section_definition *def);273 274 std::optional<Symbol *>275 createDefined(COFFSymbolRef sym,276 std::vector<const llvm::object::coff_aux_section_definition *>277 &comdatDefs,278 bool &prevailingComdat);279 Symbol *createRegular(COFFSymbolRef sym);280 Symbol *createUndefined(COFFSymbolRef sym, bool overrideLazy);281 282 std::unique_ptr<COFFObjectFile> coffObj;283 284 // List of all chunks defined by this file. This includes both section285 // chunks and non-section chunks for common symbols.286 std::vector<Chunk *> chunks;287 288 std::vector<SectionChunk *> resourceChunks;289 290 // CodeView debug info sections.291 std::vector<SectionChunk *> debugChunks;292 293 // Chunks containing symbol table indices of exception handlers. Only used for294 // 32-bit x86.295 std::vector<SectionChunk *> sxDataChunks;296 297 // Chunks containing symbol table indices of address taken symbols, address298 // taken IAT entries, longjmp and ehcont targets. These are not linked into299 // the final binary when /guard:cf is set.300 std::vector<SectionChunk *> guardFidChunks;301 std::vector<SectionChunk *> guardIATChunks;302 std::vector<SectionChunk *> guardLJmpChunks;303 std::vector<SectionChunk *> guardEHContChunks;304 305 std::vector<SectionChunk *> hybmpChunks;306 307 // This vector contains a list of all symbols defined or referenced by this308 // file. They are indexed such that you can get a Symbol by symbol309 // index. Nonexistent indices (which are occupied by auxiliary310 // symbols in the real symbol table) are filled with null pointers.311 std::vector<Symbol *> symbols;312 313 // This vector contains the same chunks as Chunks, but they are314 // indexed such that you can get a SectionChunk by section index.315 // Nonexistent section indices are filled with null pointers.316 // (Because section number is 1-based, the first slot is always a317 // null pointer.) This vector is only valid during initialization.318 std::vector<SectionChunk *> sparseChunks;319 320 DWARFCache *dwarf = nullptr;321};322 323// This is a PDB type server dependency, that is not a input file per se, but324// needs to be treated like one. Such files are discovered from the debug type325// stream.326class PDBInputFile : public InputFile {327public:328 explicit PDBInputFile(COFFLinkerContext &ctx, MemoryBufferRef m);329 ~PDBInputFile();330 static bool classof(const InputFile *f) { return f->kind() == PDBKind; }331 void parse() override;332 333 static PDBInputFile *findFromRecordPath(const COFFLinkerContext &ctx,334 StringRef path, ObjFile *fromFile);335 336 // Record possible errors while opening the PDB file337 std::optional<std::string> loadErrorStr;338 339 // This is the actual interface to the PDB (if it was opened successfully)340 std::unique_ptr<llvm::pdb::NativeSession> session;341 342 // If the PDB has a .debug$T stream, this tells how it will be handled.343 TpiSource *debugTypesObj = nullptr;344};345 346// This type represents import library members that contain DLL names347// and symbols exported from the DLLs. See Microsoft PE/COFF spec. 7348// for details about the format.349class ImportFile : public InputFile {350public:351 explicit ImportFile(COFFLinkerContext &ctx, MemoryBufferRef m);352 353 static bool classof(const InputFile *f) { return f->kind() == ImportKind; }354 MachineTypes getMachineType() const override { return getMachineType(mb); }355 static MachineTypes getMachineType(MemoryBufferRef m);356 bool isSameImport(const ImportFile *other) const;357 bool isEC() const { return impECSym != nullptr; }358 359 DefinedImportData *impSym = nullptr;360 Defined *thunkSym = nullptr;361 ImportThunkChunkARM64EC *impchkThunk = nullptr;362 ImportFile *hybridFile = nullptr;363 std::string dllName;364 365private:366 void parse() override;367 ImportThunkChunk *makeImportThunk();368 369public:370 StringRef externalName;371 const coff_import_header *hdr;372 Chunk *location = nullptr;373 374 // Auxiliary IAT symbols and chunks on ARM64EC.375 DefinedImportData *impECSym = nullptr;376 Chunk *auxLocation = nullptr;377 Defined *auxThunkSym = nullptr;378 DefinedImportData *auxImpCopySym = nullptr;379 Chunk *auxCopyLocation = nullptr;380 381 // We want to eliminate dllimported symbols if no one actually refers to them.382 // These "Live" bits are used to keep track of which import library members383 // are actually in use.384 //385 // If the Live bit is turned off by MarkLive, Writer will ignore dllimported386 // symbols provided by this import library member.387 bool live;388};389 390// Used for LTO.391class BitcodeFile : public InputFile {392public:393 explicit BitcodeFile(SymbolTable &symtab, MemoryBufferRef mb,394 std::unique_ptr<llvm::lto::InputFile> &obj, bool lazy);395 ~BitcodeFile();396 397 static BitcodeFile *create(COFFLinkerContext &ctx, MemoryBufferRef mb,398 StringRef archiveName, uint64_t offsetInArchive,399 bool lazy);400 static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }401 ArrayRef<Symbol *> getSymbols() { return symbols; }402 MachineTypes getMachineType() const override {403 return getMachineType(obj.get());404 }405 static MachineTypes getMachineType(const llvm::lto::InputFile *obj);406 void parseLazy();407 std::unique_ptr<llvm::lto::InputFile> obj;408 409private:410 void parse() override;411 412 std::vector<Symbol *> symbols;413};414 415// .dll file. MinGW only.416class DLLFile : public InputFile {417public:418 explicit DLLFile(SymbolTable &symtab, MemoryBufferRef m)419 : InputFile(symtab, DLLKind, m) {}420 static bool classof(const InputFile *f) { return f->kind() == DLLKind; }421 void parse() override;422 MachineTypes getMachineType() const override;423 424 struct Symbol {425 StringRef dllName;426 StringRef symbolName;427 llvm::COFF::ImportNameType nameType;428 llvm::COFF::ImportType importType;429 };430 431 void makeImport(Symbol *s);432 433private:434 std::unique_ptr<COFFObjectFile> coffObj;435 llvm::StringSet<> seen;436};437 438inline bool isBitcode(MemoryBufferRef mb) {439 return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode;440}441 442std::string replaceThinLTOSuffix(StringRef path, StringRef suffix,443 StringRef repl);444} // namespace coff445 446std::string toString(const coff::InputFile *file);447} // namespace lld448 449#endif450