xref: /llvm-project-15.0.7/lld/ELF/InputFiles.h (revision 928c8254)
1 //===- InputFiles.h ---------------------------------------------*- C++ -*-===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLD_ELF_INPUT_FILES_H
11 #define LLD_ELF_INPUT_FILES_H
12 
13 #include "Config.h"
14 #include "InputSection.h"
15 #include "Error.h"
16 #include "Symbols.h"
17 
18 #include "lld/Core/LLVM.h"
19 #include "llvm/ADT/DenseSet.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/IR/Comdat.h"
22 #include "llvm/Object/Archive.h"
23 #include "llvm/Object/ELF.h"
24 #include "llvm/Object/IRObjectFile.h"
25 #include "llvm/Support/StringSaver.h"
26 
27 #include <map>
28 
29 namespace lld {
30 namespace elf {
31 
32 using llvm::object::Archive;
33 
34 class InputFile;
35 class Lazy;
36 class SymbolBody;
37 
38 // The root class of input files.
39 class InputFile {
40 public:
41   enum Kind {
42     ObjectKind,
43     SharedKind,
44     LazyObjectKind,
45     ArchiveKind,
46     BitcodeKind,
47   };
48 
49   Kind kind() const { return FileKind; }
50 
51   StringRef getName() const { return MB.getBufferIdentifier(); }
52   MemoryBufferRef MB;
53 
54   // Filename of .a which contained this file. If this file was
55   // not in an archive file, it is the empty string. We use this
56   // string for creating error messages.
57   StringRef ArchiveName;
58 
59 protected:
60   InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
61 
62 private:
63   const Kind FileKind;
64 };
65 
66 template <typename ELFT> class ELFFileBase : public InputFile {
67 public:
68   typedef typename ELFT::Shdr Elf_Shdr;
69   typedef typename ELFT::Sym Elf_Sym;
70   typedef typename ELFT::Word Elf_Word;
71   typedef typename ELFT::SymRange Elf_Sym_Range;
72 
73   ELFFileBase(Kind K, MemoryBufferRef M);
74   static bool classof(const InputFile *F) {
75     Kind K = F->kind();
76     return K == ObjectKind || K == SharedKind;
77   }
78 
79   static ELFKind getELFKind();
80   const llvm::object::ELFFile<ELFT> &getObj() const { return ELFObj; }
81   llvm::object::ELFFile<ELFT> &getObj() { return ELFObj; }
82 
83   uint16_t getEMachine() const { return getObj().getHeader()->e_machine; }
84   uint8_t getOSABI() const {
85     return getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI];
86   }
87 
88   StringRef getStringTable() const { return StringTable; }
89 
90   uint32_t getSectionIndex(const Elf_Sym &Sym) const;
91 
92 protected:
93   llvm::object::ELFFile<ELFT> ELFObj;
94   const Elf_Shdr *Symtab = nullptr;
95   ArrayRef<Elf_Word> SymtabSHNDX;
96   StringRef StringTable;
97   void initStringTable();
98   Elf_Sym_Range getElfSymbols(bool OnlyGlobals);
99 };
100 
101 // .o file.
102 template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> {
103   typedef ELFFileBase<ELFT> Base;
104   typedef typename ELFT::Sym Elf_Sym;
105   typedef typename ELFT::Shdr Elf_Shdr;
106   typedef typename ELFT::SymRange Elf_Sym_Range;
107   typedef typename ELFT::Word Elf_Word;
108   typedef typename ELFT::uint uintX_t;
109 
110   StringRef getShtGroupSignature(const Elf_Shdr &Sec);
111   ArrayRef<Elf_Word> getShtGroupEntries(const Elf_Shdr &Sec);
112 
113 public:
114   static bool classof(const InputFile *F) {
115     return F->kind() == Base::ObjectKind;
116   }
117 
118   ArrayRef<SymbolBody *> getSymbols();
119   ArrayRef<SymbolBody *> getLocalSymbols();
120   ArrayRef<SymbolBody *> getNonLocalSymbols();
121 
122   explicit ObjectFile(MemoryBufferRef M);
123   void parse(llvm::DenseSet<StringRef> &ComdatGroups);
124 
125   ArrayRef<InputSectionBase<ELFT> *> getSections() const { return Sections; }
126   InputSectionBase<ELFT> *getSection(const Elf_Sym &Sym) const;
127 
128   SymbolBody &getSymbolBody(uint32_t SymbolIndex) const {
129     return SymbolBodies[SymbolIndex]->repl();
130   }
131 
132   template <typename RelT> SymbolBody &getRelocTargetSym(const RelT &Rel) const {
133     uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL);
134     return getSymbolBody(SymIndex);
135   }
136 
137   const Elf_Shdr *getSymbolTable() const { return this->Symtab; };
138 
139   // Get MIPS GP0 value defined by this file. This value represents the gp value
140   // used to create the relocatable object and required to support
141   // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
142   uint32_t getMipsGp0() const;
143 
144   // The number is the offset in the string table. It will be used as the
145   // st_name of the symbol.
146   std::vector<std::pair<const DefinedRegular<ELFT> *, unsigned>> KeptLocalSyms;
147 
148 private:
149   void initializeSections(llvm::DenseSet<StringRef> &ComdatGroups);
150   void initializeSymbols();
151   InputSectionBase<ELFT> *getRelocTarget(const Elf_Shdr &Sec);
152   InputSectionBase<ELFT> *createInputSection(const Elf_Shdr &Sec);
153 
154   SymbolBody *createSymbolBody(const Elf_Sym *Sym);
155 
156   // List of all sections defined by this file.
157   std::vector<InputSectionBase<ELFT> *> Sections;
158 
159   // List of all symbols referenced or defined by this file.
160   std::vector<SymbolBody *> SymbolBodies;
161 
162   // MIPS .reginfo section defined by this file.
163   std::unique_ptr<MipsReginfoInputSection<ELFT>> MipsReginfo;
164 
165   llvm::BumpPtrAllocator Alloc;
166   llvm::SpecificBumpPtrAllocator<InputSection<ELFT>> IAlloc;
167   llvm::SpecificBumpPtrAllocator<MergeInputSection<ELFT>> MAlloc;
168   llvm::SpecificBumpPtrAllocator<EHInputSection<ELFT>> EHAlloc;
169 };
170 
171 // LazyObjectFile is analogous to ArchiveFile in the sense that
172 // the file contains lazy symbols. The difference is that
173 // LazyObjectFile wraps a single file instead of multiple files.
174 //
175 // This class is used for --start-lib and --end-lib options which
176 // instruct the linker to link object files between them with the
177 // archive file semantics.
178 class LazyObjectFile : public InputFile {
179 public:
180   explicit LazyObjectFile(MemoryBufferRef M) : InputFile(LazyObjectKind, M) {}
181 
182   static bool classof(const InputFile *F) {
183     return F->kind() == LazyObjectKind;
184   }
185 
186   void parse();
187 
188   llvm::MutableArrayRef<LazyObject> getLazySymbols() { return LazySymbols; }
189 
190 private:
191   std::vector<StringRef> getSymbols();
192   template <class ELFT> std::vector<StringRef> getElfSymbols();
193   std::vector<StringRef> getBitcodeSymbols();
194 
195   llvm::BumpPtrAllocator Alloc;
196   llvm::StringSaver Saver{Alloc};
197   std::vector<LazyObject> LazySymbols;
198 };
199 
200 // An ArchiveFile object represents a .a file.
201 class ArchiveFile : public InputFile {
202 public:
203   explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
204   static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
205   void parse();
206 
207   // Returns a memory buffer for a given symbol. An empty memory buffer
208   // is returned if we have already returned the same memory buffer.
209   // (So that we don't instantiate same members more than once.)
210   MemoryBufferRef getMember(const Archive::Symbol *Sym);
211 
212   llvm::MutableArrayRef<LazyArchive> getLazySymbols() { return LazySymbols; }
213 
214 private:
215   std::unique_ptr<Archive> File;
216   std::vector<LazyArchive> LazySymbols;
217   llvm::DenseSet<uint64_t> Seen;
218 };
219 
220 class BitcodeFile : public InputFile {
221 public:
222   explicit BitcodeFile(MemoryBufferRef M);
223   static bool classof(const InputFile *F);
224   void parse(llvm::DenseSet<StringRef> &ComdatGroups);
225   ArrayRef<SymbolBody *> getSymbols() { return SymbolBodies; }
226   static bool shouldSkip(const llvm::object::BasicSymbolRef &Sym);
227 
228 private:
229   std::vector<SymbolBody *> SymbolBodies;
230   llvm::BumpPtrAllocator Alloc;
231   llvm::StringSaver Saver{Alloc};
232   SymbolBody *
233   createSymbolBody(const llvm::DenseSet<const llvm::Comdat *> &KeptComdats,
234                    const llvm::object::IRObjectFile &Obj,
235                    const llvm::object::BasicSymbolRef &Sym);
236   SymbolBody *
237   createBody(const llvm::DenseSet<const llvm::Comdat *> &KeptComdats,
238              const llvm::object::IRObjectFile &Obj,
239              const llvm::object::BasicSymbolRef &Sym,
240              const llvm::GlobalValue *GV);
241 };
242 
243 // .so file.
244 template <class ELFT> class SharedFile : public ELFFileBase<ELFT> {
245   typedef ELFFileBase<ELFT> Base;
246   typedef typename ELFT::Shdr Elf_Shdr;
247   typedef typename ELFT::Sym Elf_Sym;
248   typedef typename ELFT::Word Elf_Word;
249   typedef typename ELFT::SymRange Elf_Sym_Range;
250   typedef typename ELFT::Versym Elf_Versym;
251   typedef typename ELFT::Verdef Elf_Verdef;
252 
253   std::vector<SharedSymbol<ELFT>> SymbolBodies;
254   std::vector<StringRef> Undefs;
255   StringRef SoName;
256   const Elf_Shdr *VersymSec = nullptr;
257   const Elf_Shdr *VerdefSec = nullptr;
258 
259 public:
260   StringRef getSoName() const { return SoName; }
261   llvm::MutableArrayRef<SharedSymbol<ELFT>> getSharedSymbols() {
262     return SymbolBodies;
263   }
264   const Elf_Shdr *getSection(const Elf_Sym &Sym) const;
265   llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; }
266 
267   static bool classof(const InputFile *F) {
268     return F->kind() == Base::SharedKind;
269   }
270 
271   explicit SharedFile(MemoryBufferRef M);
272 
273   void parseSoName();
274   void parseRest();
275   std::vector<const Elf_Verdef *> parseVerdefs(const Elf_Versym *&Versym);
276 
277   struct NeededVer {
278     // The string table offset of the version name in the output file.
279     size_t StrTab;
280 
281     // The version identifier for this version name.
282     uint16_t Index;
283   };
284 
285   // Mapping from Elf_Verdef data structures to information about Elf_Vernaux
286   // data structures in the output file.
287   std::map<const Elf_Verdef *, NeededVer> VerdefMap;
288 
289   // Used for --as-needed
290   bool AsNeeded = false;
291   bool IsUsed = false;
292   bool isNeeded() const { return !AsNeeded || IsUsed; }
293 };
294 
295 std::unique_ptr<InputFile> createObjectFile(MemoryBufferRef MB,
296                                             StringRef ArchiveName = "");
297 std::unique_ptr<InputFile> createSharedFile(MemoryBufferRef MB);
298 
299 } // namespace elf
300 } // namespace lld
301 
302 #endif
303