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 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 ArchiveKind, 48 BitcodeKind, 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 protected: 71 InputFile(Kind k, MemoryBufferRef m) 72 : mb(m), fileKind(k), live(!config->gcSections) {} 73 74 void checkArch(llvm::Triple::ArchType arch) const; 75 76 MemoryBufferRef mb; 77 78 // List of all symbols referenced or defined by this file. 79 std::vector<Symbol *> symbols; 80 81 private: 82 const Kind fileKind; 83 bool live; 84 }; 85 86 // .a file (ar archive) 87 class ArchiveFile : public InputFile { 88 public: 89 explicit ArchiveFile(MemoryBufferRef m) : InputFile(ArchiveKind, m) {} 90 static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; } 91 92 void addMember(const llvm::object::Archive::Symbol *sym); 93 94 void parse(); 95 96 private: 97 std::unique_ptr<llvm::object::Archive> file; 98 llvm::DenseSet<uint64_t> seen; 99 }; 100 101 // .o file (wasm object file) 102 class ObjFile : public InputFile { 103 public: 104 explicit ObjFile(MemoryBufferRef m, StringRef archiveName) 105 : InputFile(ObjectKind, m) { 106 this->archiveName = std::string(archiveName); 107 108 // If this isn't part of an archive, it's eagerly linked, so mark it live. 109 if (archiveName.empty()) 110 markLive(); 111 } 112 static bool classof(const InputFile *f) { return f->kind() == ObjectKind; } 113 114 void parse(bool ignoreComdats = false); 115 116 // Returns the underlying wasm file. 117 const WasmObjectFile *getWasmObj() const { return wasmObj.get(); } 118 119 void dumpInfo() const; 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 uint64_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(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 explicit BitcodeFile(MemoryBufferRef m, StringRef archiveName) 176 : InputFile(BitcodeKind, m) { 177 this->archiveName = std::string(archiveName); 178 179 // If this isn't part of an archive, it's eagerly linked, so mark it live. 180 if (archiveName.empty()) 181 markLive(); 182 } 183 static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; } 184 185 void parse(); 186 std::unique_ptr<llvm::lto::InputFile> obj; 187 188 // Set to true once LTO is complete in order prevent further bitcode objects 189 // being added. 190 static bool doneLTO; 191 }; 192 193 inline bool isBitcode(MemoryBufferRef mb) { 194 return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode; 195 } 196 197 // Will report a fatal() error if the input buffer is not a valid bitcode 198 // or wasm object file. 199 InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = ""); 200 201 // Opens a given file. 202 llvm::Optional<MemoryBufferRef> readFile(StringRef path); 203 204 } // namespace wasm 205 206 std::string toString(const wasm::InputFile *file); 207 208 } // namespace lld 209 210 #endif 211