• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLD_WASM_INPUT_FILES_H
10 #define LLD_WASM_INPUT_FILES_H
11 
12 #include "Symbols.h"
13 #include "lld/Common/LLVM.h"
14 #include "llvm/ADT/DenseMap.h"
15 #include "llvm/ADT/DenseSet.h"
16 #include "llvm/ADT/Triple.h"
17 #include "llvm/LTO/LTO.h"
18 #include "llvm/Object/Archive.h"
19 #include "llvm/Object/Wasm.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include <vector>
22 
23 namespace llvm {
24 class TarWriter;
25 }
26 
27 namespace lld {
28 namespace wasm {
29 
30 class InputChunk;
31 class InputFunction;
32 class InputSegment;
33 class InputGlobal;
34 class InputEvent;
35 class InputSection;
36 
37 // If --reproduce option is given, all input files are written
38 // to this tar archive.
39 extern std::unique_ptr<llvm::TarWriter> tar;
40 
41 class InputFile {
42 public:
43   enum Kind {
44     ObjectKind,
45     SharedKind,
46     ArchiveKind,
47     BitcodeKind,
48   };
49 
~InputFile()50   virtual ~InputFile() {}
51 
52   // Returns the filename.
getName()53   StringRef getName() const { return mb.getBufferIdentifier(); }
54 
kind()55   Kind kind() const { return fileKind; }
56 
57   // An archive file name if this file is created from an archive.
58   std::string archiveName;
59 
getSymbols()60   ArrayRef<Symbol *> getSymbols() const { return symbols; }
61 
getMutableSymbols()62   MutableArrayRef<Symbol *> getMutableSymbols() { return symbols; }
63 
64   // An InputFile is considered live if any of the symbols defined by it
65   // are live.
markLive()66   void markLive() { live = true; }
isLive()67   bool isLive() const { return live; }
68 
69 protected:
InputFile(Kind k,MemoryBufferRef m)70   InputFile(Kind k, MemoryBufferRef m)
71       : mb(m), fileKind(k), live(!config->gcSections) {}
72 
73   void checkArch(llvm::Triple::ArchType arch) const;
74 
75   MemoryBufferRef mb;
76 
77   // List of all symbols referenced or defined by this file.
78   std::vector<Symbol *> symbols;
79 
80 private:
81   const Kind fileKind;
82   bool live;
83 };
84 
85 // .a file (ar archive)
86 class ArchiveFile : public InputFile {
87 public:
ArchiveFile(MemoryBufferRef m)88   explicit ArchiveFile(MemoryBufferRef m) : InputFile(ArchiveKind, m) {}
classof(const InputFile * f)89   static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }
90 
91   void addMember(const llvm::object::Archive::Symbol *sym);
92 
93   void parse();
94 
95 private:
96   std::unique_ptr<llvm::object::Archive> file;
97   llvm::DenseSet<uint64_t> seen;
98 };
99 
100 // .o file (wasm object file)
101 class ObjFile : public InputFile {
102 public:
ObjFile(MemoryBufferRef m,StringRef archiveName)103   explicit ObjFile(MemoryBufferRef m, StringRef archiveName)
104       : InputFile(ObjectKind, m) {
105     this->archiveName = std::string(archiveName);
106 
107     // If this isn't part of an archive, it's eagerly linked, so mark it live.
108     if (archiveName.empty())
109       markLive();
110   }
classof(const InputFile * f)111   static bool classof(const InputFile *f) { return f->kind() == ObjectKind; }
112 
113   void parse(bool ignoreComdats = false);
114 
115   // Returns the underlying wasm file.
getWasmObj()116   const WasmObjectFile *getWasmObj() const { return wasmObj.get(); }
117 
118   void dumpInfo() const;
119 
120   uint32_t calcNewIndex(const WasmRelocation &reloc) const;
121   uint64_t calcNewValue(const WasmRelocation &reloc, uint64_t tombstone) const;
122   uint64_t calcNewAddend(const WasmRelocation &reloc) const;
123   uint64_t calcExpectedValue(const WasmRelocation &reloc) const;
getSymbol(const WasmRelocation & reloc)124   Symbol *getSymbol(const WasmRelocation &reloc) const {
125     return symbols[reloc.Index];
126   };
127 
128   const WasmSection *codeSection = nullptr;
129   const WasmSection *dataSection = nullptr;
130 
131   // Maps input type indices to output type indices
132   std::vector<uint32_t> typeMap;
133   std::vector<bool> typeIsUsed;
134   // Maps function indices to table indices
135   std::vector<uint32_t> tableEntries;
136   std::vector<uint32_t> tableEntriesRel;
137   std::vector<bool> keptComdats;
138   std::vector<InputSegment *> segments;
139   std::vector<InputFunction *> functions;
140   std::vector<InputGlobal *> globals;
141   std::vector<InputEvent *> events;
142   std::vector<InputSection *> customSections;
143   llvm::DenseMap<uint32_t, InputSection *> customSectionsByIndex;
144 
getSymbol(uint32_t index)145   Symbol *getSymbol(uint32_t index) const { return symbols[index]; }
146   FunctionSymbol *getFunctionSymbol(uint32_t index) const;
147   DataSymbol *getDataSymbol(uint32_t index) const;
148   GlobalSymbol *getGlobalSymbol(uint32_t index) const;
149   SectionSymbol *getSectionSymbol(uint32_t index) const;
150   EventSymbol *getEventSymbol(uint32_t index) const;
151 
152 private:
153   Symbol *createDefined(const WasmSymbol &sym);
154   Symbol *createUndefined(const WasmSymbol &sym, bool isCalledDirectly);
155 
156   bool isExcludedByComdat(InputChunk *chunk) const;
157 
158   std::unique_ptr<WasmObjectFile> wasmObj;
159 };
160 
161 // .so file.
162 class SharedFile : public InputFile {
163 public:
SharedFile(MemoryBufferRef m)164   explicit SharedFile(MemoryBufferRef m) : InputFile(SharedKind, m) {}
classof(const InputFile * f)165   static bool classof(const InputFile *f) { return f->kind() == SharedKind; }
166 };
167 
168 // .bc file
169 class BitcodeFile : public InputFile {
170 public:
BitcodeFile(MemoryBufferRef m,StringRef archiveName)171   explicit BitcodeFile(MemoryBufferRef m, StringRef archiveName)
172       : InputFile(BitcodeKind, m) {
173     this->archiveName = std::string(archiveName);
174 
175     // If this isn't part of an archive, it's eagerly linked, so mark it live.
176     if (archiveName.empty())
177       markLive();
178   }
classof(const InputFile * f)179   static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
180 
181   void parse();
182   std::unique_ptr<llvm::lto::InputFile> obj;
183 
184   // Set to true once LTO is complete in order prevent further bitcode objects
185   // being added.
186   static bool doneLTO;
187 };
188 
isBitcode(MemoryBufferRef mb)189 inline bool isBitcode(MemoryBufferRef mb) {
190   return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode;
191 }
192 
193 // Will report a fatal() error if the input buffer is not a valid bitcode
194 // or wasm object file.
195 InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "");
196 
197 // Opens a given file.
198 llvm::Optional<MemoryBufferRef> readFile(StringRef path);
199 
200 } // namespace wasm
201 
202 std::string toString(const wasm::InputFile *file);
203 
204 } // namespace lld
205 
206 #endif
207