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