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/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:
     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 
     47   bool isTypeFunction() const {
     48     return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
     49   }
     50 
     51   bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; }
     52 
     53   bool isTypeGlobal() const {
     54     return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL;
     55   }
     56 
     57   bool isTypeSection() const {
     58     return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION;
     59   }
     60 
     61   bool isDefined() const { return !isUndefined(); }
     62 
     63   bool isUndefined() const {
     64     return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0;
     65   }
     66 
     67   bool isBindingWeak() const {
     68     return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
     69   }
     70 
     71   bool isBindingGlobal() const {
     72     return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL;
     73   }
     74 
     75   bool isBindingLocal() const {
     76     return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL;
     77   }
     78 
     79   unsigned getBinding() const {
     80     return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK;
     81   }
     82 
     83   bool isHidden() const {
     84     return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
     85   }
     86 
     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 
    124   static bool classof(const Binary *v) { return v->isWasm(); }
    125 
    126   ArrayRef<wasm::WasmSignature> types() const { return Signatures; }
    127   ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; }
    128   ArrayRef<wasm::WasmImport> imports() const { return Imports; }
    129   ArrayRef<wasm::WasmTable> tables() const { return Tables; }
    130   ArrayRef<wasm::WasmLimits> memories() const { return Memories; }
    131   ArrayRef<wasm::WasmGlobal> globals() const { return Globals; }
    132   ArrayRef<wasm::WasmExport> exports() const { return Exports; }
    133   ArrayRef<WasmSymbol> syms() const { return Symbols; }
    134   const wasm::WasmLinkingData& linkingData() const { return LinkingData; }
    135   uint32_t getNumberOfSymbols() const { return Symbols.size(); }
    136   ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
    137   ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
    138   ArrayRef<wasm::WasmFunction> functions() const { return Functions; }
    139   ArrayRef<wasm::WasmFunctionName> debugNames() const { return DebugNames; }
    140   uint32_t startFunction() const { return StartFunction; }
    141   uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
    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