Home | History | Annotate | Line # | Download | only in Object
      1 //===- Wasm.h - Wasm object file implementation -----------------*- 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 // This file declares the WasmObjectFile class, which implements the ObjectFile
     10 // interface for Wasm files.
     11 //
     12 // See: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #ifndef LLVM_OBJECT_WASM_H
     17 #define LLVM_OBJECT_WASM_H
     18 
     19 #include "llvm/ADT/ArrayRef.h"
     20 #include "llvm/ADT/StringRef.h"
     21 #include "llvm/BinaryFormat/Wasm.h"
     22 #include "llvm/Config/llvm-config.h"
     23 #include "llvm/MC/MCSymbolWasm.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   WasmSymbol(const wasm::WasmSymbolInfo &Info,
     38              const wasm::WasmGlobalType *GlobalType,
     39              const wasm::WasmTableType *TableType,
     40              const wasm::WasmEventType *EventType,
     41              const wasm::WasmSignature *Signature)
     42       : Info(Info), GlobalType(GlobalType), TableType(TableType),
     43         EventType(EventType), Signature(Signature) {}
     44 
     45   const wasm::WasmSymbolInfo &Info;
     46   const wasm::WasmGlobalType *GlobalType;
     47   const wasm::WasmTableType *TableType;
     48   const wasm::WasmEventType *EventType;
     49   const wasm::WasmSignature *Signature;
     50 
     51   bool isTypeFunction() const {
     52     return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
     53   }
     54 
     55   bool isTypeTable() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_TABLE; }
     56 
     57   bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; }
     58 
     59   bool isTypeGlobal() const {
     60     return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL;
     61   }
     62 
     63   bool isTypeSection() const {
     64     return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION;
     65   }
     66 
     67   bool isTypeEvent() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT; }
     68 
     69   bool isDefined() const { return !isUndefined(); }
     70 
     71   bool isUndefined() const {
     72     return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0;
     73   }
     74 
     75   bool isBindingWeak() const {
     76     return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
     77   }
     78 
     79   bool isBindingGlobal() const {
     80     return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL;
     81   }
     82 
     83   bool isBindingLocal() const {
     84     return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL;
     85   }
     86 
     87   unsigned getBinding() const {
     88     return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK;
     89   }
     90 
     91   bool isHidden() const {
     92     return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
     93   }
     94 
     95   unsigned getVisibility() const {
     96     return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
     97   }
     98 
     99   void print(raw_ostream &Out) const;
    100 
    101 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    102   LLVM_DUMP_METHOD void dump() const;
    103 #endif
    104 };
    105 
    106 struct WasmSection {
    107   WasmSection() = default;
    108 
    109   uint32_t Type = 0;         // Section type (See below)
    110   uint32_t Offset = 0;       // Offset with in the file
    111   StringRef Name;            // Section name (User-defined sections only)
    112   uint32_t Comdat = UINT32_MAX; // From the "comdat info" section
    113   ArrayRef<uint8_t> Content; // Section content
    114   std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
    115 };
    116 
    117 struct WasmSegment {
    118   uint32_t SectionOffset;
    119   wasm::WasmDataSegment Data;
    120 };
    121 
    122 class WasmObjectFile : public ObjectFile {
    123 
    124 public:
    125   WasmObjectFile(MemoryBufferRef Object, Error &Err);
    126 
    127   const wasm::WasmObjectHeader &getHeader() const;
    128   const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const;
    129   const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const;
    130   const WasmSection &getWasmSection(const SectionRef &Section) const;
    131   const wasm::WasmRelocation &getWasmRelocation(const RelocationRef &Ref) const;
    132 
    133   static bool classof(const Binary *v) { return v->isWasm(); }
    134 
    135   const wasm::WasmDylinkInfo &dylinkInfo() const { return DylinkInfo; }
    136   const wasm::WasmProducerInfo &getProducerInfo() const { return ProducerInfo; }
    137   ArrayRef<wasm::WasmFeatureEntry> getTargetFeatures() const {
    138     return TargetFeatures;
    139   }
    140   ArrayRef<wasm::WasmSignature> types() const { return Signatures; }
    141   ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; }
    142   ArrayRef<wasm::WasmImport> imports() const { return Imports; }
    143   ArrayRef<wasm::WasmTable> tables() const { return Tables; }
    144   ArrayRef<wasm::WasmLimits> memories() const { return Memories; }
    145   ArrayRef<wasm::WasmGlobal> globals() const { return Globals; }
    146   ArrayRef<wasm::WasmEvent> events() const { return Events; }
    147   ArrayRef<wasm::WasmExport> exports() const { return Exports; }
    148   ArrayRef<WasmSymbol> syms() const { return Symbols; }
    149   const wasm::WasmLinkingData &linkingData() const { return LinkingData; }
    150   uint32_t getNumberOfSymbols() const { return Symbols.size(); }
    151   ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
    152   ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
    153   ArrayRef<wasm::WasmFunction> functions() const { return Functions; }
    154   ArrayRef<wasm::WasmDebugName> debugNames() const { return DebugNames; }
    155   uint32_t startFunction() const { return StartFunction; }
    156   uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
    157   uint32_t getNumImportedTables() const { return NumImportedTables; }
    158   uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
    159   uint32_t getNumImportedEvents() const { return NumImportedEvents; }
    160   uint32_t getNumSections() const { return Sections.size(); }
    161   void moveSymbolNext(DataRefImpl &Symb) const override;
    162 
    163   Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
    164 
    165   basic_symbol_iterator symbol_begin() const override;
    166 
    167   basic_symbol_iterator symbol_end() const override;
    168   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
    169 
    170   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
    171   uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const;
    172   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
    173   uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
    174   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
    175   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
    176   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
    177   uint32_t getSymbolSectionId(SymbolRef Sym) const;
    178 
    179   // Overrides from SectionRef.
    180   void moveSectionNext(DataRefImpl &Sec) const override;
    181   Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
    182   uint64_t getSectionAddress(DataRefImpl Sec) const override;
    183   uint64_t getSectionIndex(DataRefImpl Sec) const override;
    184   uint64_t getSectionSize(DataRefImpl Sec) const override;
    185   Expected<ArrayRef<uint8_t>>
    186   getSectionContents(DataRefImpl Sec) const override;
    187   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
    188   bool isSectionCompressed(DataRefImpl Sec) const override;
    189   bool isSectionText(DataRefImpl Sec) const override;
    190   bool isSectionData(DataRefImpl Sec) const override;
    191   bool isSectionBSS(DataRefImpl Sec) const override;
    192   bool isSectionVirtual(DataRefImpl Sec) const override;
    193   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
    194   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
    195 
    196   // Overrides from RelocationRef.
    197   void moveRelocationNext(DataRefImpl &Rel) const override;
    198   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
    199   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
    200   uint64_t getRelocationType(DataRefImpl Rel) const override;
    201   void getRelocationTypeName(DataRefImpl Rel,
    202                              SmallVectorImpl<char> &Result) const override;
    203 
    204   section_iterator section_begin() const override;
    205   section_iterator section_end() const override;
    206   uint8_t getBytesInAddress() const override;
    207   StringRef getFileFormatName() const override;
    208   Triple::ArchType getArch() const override;
    209   SubtargetFeatures getFeatures() const override;
    210   bool isRelocatableObject() const override;
    211   bool isSharedObject() const;
    212 
    213   struct ReadContext {
    214     const uint8_t *Start;
    215     const uint8_t *Ptr;
    216     const uint8_t *End;
    217   };
    218 
    219 private:
    220   bool isValidFunctionIndex(uint32_t Index) const;
    221   bool isDefinedFunctionIndex(uint32_t Index) const;
    222   bool isValidGlobalIndex(uint32_t Index) const;
    223   bool isValidTableNumber(uint32_t Index) const;
    224   bool isDefinedGlobalIndex(uint32_t Index) const;
    225   bool isDefinedTableNumber(uint32_t Index) const;
    226   bool isValidEventIndex(uint32_t Index) const;
    227   bool isDefinedEventIndex(uint32_t Index) const;
    228   bool isValidFunctionSymbol(uint32_t Index) const;
    229   bool isValidTableSymbol(uint32_t Index) const;
    230   bool isValidGlobalSymbol(uint32_t Index) const;
    231   bool isValidEventSymbol(uint32_t Index) const;
    232   bool isValidDataSymbol(uint32_t Index) const;
    233   bool isValidSectionSymbol(uint32_t Index) const;
    234   wasm::WasmFunction &getDefinedFunction(uint32_t Index);
    235   const wasm::WasmFunction &getDefinedFunction(uint32_t Index) const;
    236   wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);
    237   wasm::WasmEvent &getDefinedEvent(uint32_t Index);
    238 
    239   const WasmSection &getWasmSection(DataRefImpl Ref) const;
    240   const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
    241   uint32_t getSymbolSectionIdImpl(const WasmSymbol &Symb) const;
    242 
    243   Error parseSection(WasmSection &Sec);
    244   Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx);
    245 
    246   // Standard section types
    247   Error parseTypeSection(ReadContext &Ctx);
    248   Error parseImportSection(ReadContext &Ctx);
    249   Error parseFunctionSection(ReadContext &Ctx);
    250   Error parseTableSection(ReadContext &Ctx);
    251   Error parseMemorySection(ReadContext &Ctx);
    252   Error parseEventSection(ReadContext &Ctx);
    253   Error parseGlobalSection(ReadContext &Ctx);
    254   Error parseExportSection(ReadContext &Ctx);
    255   Error parseStartSection(ReadContext &Ctx);
    256   Error parseElemSection(ReadContext &Ctx);
    257   Error parseCodeSection(ReadContext &Ctx);
    258   Error parseDataSection(ReadContext &Ctx);
    259   Error parseDataCountSection(ReadContext &Ctx);
    260 
    261   // Custom section types
    262   Error parseDylinkSection(ReadContext &Ctx);
    263   Error parseNameSection(ReadContext &Ctx);
    264   Error parseLinkingSection(ReadContext &Ctx);
    265   Error parseLinkingSectionSymtab(ReadContext &Ctx);
    266   Error parseLinkingSectionComdat(ReadContext &Ctx);
    267   Error parseProducersSection(ReadContext &Ctx);
    268   Error parseTargetFeaturesSection(ReadContext &Ctx);
    269   Error parseRelocSection(StringRef Name, ReadContext &Ctx);
    270 
    271   wasm::WasmObjectHeader Header;
    272   std::vector<WasmSection> Sections;
    273   wasm::WasmDylinkInfo DylinkInfo;
    274   wasm::WasmProducerInfo ProducerInfo;
    275   std::vector<wasm::WasmFeatureEntry> TargetFeatures;
    276   std::vector<wasm::WasmSignature> Signatures;
    277   std::vector<uint32_t> FunctionTypes;
    278   std::vector<wasm::WasmTable> Tables;
    279   std::vector<wasm::WasmLimits> Memories;
    280   std::vector<wasm::WasmGlobal> Globals;
    281   std::vector<wasm::WasmEvent> Events;
    282   std::vector<wasm::WasmImport> Imports;
    283   std::vector<wasm::WasmExport> Exports;
    284   std::vector<wasm::WasmElemSegment> ElemSegments;
    285   std::vector<WasmSegment> DataSegments;
    286   llvm::Optional<size_t> DataCount;
    287   std::vector<wasm::WasmFunction> Functions;
    288   std::vector<WasmSymbol> Symbols;
    289   std::vector<wasm::WasmDebugName> DebugNames;
    290   uint32_t StartFunction = -1;
    291   bool HasLinkingSection = false;
    292   bool HasDylinkSection = false;
    293   bool SeenCodeSection = false;
    294   bool HasMemory64 = false;
    295   wasm::WasmLinkingData LinkingData;
    296   uint32_t NumImportedGlobals = 0;
    297   uint32_t NumImportedTables = 0;
    298   uint32_t NumImportedFunctions = 0;
    299   uint32_t NumImportedEvents = 0;
    300   uint32_t CodeSection = 0;
    301   uint32_t DataSection = 0;
    302   uint32_t EventSection = 0;
    303   uint32_t GlobalSection = 0;
    304   uint32_t TableSection = 0;
    305 };
    306 
    307 class WasmSectionOrderChecker {
    308 public:
    309   // We define orders for all core wasm sections and known custom sections.
    310   enum : int {
    311     // Sentinel, must be zero
    312     WASM_SEC_ORDER_NONE = 0,
    313 
    314     // Core sections
    315     WASM_SEC_ORDER_TYPE,
    316     WASM_SEC_ORDER_IMPORT,
    317     WASM_SEC_ORDER_FUNCTION,
    318     WASM_SEC_ORDER_TABLE,
    319     WASM_SEC_ORDER_MEMORY,
    320     WASM_SEC_ORDER_EVENT,
    321     WASM_SEC_ORDER_GLOBAL,
    322     WASM_SEC_ORDER_EXPORT,
    323     WASM_SEC_ORDER_START,
    324     WASM_SEC_ORDER_ELEM,
    325     WASM_SEC_ORDER_DATACOUNT,
    326     WASM_SEC_ORDER_CODE,
    327     WASM_SEC_ORDER_DATA,
    328 
    329     // Custom sections
    330     // "dylink" should be the very first section in the module
    331     WASM_SEC_ORDER_DYLINK,
    332     // "linking" section requires DATA section in order to validate data symbols
    333     WASM_SEC_ORDER_LINKING,
    334     // Must come after "linking" section in order to validate reloc indexes.
    335     WASM_SEC_ORDER_RELOC,
    336     // "name" section must appear after DATA. Comes after "linking" to allow
    337     // symbol table to set default function name.
    338     WASM_SEC_ORDER_NAME,
    339     // "producers" section must appear after "name" section.
    340     WASM_SEC_ORDER_PRODUCERS,
    341     // "target_features" section must appear after producers section
    342     WASM_SEC_ORDER_TARGET_FEATURES,
    343 
    344     // Must be last
    345     WASM_NUM_SEC_ORDERS
    346 
    347   };
    348 
    349   // Sections that may or may not be present, but cannot be predecessors
    350   static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS];
    351 
    352   bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName = "");
    353 
    354 private:
    355   bool Seen[WASM_NUM_SEC_ORDERS] = {}; // Sections that have been seen already
    356 
    357   // Returns -1 for unknown sections.
    358   int getSectionOrder(unsigned ID, StringRef CustomSectionName = "");
    359 };
    360 
    361 } // end namespace object
    362 
    363 inline raw_ostream &operator<<(raw_ostream &OS, const object::WasmSymbol &Sym) {
    364   Sym.print(OS);
    365   return OS;
    366 }
    367 
    368 } // end namespace llvm
    369 
    370 #endif // LLVM_OBJECT_WASM_H
    371