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/LTO/LTO.h" 17 #include "llvm/Object/Wasm.h" 18 #include "llvm/Support/MemoryBuffer.h" 19 #include "llvm/TargetParser/Triple.h" 20 #include <optional> 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 InputTag; 35 class InputTable; 36 class InputSection; 37 38 // If --reproduce option is given, all input files are written 39 // to this tar archive. 40 extern std::unique_ptr<llvm::TarWriter> tar; 41 42 class InputFile { 43 public: 44 enum Kind { 45 ObjectKind, 46 SharedKind, 47 BitcodeKind, 48 StubKind, 49 }; 50 51 virtual ~InputFile() {} 52 53 // Returns the filename. 54 StringRef getName() const { return mb.getBufferIdentifier(); } 55 56 Kind kind() const { return fileKind; } 57 58 // An archive file name if this file is created from an archive. 59 std::string archiveName; 60 61 ArrayRef<Symbol *> getSymbols() const { return symbols; } 62 63 MutableArrayRef<Symbol *> getMutableSymbols() { return symbols; } 64 65 // An InputFile is considered live if any of the symbols defined by it 66 // are live. 67 void markLive() { live = true; } 68 bool isLive() const { return live; } 69 70 // True if this is a relocatable object file/bitcode file in an ar archive 71 // or between --start-lib and --end-lib. 72 bool lazy = false; 73 74 protected: 75 InputFile(Kind k, MemoryBufferRef m) 76 : mb(m), fileKind(k), live(!ctx.arg.gcSections) {} 77 78 void checkArch(llvm::Triple::ArchType arch) const; 79 80 MemoryBufferRef mb; 81 82 // List of all symbols referenced or defined by this file. 83 std::vector<Symbol *> symbols; 84 85 private: 86 const Kind fileKind; 87 bool live; 88 }; 89 90 class WasmFileBase : public InputFile { 91 public: 92 explicit WasmFileBase(Kind k, MemoryBufferRef m); 93 94 // Returns the underlying wasm file. 95 const WasmObjectFile *getWasmObj() const { return wasmObj.get(); } 96 97 protected: 98 std::unique_ptr<WasmObjectFile> wasmObj; 99 }; 100 101 // .o file (wasm object file) 102 class ObjFile : public WasmFileBase { 103 public: 104 ObjFile(MemoryBufferRef m, StringRef archiveName, bool lazy = false); 105 static bool classof(const InputFile *f) { return f->kind() == ObjectKind; } 106 107 void parse(bool ignoreComdats = false); 108 void parseLazy(); 109 110 uint32_t calcNewIndex(const WasmRelocation &reloc) const; 111 uint64_t calcNewValue(const WasmRelocation &reloc, uint64_t tombstone, 112 const InputChunk *chunk) const; 113 int64_t calcNewAddend(const WasmRelocation &reloc) const; 114 Symbol *getSymbol(const WasmRelocation &reloc) const { 115 return symbols[reloc.Index]; 116 }; 117 118 const WasmSection *codeSection = nullptr; 119 const WasmSection *dataSection = nullptr; 120 121 // Maps input type indices to output type indices 122 std::vector<uint32_t> typeMap; 123 std::vector<bool> typeIsUsed; 124 // Maps function indices to table indices 125 std::vector<uint32_t> tableEntries; 126 std::vector<uint32_t> tableEntriesRel; 127 std::vector<bool> keptComdats; 128 std::vector<InputChunk *> segments; 129 std::vector<InputFunction *> functions; 130 std::vector<InputGlobal *> globals; 131 std::vector<InputTag *> tags; 132 std::vector<InputTable *> tables; 133 std::vector<InputChunk *> customSections; 134 llvm::DenseMap<uint32_t, InputChunk *> customSectionsByIndex; 135 136 Symbol *getSymbol(uint32_t index) const { return symbols[index]; } 137 FunctionSymbol *getFunctionSymbol(uint32_t index) const; 138 DataSymbol *getDataSymbol(uint32_t index) const; 139 GlobalSymbol *getGlobalSymbol(uint32_t index) const; 140 SectionSymbol *getSectionSymbol(uint32_t index) const; 141 TagSymbol *getTagSymbol(uint32_t index) const; 142 TableSymbol *getTableSymbol(uint32_t index) const; 143 144 private: 145 Symbol *createDefined(const WasmSymbol &sym); 146 Symbol *createUndefined(const WasmSymbol &sym, bool isCalledDirectly); 147 148 bool isExcludedByComdat(const InputChunk *chunk) const; 149 void addLegacyIndirectFunctionTableIfNeeded(uint32_t tableSymbolCount); 150 }; 151 152 // .so file. 153 class SharedFile : public WasmFileBase { 154 public: 155 explicit SharedFile(MemoryBufferRef m) : WasmFileBase(SharedKind, m) {} 156 157 void parse(); 158 159 static bool classof(const InputFile *f) { return f->kind() == SharedKind; } 160 }; 161 162 // .bc file 163 class BitcodeFile : public InputFile { 164 public: 165 BitcodeFile(MemoryBufferRef m, StringRef archiveName, 166 uint64_t offsetInArchive, bool lazy); 167 static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; } 168 169 void parse(StringRef symName); 170 void parseLazy(); 171 std::unique_ptr<llvm::lto::InputFile> obj; 172 173 // Set to true once LTO is complete in order prevent further bitcode objects 174 // being added. 175 static bool doneLTO; 176 }; 177 178 // Stub library (See docs/WebAssembly.rst) 179 class StubFile : public InputFile { 180 public: 181 explicit StubFile(MemoryBufferRef m) : InputFile(StubKind, m) {} 182 183 static bool classof(const InputFile *f) { return f->kind() == StubKind; } 184 185 void parse(); 186 187 llvm::DenseMap<StringRef, std::vector<StringRef>> symbolDependencies; 188 }; 189 190 // Will report a fatal() error if the input buffer is not a valid bitcode 191 // or wasm object file. 192 InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "", 193 uint64_t offsetInArchive = 0, bool lazy = false); 194 195 // Opens a given file. 196 std::optional<MemoryBufferRef> readFile(StringRef path); 197 198 std::string replaceThinLTOSuffix(StringRef path); 199 200 } // namespace wasm 201 202 std::string toString(const wasm::InputFile *file); 203 204 } // namespace lld 205 206 #endif 207