1 //===- WasmObjectFile.h - Wasm object file implementation -------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file declares the WasmObjectFile class, which implements the ObjectFile 11 // interface for Wasm files. 12 // 13 // See: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md 14 // 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_OBJECT_WASM_H 18 #define LLVM_OBJECT_WASM_H 19 20 #include "llvm/ADT/ArrayRef.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/ADT/StringMap.h" 23 #include "llvm/BinaryFormat/Wasm.h" 24 #include "llvm/Object/Binary.h" 25 #include "llvm/Object/ObjectFile.h" 26 #include "llvm/Support/Error.h" 27 #include "llvm/Support/MemoryBuffer.h" 28 #include <cstddef> 29 #include <cstdint> 30 #include <vector> 31 32 namespace llvm { 33 namespace object { 34 35 class WasmSymbol { 36 public: 37 enum class SymbolType { 38 FUNCTION_IMPORT, 39 FUNCTION_EXPORT, 40 GLOBAL_IMPORT, 41 GLOBAL_EXPORT, 42 DEBUG_FUNCTION_NAME, 43 }; 44 45 WasmSymbol(StringRef Name, SymbolType Type, uint32_t Section, 46 uint32_t ElementIndex, uint32_t ImportIndex = 0) 47 : Name(Name), Type(Type), Section(Section), ElementIndex(ElementIndex), 48 ImportIndex(ImportIndex) {} 49 50 StringRef Name; 51 SymbolType Type; 52 uint32_t Section; 53 uint32_t Flags = 0; 54 55 // Index into either the function or global index space. 56 uint32_t ElementIndex; 57 58 // For imports, the index into the import table 59 uint32_t ImportIndex; 60 61 bool isFunction() const { 62 return Type == WasmSymbol::SymbolType::FUNCTION_IMPORT || 63 Type == WasmSymbol::SymbolType::FUNCTION_EXPORT || 64 Type == WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME; 65 } 66 67 68 bool isWeak() const { 69 return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK; 70 } 71 72 bool isGlobal() const { 73 return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL; 74 } 75 76 bool isLocal() const { 77 return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL; 78 } 79 80 unsigned getBinding() const { 81 return Flags & wasm::WASM_SYMBOL_BINDING_MASK; 82 } 83 84 void print(raw_ostream &Out) const { 85 Out << "Name=" << Name << ", Type=" << static_cast<int>(Type) 86 << ", Flags=" << Flags << " ElemIndex=" << ElementIndex 87 << ", ImportIndex=" << ImportIndex; 88 } 89 90 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 91 LLVM_DUMP_METHOD void dump() const { print(dbgs()); } 92 #endif 93 }; 94 95 struct WasmSection { 96 WasmSection() = default; 97 98 uint32_t Type = 0; // Section type (See below) 99 uint32_t Offset = 0; // Offset with in the file 100 StringRef Name; // Section name (User-defined sections only) 101 ArrayRef<uint8_t> Content; // Section content 102 std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section 103 }; 104 105 struct WasmSegment { 106 uint32_t SectionOffset; 107 wasm::WasmDataSegment Data; 108 }; 109 110 class WasmObjectFile : public ObjectFile { 111 112 public: 113 WasmObjectFile(MemoryBufferRef Object, Error &Err); 114 115 const wasm::WasmObjectHeader &getHeader() const; 116 const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const; 117 const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const; 118 const WasmSection &getWasmSection(const SectionRef &Section) const; 119 const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const; 120 121 static bool classof(const Binary *v) { return v->isWasm(); } 122 123 const std::vector<wasm::WasmSignature>& types() const { return Signatures; } 124 const std::vector<uint32_t>& functionTypes() const { return FunctionTypes; } 125 const std::vector<wasm::WasmImport>& imports() const { return Imports; } 126 const std::vector<wasm::WasmTable>& tables() const { return Tables; } 127 const std::vector<wasm::WasmLimits>& memories() const { return Memories; } 128 const std::vector<wasm::WasmGlobal>& globals() const { return Globals; } 129 const std::vector<wasm::WasmExport>& exports() const { return Exports; } 130 const wasm::WasmLinkingData& linkingData() const { return LinkingData; } 131 132 uint32_t getNumberOfSymbols() const { 133 return Symbols.size(); 134 } 135 136 const std::vector<wasm::WasmElemSegment>& elements() const { 137 return ElemSegments; 138 } 139 140 const std::vector<WasmSegment>& dataSegments() const { 141 return DataSegments; 142 } 143 144 const std::vector<wasm::WasmFunction>& functions() const { return Functions; } 145 const ArrayRef<uint8_t>& code() const { return CodeSection; } 146 uint32_t startFunction() const { return StartFunction; } 147 148 void moveSymbolNext(DataRefImpl &Symb) const override; 149 150 uint32_t getSymbolFlags(DataRefImpl Symb) const override; 151 152 basic_symbol_iterator symbol_begin() const override; 153 154 basic_symbol_iterator symbol_end() const override; 155 Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; 156 157 Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; 158 uint64_t getWasmSymbolValue(const WasmSymbol& Sym) const; 159 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; 160 uint32_t getSymbolAlignment(DataRefImpl Symb) const override; 161 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; 162 Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; 163 Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; 164 165 // Overrides from SectionRef. 166 void moveSectionNext(DataRefImpl &Sec) const override; 167 std::error_code getSectionName(DataRefImpl Sec, 168 StringRef &Res) const override; 169 uint64_t getSectionAddress(DataRefImpl Sec) const override; 170 uint64_t getSectionIndex(DataRefImpl Sec) const override; 171 uint64_t getSectionSize(DataRefImpl Sec) const override; 172 std::error_code getSectionContents(DataRefImpl Sec, 173 StringRef &Res) const override; 174 uint64_t getSectionAlignment(DataRefImpl Sec) const override; 175 bool isSectionCompressed(DataRefImpl Sec) const override; 176 bool isSectionText(DataRefImpl Sec) const override; 177 bool isSectionData(DataRefImpl Sec) const override; 178 bool isSectionBSS(DataRefImpl Sec) const override; 179 bool isSectionVirtual(DataRefImpl Sec) const override; 180 bool isSectionBitcode(DataRefImpl Sec) const override; 181 relocation_iterator section_rel_begin(DataRefImpl Sec) const override; 182 relocation_iterator section_rel_end(DataRefImpl Sec) const override; 183 184 // Overrides from RelocationRef. 185 void moveRelocationNext(DataRefImpl &Rel) const override; 186 uint64_t getRelocationOffset(DataRefImpl Rel) const override; 187 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; 188 uint64_t getRelocationType(DataRefImpl Rel) const override; 189 void getRelocationTypeName(DataRefImpl Rel, 190 SmallVectorImpl<char> &Result) const override; 191 192 section_iterator section_begin() const override; 193 section_iterator section_end() const override; 194 uint8_t getBytesInAddress() const override; 195 StringRef getFileFormatName() const override; 196 unsigned getArch() const override; 197 SubtargetFeatures getFeatures() const override; 198 bool isRelocatableObject() const override; 199 200 private: 201 const WasmSection &getWasmSection(DataRefImpl Ref) const; 202 const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const; 203 204 WasmSection* findCustomSectionByName(StringRef Name); 205 WasmSection* findSectionByType(uint32_t Type); 206 207 const uint8_t *getPtr(size_t Offset) const; 208 Error parseSection(WasmSection &Sec); 209 Error parseCustomSection(WasmSection &Sec, const uint8_t *Ptr, 210 const uint8_t *End); 211 212 // Standard section types 213 Error parseTypeSection(const uint8_t *Ptr, const uint8_t *End); 214 Error parseImportSection(const uint8_t *Ptr, const uint8_t *End); 215 Error parseFunctionSection(const uint8_t *Ptr, const uint8_t *End); 216 Error parseTableSection(const uint8_t *Ptr, const uint8_t *End); 217 Error parseMemorySection(const uint8_t *Ptr, const uint8_t *End); 218 Error parseGlobalSection(const uint8_t *Ptr, const uint8_t *End); 219 Error parseExportSection(const uint8_t *Ptr, const uint8_t *End); 220 Error parseStartSection(const uint8_t *Ptr, const uint8_t *End); 221 Error parseElemSection(const uint8_t *Ptr, const uint8_t *End); 222 Error parseCodeSection(const uint8_t *Ptr, const uint8_t *End); 223 Error parseDataSection(const uint8_t *Ptr, const uint8_t *End); 224 225 // Custom section types 226 Error parseNameSection(const uint8_t *Ptr, const uint8_t *End); 227 Error parseLinkingSection(const uint8_t *Ptr, const uint8_t *End); 228 Error parseRelocSection(StringRef Name, const uint8_t *Ptr, 229 const uint8_t *End); 230 231 void populateSymbolTable(); 232 233 wasm::WasmObjectHeader Header; 234 std::vector<WasmSection> Sections; 235 std::vector<wasm::WasmSignature> Signatures; 236 std::vector<uint32_t> FunctionTypes; 237 std::vector<wasm::WasmTable> Tables; 238 std::vector<wasm::WasmLimits> Memories; 239 std::vector<wasm::WasmGlobal> Globals; 240 std::vector<wasm::WasmImport> Imports; 241 std::vector<wasm::WasmExport> Exports; 242 std::vector<wasm::WasmElemSegment> ElemSegments; 243 std::vector<WasmSegment> DataSegments; 244 std::vector<wasm::WasmFunction> Functions; 245 std::vector<WasmSymbol> Symbols; 246 ArrayRef<uint8_t> CodeSection; 247 uint32_t StartFunction = -1; 248 bool HasLinkingSection = false; 249 wasm::WasmLinkingData LinkingData; 250 uint32_t NumImportedGlobals = 0; 251 uint32_t NumImportedFunctions = 0; 252 uint32_t ImportSection = 0; 253 uint32_t ExportSection = 0; 254 255 StringMap<uint32_t> SymbolMap; 256 }; 257 258 } // end namespace object 259 260 inline raw_ostream &operator<<(raw_ostream &OS, 261 const object::WasmSymbol &Sym) { 262 Sym.print(OS); 263 return OS; 264 } 265 266 } // end namespace llvm 267 268 #endif // LLVM_OBJECT_WASM_H 269