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