brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.7 KiB · ba844ad Raw
390 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_ELF_INPUT_FILES_H10#define LLD_ELF_INPUT_FILES_H11 12#include "Config.h"13#include "Symbols.h"14#include "lld/Common/ErrorHandler.h"15#include "lld/Common/LLVM.h"16#include "lld/Common/Reproduce.h"17#include "llvm/ADT/DenseSet.h"18#include "llvm/BinaryFormat/Magic.h"19#include "llvm/Object/ELF.h"20#include "llvm/Support/MemoryBufferRef.h"21#include "llvm/Support/Threading.h"22 23namespace llvm {24struct DILineInfo;25class TarWriter;26namespace lto {27class InputFile;28}29} // namespace llvm30 31namespace lld {32class DWARFCache;33 34namespace elf {35class InputSection;36class Symbol;37 38// Returns "<internal>", "foo.a(bar.o)" or "baz.o".39std::string toStr(Ctx &, const InputFile *f);40const ELFSyncStream &operator<<(const ELFSyncStream &, const InputFile *);41 42// Opens a given file.43std::optional<MemoryBufferRef> readFile(Ctx &, StringRef path);44 45// Add symbols in File to the symbol table.46void parseFile(Ctx &, InputFile *file);47void parseFiles(Ctx &, const SmallVector<std::unique_ptr<InputFile>, 0> &);48 49// The root class of input files.50class InputFile {51public:52  Ctx &ctx;53 54protected:55  std::unique_ptr<Symbol *[]> symbols;56  size_t numSymbols = 0;57  SmallVector<InputSectionBase *, 0> sections;58 59public:60  enum Kind : uint8_t {61    ObjKind,62    SharedKind,63    BitcodeKind,64    BinaryKind,65    InternalKind,66  };67 68  InputFile(Ctx &, Kind k, MemoryBufferRef m);69  virtual ~InputFile();70  Kind kind() const { return fileKind; }71 72  bool isElf() const {73    Kind k = kind();74    return k == ObjKind || k == SharedKind;75  }76  bool isInternal() const { return kind() == InternalKind; }77 78  StringRef getName() const { return mb.getBufferIdentifier(); }79  MemoryBufferRef mb;80 81  // Returns sections. It is a runtime error to call this function82  // on files that don't have the notion of sections.83  ArrayRef<InputSectionBase *> getSections() const {84    assert(fileKind == ObjKind || fileKind == BinaryKind);85    return sections;86  }87  void cacheDecodedCrel(size_t i, InputSectionBase *s) { sections[i] = s; }88 89  // Returns object file symbols. It is a runtime error to call this90  // function on files of other types.91  ArrayRef<Symbol *> getSymbols() const {92    assert(fileKind == BinaryKind || fileKind == ObjKind ||93           fileKind == BitcodeKind);94    return {symbols.get(), numSymbols};95  }96 97  MutableArrayRef<Symbol *> getMutableSymbols() {98    assert(fileKind == BinaryKind || fileKind == ObjKind ||99           fileKind == BitcodeKind);100    return {symbols.get(), numSymbols};101  }102 103  Symbol &getSymbol(uint32_t symbolIndex) const {104    assert(fileKind == ObjKind);105    if (symbolIndex >= numSymbols)106      Fatal(ctx) << this << ": invalid symbol index";107    return *this->symbols[symbolIndex];108  }109 110  template <typename RelT> Symbol &getRelocTargetSym(const RelT &rel) const {111    uint32_t symIndex = rel.getSymbol(ctx.arg.isMips64EL);112    return getSymbol(symIndex);113  }114 115  // Get filename to use for linker script processing.116  StringRef getNameForScript() const;117 118  // Check if a non-common symbol should be extracted to override a common119  // definition.120  bool shouldExtractForCommon(StringRef name) const;121 122  // .got2 in the current file. This is used by PPC32 -fPIC/-fPIE to compute123  // offsets in PLT call stubs.124  InputSection *ppc32Got2 = nullptr;125 126  // Index of MIPS GOT built for this file.127  uint32_t mipsGotIndex = -1;128 129  // groupId is used for --warn-backrefs which is an optional error130  // checking feature. All files within the same --{start,end}-group or131  // --{start,end}-lib get the same group ID. Otherwise, each file gets a new132  // group ID. For more info, see checkDependency() in SymbolTable.cpp.133  uint32_t groupId;134 135  // If this is an architecture-specific file, the following members136  // have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type.137  uint16_t emachine = llvm::ELF::EM_NONE;138  const Kind fileKind;139  ELFKind ekind = ELFNoneKind;140  uint8_t osabi = 0;141  uint8_t abiVersion = 0;142 143  // True if this is a relocatable object file/bitcode file in an ar archive144  // or between --start-lib and --end-lib.145  bool lazy = false;146 147  // True if this is an argument for --just-symbols. Usually false.148  bool justSymbols = false;149 150  // On PPC64 we need to keep track of which files contain small code model151  // relocations that access the .toc section. To minimize the chance of a152  // relocation overflow, files that do contain said relocations should have153  // their .toc sections sorted closer to the .got section than files that do154  // not contain any small code model relocations. Thats because the toc-pointer155  // is defined to point at .got + 0x8000 and the instructions used with small156  // code model relocations support immediates in the range [-0x8000, 0x7FFC],157  // making the addressable range relative to the toc pointer158  // [.got, .got + 0xFFFC].159  bool ppc64SmallCodeModelTocRelocs = false;160 161  // True if the file has TLSGD/TLSLD GOT relocations without R_PPC64_TLSGD or162  // R_PPC64_TLSLD. Disable TLS relaxation to avoid bad code generation.163  bool ppc64DisableTLSRelax = false;164 165public:166  // If not empty, this stores the name of the archive containing this file.167  // We use this string for creating error messages.168  SmallString<0> archiveName;169  // Cache for toStr(Ctx &, const InputFile *). Only toStr should use this170  // member.171  mutable SmallString<0> toStringCache;172 173private:174  // Cache for getNameForScript().175  mutable SmallString<0> nameForScriptCache;176};177 178class ELFFileBase : public InputFile {179public:180  ELFFileBase(Ctx &ctx, Kind k, ELFKind ekind, MemoryBufferRef m);181  ~ELFFileBase();182  static bool classof(const InputFile *f) { return f->isElf(); }183 184  void init();185  template <typename ELFT> llvm::object::ELFFile<ELFT> getObj() const {186    return check(llvm::object::ELFFile<ELFT>::create(mb.getBuffer()));187  }188 189  StringRef getStringTable() const { return stringTable; }190 191  ArrayRef<Symbol *> getLocalSymbols() {192    if (numSymbols == 0)193      return {};194    return llvm::ArrayRef(symbols.get() + 1, firstGlobal - 1);195  }196  ArrayRef<Symbol *> getGlobalSymbols() {197    return llvm::ArrayRef(symbols.get() + firstGlobal,198                          numSymbols - firstGlobal);199  }200  MutableArrayRef<Symbol *> getMutableGlobalSymbols() {201    return llvm::MutableArrayRef(symbols.get() + firstGlobal,202                                     numSymbols - firstGlobal);203  }204 205  template <typename ELFT> typename ELFT::ShdrRange getELFShdrs() const {206    return typename ELFT::ShdrRange(207        reinterpret_cast<const typename ELFT::Shdr *>(elfShdrs), numELFShdrs);208  }209  template <typename ELFT> typename ELFT::SymRange getELFSyms() const {210    return typename ELFT::SymRange(211        reinterpret_cast<const typename ELFT::Sym *>(elfSyms), numSymbols);212  }213  template <typename ELFT> typename ELFT::SymRange getGlobalELFSyms() const {214    return getELFSyms<ELFT>().slice(firstGlobal);215  }216 217  // Get cached DWARF information.218  DWARFCache *getDwarf();219 220protected:221  // Initializes this class's member variables.222  template <typename ELFT> void init(InputFile::Kind k);223 224  StringRef stringTable;225  const void *elfShdrs = nullptr;226  const void *elfSyms = nullptr;227  uint32_t numELFShdrs = 0;228  uint32_t firstGlobal = 0;229 230  // Below are ObjFile specific members.231 232  // Debugging information to retrieve source file and line for error233  // reporting. Linker may find reasonable number of errors in a234  // single object file, so we cache debugging information in order to235  // parse it only once for each object file we link.236  llvm::once_flag initDwarf;237  std::unique_ptr<DWARFCache> dwarf;238 239public:240  // Name of source file obtained from STT_FILE, if present.241  StringRef sourceFile;242  uint32_t andFeatures = 0;243  bool hasCommonSyms = false;244  std::optional<AArch64PauthAbiCoreInfo> aarch64PauthAbiCoreInfo;245};246 247// .o file.248template <class ELFT> class ObjFile : public ELFFileBase {249  LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)250 251public:252  static bool classof(const InputFile *f) { return f->kind() == ObjKind; }253 254  llvm::object::ELFFile<ELFT> getObj() const {255    return this->ELFFileBase::getObj<ELFT>();256  }257 258  ObjFile(Ctx &ctx, ELFKind ekind, MemoryBufferRef m, StringRef archiveName)259      : ELFFileBase(ctx, ObjKind, ekind, m) {260    this->archiveName = archiveName;261  }262 263  void parse(bool ignoreComdats = false);264  void parseLazy();265 266  StringRef getShtGroupSignature(ArrayRef<Elf_Shdr> sections,267                                 const Elf_Shdr &sec);268 269  uint32_t getSectionIndex(const Elf_Sym &sym) const;270 271 272  // Pointer to this input file's .llvm_addrsig section, if it has one.273  const Elf_Shdr *addrsigSec = nullptr;274 275  // SHT_LLVM_CALL_GRAPH_PROFILE section index.276  uint32_t cgProfileSectionIndex = 0;277 278  // MIPS GP0 value defined by this file. This value represents the gp value279  // used to create the relocatable object and required to support280  // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.281  uint32_t mipsGp0 = 0;282 283  // True if the file defines functions compiled with284  // -fsplit-stack. Usually false.285  bool splitStack = false;286 287  // True if the file defines functions compiled with -fsplit-stack,288  // but had one or more functions with the no_split_stack attribute.289  bool someNoSplitStack = false;290 291  void initDwarf();292 293  void initSectionsAndLocalSyms(bool ignoreComdats);294  void postParse();295  void importCmseSymbols();296 297private:298  void initializeSections(bool ignoreComdats,299                          const llvm::object::ELFFile<ELFT> &obj);300  void initializeSymbols(const llvm::object::ELFFile<ELFT> &obj);301  void initializeJustSymbols();302 303  InputSectionBase *getRelocTarget(uint32_t idx, uint32_t info);304  InputSectionBase *createInputSection(uint32_t idx, const Elf_Shdr &sec,305                                       StringRef name);306 307  bool shouldMerge(const Elf_Shdr &sec, StringRef name);308 309  // Each ELF symbol contains a section index which the symbol belongs to.310  // However, because the number of bits dedicated for that is limited, a311  // symbol can directly point to a section only when the section index is312  // equal to or smaller than 65280.313  //314  // If an object file contains more than 65280 sections, the file must315  // contain .symtab_shndx section. The section contains an array of316  // 32-bit integers whose size is the same as the number of symbols.317  // Nth symbol's section index is in the Nth entry of .symtab_shndx.318  //319  // The following variable contains the contents of .symtab_shndx.320  // If the section does not exist (which is common), the array is empty.321  ArrayRef<Elf_Word> shndxTable;322};323 324class BitcodeFile : public InputFile {325public:326  BitcodeFile(Ctx &, MemoryBufferRef m, StringRef archiveName,327              uint64_t offsetInArchive, bool lazy);328  static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }329  void parse();330  void parseLazy();331  void postParse();332  std::unique_ptr<llvm::lto::InputFile> obj;333  std::vector<bool> keptComdats;334};335 336// .so file.337class SharedFile : public ELFFileBase {338public:339  SharedFile(Ctx &, MemoryBufferRef m, StringRef defaultSoName);340 341  // This is actually a vector of Elf_Verdef pointers.342  SmallVector<const void *, 0> verdefs;343 344  // If the output file needs Elf_Verneed data structures for this file, this is345  // a vector of Elf_Vernaux version identifiers that map onto the entries in346  // Verdefs, otherwise it is empty.347  SmallVector<uint32_t, 0> vernauxs;348 349  SmallVector<StringRef, 0> dtNeeded;350  StringRef soName;351 352  static bool classof(const InputFile *f) { return f->kind() == SharedKind; }353 354  template <typename ELFT> void parse();355 356  // Used for --as-needed357  bool isNeeded;358 359  // Non-weak undefined symbols which are not yet resolved when the SO is360  // parsed. Only filled for `--no-allow-shlib-undefined`.361  SmallVector<Symbol *, 0> requiredSymbols;362 363private:364  template <typename ELFT>365  std::vector<uint32_t> parseVerneed(const llvm::object::ELFFile<ELFT> &obj,366                                     const typename ELFT::Shdr *sec);367  template <typename ELFT>368  void parseGnuAndFeatures(const llvm::object::ELFFile<ELFT> &obj);369};370 371class BinaryFile : public InputFile {372public:373  explicit BinaryFile(Ctx &ctx, MemoryBufferRef m)374      : InputFile(ctx, BinaryKind, m) {}375  static bool classof(const InputFile *f) { return f->kind() == BinaryKind; }376  void parse();377};378 379InputFile *createInternalFile(Ctx &, StringRef name);380std::unique_ptr<ELFFileBase> createObjFile(Ctx &, MemoryBufferRef mb,381                                           StringRef archiveName = "",382                                           bool lazy = false);383 384std::string replaceThinLTOSuffix(Ctx &, StringRef path);385 386} // namespace elf387} // namespace lld388 389#endif390