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/Config/llvm-config.h" 25 #include "llvm/Object/Binary.h" 26 #include "llvm/Object/ObjectFile.h" 27 #include "llvm/Support/Error.h" 28 #include "llvm/Support/MemoryBuffer.h" 29 #include <cstddef> 30 #include <cstdint> 31 #include <vector> 32 33 namespace llvm { 34 namespace object { 35 36 class WasmSymbol { 37 public: WasmSymbol(const wasm::WasmSymbolInfo & Info,const wasm::WasmSignature * FunctionType,const wasm::WasmGlobalType * GlobalType)38 WasmSymbol(const wasm::WasmSymbolInfo &Info, 39 const wasm::WasmSignature *FunctionType, 40 const wasm::WasmGlobalType *GlobalType) 41 : Info(Info), FunctionType(FunctionType), GlobalType(GlobalType) {} 42 43 const wasm::WasmSymbolInfo &Info; 44 const wasm::WasmSignature *FunctionType; 45 const wasm::WasmGlobalType *GlobalType; 46 isTypeFunction()47 bool isTypeFunction() const { 48 return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION; 49 } 50 isTypeData()51 bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; } 52 isTypeGlobal()53 bool isTypeGlobal() const { 54 return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL; 55 } 56 isTypeSection()57 bool isTypeSection() const { 58 return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION; 59 } 60 isDefined()61 bool isDefined() const { return !isUndefined(); } 62 isUndefined()63 bool isUndefined() const { 64 return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0; 65 } 66 isBindingWeak()67 bool isBindingWeak() const { 68 return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK; 69 } 70 isBindingGlobal()71 bool isBindingGlobal() const { 72 return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL; 73 } 74 isBindingLocal()75 bool isBindingLocal() const { 76 return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL; 77 } 78 getBinding()79 unsigned getBinding() const { 80 return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK; 81 } 82 isHidden()83 bool isHidden() const { 84 return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN; 85 } 86 getVisibility()87 unsigned getVisibility() const { 88 return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK; 89 } 90 91 void print(raw_ostream &Out) const; 92 93 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 94 LLVM_DUMP_METHOD void dump() const; 95 #endif 96 }; 97 98 struct WasmSection { 99 WasmSection() = default; 100 101 uint32_t Type = 0; // Section type (See below) 102 uint32_t Offset = 0; // Offset with in the file 103 StringRef Name; // Section name (User-defined sections only) 104 ArrayRef<uint8_t> Content; // Section content 105 std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section 106 }; 107 108 struct WasmSegment { 109 uint32_t SectionOffset; 110 wasm::WasmDataSegment Data; 111 }; 112 113 class WasmObjectFile : public ObjectFile { 114 115 public: 116 WasmObjectFile(MemoryBufferRef Object, Error &Err); 117 118 const wasm::WasmObjectHeader &getHeader() const; 119 const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const; 120 const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const; 121 const WasmSection &getWasmSection(const SectionRef &Section) const; 122 const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const; 123 classof(const Binary * v)124 static bool classof(const Binary *v) { return v->isWasm(); } 125 types()126 ArrayRef<wasm::WasmSignature> types() const { return Signatures; } functionTypes()127 ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; } imports()128 ArrayRef<wasm::WasmImport> imports() const { return Imports; } tables()129 ArrayRef<wasm::WasmTable> tables() const { return Tables; } memories()130 ArrayRef<wasm::WasmLimits> memories() const { return Memories; } globals()131 ArrayRef<wasm::WasmGlobal> globals() const { return Globals; } exports()132 ArrayRef<wasm::WasmExport> exports() const { return Exports; } syms()133 ArrayRef<WasmSymbol> syms() const { return Symbols; } linkingData()134 const wasm::WasmLinkingData& linkingData() const { return LinkingData; } getNumberOfSymbols()135 uint32_t getNumberOfSymbols() const { return Symbols.size(); } elements()136 ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; } dataSegments()137 ArrayRef<WasmSegment> dataSegments() const { return DataSegments; } functions()138 ArrayRef<wasm::WasmFunction> functions() const { return Functions; } debugNames()139 ArrayRef<wasm::WasmFunctionName> debugNames() const { return DebugNames; } startFunction()140 uint32_t startFunction() const { return StartFunction; } getNumImportedGlobals()141 uint32_t getNumImportedGlobals() const { return NumImportedGlobals; } getNumImportedFunctions()142 uint32_t getNumImportedFunctions() const { return NumImportedFunctions; } 143 144 void moveSymbolNext(DataRefImpl &Symb) const override; 145 146 uint32_t getSymbolFlags(DataRefImpl Symb) const override; 147 148 basic_symbol_iterator symbol_begin() const override; 149 150 basic_symbol_iterator symbol_end() const override; 151 Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; 152 153 Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; 154 uint64_t getWasmSymbolValue(const WasmSymbol& Sym) const; 155 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; 156 uint32_t getSymbolAlignment(DataRefImpl Symb) const override; 157 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; 158 Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; 159 Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; 160 161 // Overrides from SectionRef. 162 void moveSectionNext(DataRefImpl &Sec) const override; 163 std::error_code getSectionName(DataRefImpl Sec, 164 StringRef &Res) const override; 165 uint64_t getSectionAddress(DataRefImpl Sec) const override; 166 uint64_t getSectionIndex(DataRefImpl Sec) const override; 167 uint64_t getSectionSize(DataRefImpl Sec) const override; 168 std::error_code getSectionContents(DataRefImpl Sec, 169 StringRef &Res) const override; 170 uint64_t getSectionAlignment(DataRefImpl Sec) const override; 171 bool isSectionCompressed(DataRefImpl Sec) const override; 172 bool isSectionText(DataRefImpl Sec) const override; 173 bool isSectionData(DataRefImpl Sec) const override; 174 bool isSectionBSS(DataRefImpl Sec) const override; 175 bool isSectionVirtual(DataRefImpl Sec) const override; 176 bool isSectionBitcode(DataRefImpl Sec) const override; 177 relocation_iterator section_rel_begin(DataRefImpl Sec) const override; 178 relocation_iterator section_rel_end(DataRefImpl Sec) const override; 179 180 // Overrides from RelocationRef. 181 void moveRelocationNext(DataRefImpl &Rel) const override; 182 uint64_t getRelocationOffset(DataRefImpl Rel) const override; 183 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; 184 uint64_t getRelocationType(DataRefImpl Rel) const override; 185 void getRelocationTypeName(DataRefImpl Rel, 186 SmallVectorImpl<char> &Result) const override; 187 188 section_iterator section_begin() const override; 189 section_iterator section_end() const override; 190 uint8_t getBytesInAddress() const override; 191 StringRef getFileFormatName() const override; 192 Triple::ArchType getArch() const override; 193 SubtargetFeatures getFeatures() const override; 194 bool isRelocatableObject() const override; 195 196 struct ReadContext { 197 const uint8_t *Start; 198 const uint8_t *Ptr; 199 const uint8_t *End; 200 }; 201 202 private: 203 bool isValidFunctionIndex(uint32_t Index) const; 204 bool isDefinedFunctionIndex(uint32_t Index) const; 205 bool isValidGlobalIndex(uint32_t Index) const; 206 bool isDefinedGlobalIndex(uint32_t Index) const; 207 bool isValidFunctionSymbol(uint32_t Index) const; 208 bool isValidGlobalSymbol(uint32_t Index) const; 209 bool isValidDataSymbol(uint32_t Index) const; 210 bool isValidSectionSymbol(uint32_t Index) const; 211 wasm::WasmFunction &getDefinedFunction(uint32_t Index); 212 wasm::WasmGlobal &getDefinedGlobal(uint32_t Index); 213 214 const WasmSection &getWasmSection(DataRefImpl Ref) const; 215 const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const; 216 217 const uint8_t *getPtr(size_t Offset) const; 218 Error parseSection(WasmSection &Sec); 219 Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx); 220 221 // Standard section types 222 Error parseTypeSection(ReadContext &Ctx); 223 Error parseImportSection(ReadContext &Ctx); 224 Error parseFunctionSection(ReadContext &Ctx); 225 Error parseTableSection(ReadContext &Ctx); 226 Error parseMemorySection(ReadContext &Ctx); 227 Error parseGlobalSection(ReadContext &Ctx); 228 Error parseExportSection(ReadContext &Ctx); 229 Error parseStartSection(ReadContext &Ctx); 230 Error parseElemSection(ReadContext &Ctx); 231 Error parseCodeSection(ReadContext &Ctx); 232 Error parseDataSection(ReadContext &Ctx); 233 234 // Custom section types 235 Error parseNameSection(ReadContext &Ctx); 236 Error parseLinkingSection(ReadContext &Ctx); 237 Error parseLinkingSectionSymtab(ReadContext &Ctx); 238 Error parseLinkingSectionComdat(ReadContext &Ctx); 239 Error parseRelocSection(StringRef Name, ReadContext &Ctx); 240 241 wasm::WasmObjectHeader Header; 242 std::vector<WasmSection> Sections; 243 std::vector<wasm::WasmSignature> Signatures; 244 std::vector<uint32_t> FunctionTypes; 245 std::vector<wasm::WasmTable> Tables; 246 std::vector<wasm::WasmLimits> Memories; 247 std::vector<wasm::WasmGlobal> Globals; 248 std::vector<wasm::WasmImport> Imports; 249 std::vector<wasm::WasmExport> Exports; 250 std::vector<wasm::WasmElemSegment> ElemSegments; 251 std::vector<WasmSegment> DataSegments; 252 std::vector<wasm::WasmFunction> Functions; 253 std::vector<WasmSymbol> Symbols; 254 std::vector<wasm::WasmFunctionName> DebugNames; 255 uint32_t StartFunction = -1; 256 bool HasLinkingSection = false; 257 wasm::WasmLinkingData LinkingData; 258 uint32_t NumImportedGlobals = 0; 259 uint32_t NumImportedFunctions = 0; 260 uint32_t CodeSection = 0; 261 uint32_t DataSection = 0; 262 uint32_t GlobalSection = 0; 263 }; 264 265 } // end namespace object 266 267 inline raw_ostream &operator<<(raw_ostream &OS, 268 const object::WasmSymbol &Sym) { 269 Sym.print(OS); 270 return OS; 271 } 272 273 } // end namespace llvm 274 275 #endif // LLVM_OBJECT_WASM_H 276