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