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 uint32_t calcNewIndex(const WasmRelocation &reloc) const; 120 uint64_t calcNewValue(const WasmRelocation &reloc, uint64_t tombstone, 121 const InputChunk *chunk) const; 122 uint64_t calcNewAddend(const WasmRelocation &reloc) const; 123 Symbol *getSymbol(const WasmRelocation &reloc) const { 124 return symbols[reloc.Index]; 125 }; 126 127 const WasmSection *codeSection = nullptr; 128 const WasmSection *dataSection = nullptr; 129 130 // Maps input type indices to output type indices 131 std::vector<uint32_t> typeMap; 132 std::vector<bool> typeIsUsed; 133 // Maps function indices to table indices 134 std::vector<uint32_t> tableEntries; 135 std::vector<uint32_t> tableEntriesRel; 136 std::vector<bool> keptComdats; 137 std::vector<InputChunk *> segments; 138 std::vector<InputFunction *> functions; 139 std::vector<InputGlobal *> globals; 140 std::vector<InputTag *> tags; 141 std::vector<InputTable *> tables; 142 std::vector<InputChunk *> customSections; 143 llvm::DenseMap<uint32_t, InputChunk *> customSectionsByIndex; 144 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 TagSymbol *getTagSymbol(uint32_t index) const; 151 TableSymbol *getTableSymbol(uint32_t index) const; 152 153 private: 154 Symbol *createDefined(const WasmSymbol &sym); 155 Symbol *createUndefined(const WasmSymbol &sym, bool isCalledDirectly); 156 157 bool isExcludedByComdat(const InputChunk *chunk) const; 158 void addLegacyIndirectFunctionTableIfNeeded(uint32_t tableSymbolCount); 159 160 std::unique_ptr<WasmObjectFile> wasmObj; 161 }; 162 163 // .so file. 164 class SharedFile : public InputFile { 165 public: 166 explicit SharedFile(MemoryBufferRef m) : InputFile(SharedKind, m) {} 167 static bool classof(const InputFile *f) { return f->kind() == SharedKind; } 168 }; 169 170 // .bc file 171 class BitcodeFile : public InputFile { 172 public: 173 BitcodeFile(MemoryBufferRef m, StringRef archiveName, 174 uint64_t offsetInArchive); 175 static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; } 176 177 void parse(); 178 std::unique_ptr<llvm::lto::InputFile> obj; 179 180 // Set to true once LTO is complete in order prevent further bitcode objects 181 // being added. 182 static bool doneLTO; 183 }; 184 185 inline bool isBitcode(MemoryBufferRef mb) { 186 return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode; 187 } 188 189 // Will report a fatal() error if the input buffer is not a valid bitcode 190 // or wasm object file. 191 InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "", 192 uint64_t offsetInArchive = 0); 193 194 // Opens a given file. 195 llvm::Optional<MemoryBufferRef> readFile(StringRef path); 196 197 } // namespace wasm 198 199 std::string toString(const wasm::InputFile *file); 200 201 } // namespace lld 202 203 #endif 204