Home | History | Annotate | Download | only in Object
      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