Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:20

0001 //===- Wasm.h - Wasm object file implementation -----------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file declares the WasmObjectFile class, which implements the ObjectFile
0010 // interface for Wasm files.
0011 //
0012 // See: https://github.com/WebAssembly/design/blob/main/BinaryEncoding.md
0013 //
0014 //===----------------------------------------------------------------------===//
0015 
0016 #ifndef LLVM_OBJECT_WASM_H
0017 #define LLVM_OBJECT_WASM_H
0018 
0019 #include "llvm/ADT/ArrayRef.h"
0020 #include "llvm/ADT/StringRef.h"
0021 #include "llvm/BinaryFormat/Wasm.h"
0022 #include "llvm/Config/llvm-config.h"
0023 #include "llvm/MC/MCSymbolWasm.h"
0024 #include "llvm/Object/Binary.h"
0025 #include "llvm/Object/ObjectFile.h"
0026 #include "llvm/Support/Error.h"
0027 #include "llvm/Support/MemoryBuffer.h"
0028 #include <cstddef>
0029 #include <cstdint>
0030 #include <vector>
0031 
0032 namespace llvm {
0033 namespace object {
0034 
0035 class WasmSymbol {
0036 public:
0037   WasmSymbol(const wasm::WasmSymbolInfo &Info,
0038              const wasm::WasmGlobalType *GlobalType,
0039              const wasm::WasmTableType *TableType,
0040              const wasm::WasmSignature *Signature)
0041       : Info(Info), GlobalType(GlobalType), TableType(TableType),
0042         Signature(Signature) {
0043     assert(!Signature || Signature->Kind != wasm::WasmSignature::Placeholder);
0044   }
0045 
0046   // Symbol info as represented in the symbol's 'syminfo' entry of an object
0047   // file's symbol table.
0048   wasm::WasmSymbolInfo Info;
0049   const wasm::WasmGlobalType *GlobalType;
0050   const wasm::WasmTableType *TableType;
0051   const wasm::WasmSignature *Signature;
0052 
0053   bool isTypeFunction() const {
0054     return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
0055   }
0056 
0057   bool isTypeTable() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_TABLE; }
0058 
0059   bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; }
0060 
0061   bool isTypeGlobal() const {
0062     return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL;
0063   }
0064 
0065   bool isTypeSection() const {
0066     return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION;
0067   }
0068 
0069   bool isTypeTag() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_TAG; }
0070 
0071   bool isDefined() const { return !isUndefined(); }
0072 
0073   bool isUndefined() const {
0074     return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0;
0075   }
0076 
0077   bool isBindingWeak() const {
0078     return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
0079   }
0080 
0081   bool isBindingGlobal() const {
0082     return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL;
0083   }
0084 
0085   bool isBindingLocal() const {
0086     return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL;
0087   }
0088 
0089   unsigned getBinding() const {
0090     return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK;
0091   }
0092 
0093   bool isHidden() const {
0094     return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
0095   }
0096 
0097   unsigned getVisibility() const {
0098     return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
0099   }
0100 
0101   void print(raw_ostream &Out) const;
0102 
0103 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0104   LLVM_DUMP_METHOD void dump() const;
0105 #endif
0106 };
0107 
0108 struct WasmSection {
0109   WasmSection() = default;
0110 
0111   uint32_t Type = 0;
0112   uint32_t Offset = 0;       // Offset within the file
0113   StringRef Name;            // Section name (User-defined sections only)
0114   uint32_t Comdat = UINT32_MAX; // From the "comdat info" section
0115   ArrayRef<uint8_t> Content;
0116   std::vector<wasm::WasmRelocation> Relocations;
0117   // Length of the LEB encoding of the section header's size field
0118   std::optional<uint8_t> HeaderSecSizeEncodingLen;
0119 };
0120 
0121 struct WasmSegment {
0122   uint32_t SectionOffset;
0123   wasm::WasmDataSegment Data;
0124 };
0125 
0126 class WasmObjectFile : public ObjectFile {
0127 
0128 public:
0129   WasmObjectFile(MemoryBufferRef Object, Error &Err);
0130 
0131   const wasm::WasmObjectHeader &getHeader() const;
0132   const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const;
0133   const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const;
0134   const WasmSection &getWasmSection(const SectionRef &Section) const;
0135   const wasm::WasmRelocation &getWasmRelocation(const RelocationRef &Ref) const;
0136 
0137   static bool classof(const Binary *v) { return v->isWasm(); }
0138 
0139   const wasm::WasmDylinkInfo &dylinkInfo() const { return DylinkInfo; }
0140   const wasm::WasmProducerInfo &getProducerInfo() const { return ProducerInfo; }
0141   ArrayRef<wasm::WasmFeatureEntry> getTargetFeatures() const {
0142     return TargetFeatures;
0143   }
0144   ArrayRef<wasm::WasmSignature> types() const { return Signatures; }
0145   ArrayRef<wasm::WasmImport> imports() const { return Imports; }
0146   ArrayRef<wasm::WasmTable> tables() const { return Tables; }
0147   ArrayRef<wasm::WasmLimits> memories() const { return Memories; }
0148   ArrayRef<wasm::WasmGlobal> globals() const { return Globals; }
0149   ArrayRef<wasm::WasmTag> tags() const { return Tags; }
0150   ArrayRef<wasm::WasmExport> exports() const { return Exports; }
0151   const wasm::WasmLinkingData &linkingData() const { return LinkingData; }
0152   uint32_t getNumberOfSymbols() const { return Symbols.size(); }
0153   ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
0154   ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
0155   ArrayRef<wasm::WasmFunction> functions() const { return Functions; }
0156   ArrayRef<wasm::WasmDebugName> debugNames() const { return DebugNames; }
0157   uint32_t startFunction() const { return StartFunction; }
0158   uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
0159   uint32_t getNumImportedTables() const { return NumImportedTables; }
0160   uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
0161   uint32_t getNumImportedTags() const { return NumImportedTags; }
0162   uint32_t getNumSections() const { return Sections.size(); }
0163   void moveSymbolNext(DataRefImpl &Symb) const override;
0164 
0165   Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
0166 
0167   basic_symbol_iterator symbol_begin() const override;
0168 
0169   basic_symbol_iterator symbol_end() const override;
0170   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
0171 
0172   bool is64Bit() const override { return false; }
0173 
0174   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
0175   uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const;
0176   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
0177   uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
0178   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
0179   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
0180   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
0181   uint32_t getSymbolSectionId(SymbolRef Sym) const;
0182   uint32_t getSymbolSize(SymbolRef Sym) const;
0183 
0184   // Overrides from SectionRef.
0185   void moveSectionNext(DataRefImpl &Sec) const override;
0186   Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
0187   uint64_t getSectionAddress(DataRefImpl Sec) const override;
0188   uint64_t getSectionIndex(DataRefImpl Sec) const override;
0189   uint64_t getSectionSize(DataRefImpl Sec) const override;
0190   Expected<ArrayRef<uint8_t>>
0191   getSectionContents(DataRefImpl Sec) const override;
0192   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
0193   bool isSectionCompressed(DataRefImpl Sec) const override;
0194   bool isSectionText(DataRefImpl Sec) const override;
0195   bool isSectionData(DataRefImpl Sec) const override;
0196   bool isSectionBSS(DataRefImpl Sec) const override;
0197   bool isSectionVirtual(DataRefImpl Sec) const override;
0198   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
0199   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
0200 
0201   // Overrides from RelocationRef.
0202   void moveRelocationNext(DataRefImpl &Rel) const override;
0203   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
0204   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
0205   uint64_t getRelocationType(DataRefImpl Rel) const override;
0206   void getRelocationTypeName(DataRefImpl Rel,
0207                              SmallVectorImpl<char> &Result) const override;
0208 
0209   section_iterator section_begin() const override;
0210   section_iterator section_end() const override;
0211   uint8_t getBytesInAddress() const override;
0212   StringRef getFileFormatName() const override;
0213   Triple::ArchType getArch() const override;
0214   Expected<SubtargetFeatures> getFeatures() const override;
0215   bool isRelocatableObject() const override;
0216   bool isSharedObject() const;
0217   bool hasUnmodeledTypes() const { return HasUnmodeledTypes; }
0218 
0219   struct ReadContext {
0220     const uint8_t *Start;
0221     const uint8_t *Ptr;
0222     const uint8_t *End;
0223   };
0224 
0225 private:
0226   bool isValidFunctionIndex(uint32_t Index) const;
0227   bool isDefinedFunctionIndex(uint32_t Index) const;
0228   bool isValidGlobalIndex(uint32_t Index) const;
0229   bool isValidTableNumber(uint32_t Index) const;
0230   bool isDefinedGlobalIndex(uint32_t Index) const;
0231   bool isDefinedTableNumber(uint32_t Index) const;
0232   bool isValidTagIndex(uint32_t Index) const;
0233   bool isDefinedTagIndex(uint32_t Index) const;
0234   bool isValidFunctionSymbol(uint32_t Index) const;
0235   bool isValidTableSymbol(uint32_t Index) const;
0236   bool isValidGlobalSymbol(uint32_t Index) const;
0237   bool isValidTagSymbol(uint32_t Index) const;
0238   bool isValidDataSymbol(uint32_t Index) const;
0239   bool isValidSectionSymbol(uint32_t Index) const;
0240   wasm::WasmFunction &getDefinedFunction(uint32_t Index);
0241   const wasm::WasmFunction &getDefinedFunction(uint32_t Index) const;
0242   const wasm::WasmGlobal &getDefinedGlobal(uint32_t Index) const;
0243   wasm::WasmTag &getDefinedTag(uint32_t Index);
0244 
0245   const WasmSection &getWasmSection(DataRefImpl Ref) const;
0246   const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
0247   uint32_t getSymbolSectionIdImpl(const WasmSymbol &Symb) const;
0248 
0249   Error parseSection(WasmSection &Sec);
0250   Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx);
0251 
0252   // Standard section types
0253   Error parseTypeSection(ReadContext &Ctx);
0254   Error parseImportSection(ReadContext &Ctx);
0255   Error parseFunctionSection(ReadContext &Ctx);
0256   Error parseTableSection(ReadContext &Ctx);
0257   Error parseMemorySection(ReadContext &Ctx);
0258   Error parseTagSection(ReadContext &Ctx);
0259   Error parseGlobalSection(ReadContext &Ctx);
0260   Error parseExportSection(ReadContext &Ctx);
0261   Error parseStartSection(ReadContext &Ctx);
0262   Error parseElemSection(ReadContext &Ctx);
0263   Error parseCodeSection(ReadContext &Ctx);
0264   Error parseDataSection(ReadContext &Ctx);
0265   Error parseDataCountSection(ReadContext &Ctx);
0266 
0267   // Custom section types
0268   Error parseDylinkSection(ReadContext &Ctx);
0269   Error parseDylink0Section(ReadContext &Ctx);
0270   Error parseNameSection(ReadContext &Ctx);
0271   Error parseLinkingSection(ReadContext &Ctx);
0272   Error parseLinkingSectionSymtab(ReadContext &Ctx);
0273   Error parseLinkingSectionComdat(ReadContext &Ctx);
0274   Error parseProducersSection(ReadContext &Ctx);
0275   Error parseTargetFeaturesSection(ReadContext &Ctx);
0276   Error parseRelocSection(StringRef Name, ReadContext &Ctx);
0277 
0278   wasm::WasmObjectHeader Header;
0279   std::vector<WasmSection> Sections;
0280   wasm::WasmDylinkInfo DylinkInfo;
0281   wasm::WasmProducerInfo ProducerInfo;
0282   std::vector<wasm::WasmFeatureEntry> TargetFeatures;
0283   std::vector<wasm::WasmSignature> Signatures;
0284   std::vector<wasm::WasmTable> Tables;
0285   std::vector<wasm::WasmLimits> Memories;
0286   std::vector<wasm::WasmGlobal> Globals;
0287   std::vector<wasm::WasmTag> Tags;
0288   std::vector<wasm::WasmImport> Imports;
0289   std::vector<wasm::WasmExport> Exports;
0290   std::vector<wasm::WasmElemSegment> ElemSegments;
0291   std::vector<WasmSegment> DataSegments;
0292   std::optional<size_t> DataCount;
0293   std::vector<wasm::WasmFunction> Functions;
0294   std::vector<WasmSymbol> Symbols;
0295   std::vector<wasm::WasmDebugName> DebugNames;
0296   uint32_t StartFunction = -1;
0297   bool HasLinkingSection = false;
0298   bool HasDylinkSection = false;
0299   bool HasMemory64 = false;
0300   bool HasUnmodeledTypes = false;
0301   wasm::WasmLinkingData LinkingData;
0302   uint32_t NumImportedGlobals = 0;
0303   uint32_t NumImportedTables = 0;
0304   uint32_t NumImportedFunctions = 0;
0305   uint32_t NumImportedTags = 0;
0306   uint32_t CodeSection = 0;
0307   uint32_t DataSection = 0;
0308   uint32_t TagSection = 0;
0309   uint32_t GlobalSection = 0;
0310   uint32_t TableSection = 0;
0311 };
0312 
0313 class WasmSectionOrderChecker {
0314 public:
0315   // We define orders for all core wasm sections and known custom sections.
0316   enum : int {
0317     // Sentinel, must be zero
0318     WASM_SEC_ORDER_NONE = 0,
0319 
0320     // Core sections
0321     WASM_SEC_ORDER_TYPE,
0322     WASM_SEC_ORDER_IMPORT,
0323     WASM_SEC_ORDER_FUNCTION,
0324     WASM_SEC_ORDER_TABLE,
0325     WASM_SEC_ORDER_MEMORY,
0326     WASM_SEC_ORDER_TAG,
0327     WASM_SEC_ORDER_GLOBAL,
0328     WASM_SEC_ORDER_EXPORT,
0329     WASM_SEC_ORDER_START,
0330     WASM_SEC_ORDER_ELEM,
0331     WASM_SEC_ORDER_DATACOUNT,
0332     WASM_SEC_ORDER_CODE,
0333     WASM_SEC_ORDER_DATA,
0334 
0335     // Custom sections
0336     // "dylink" should be the very first section in the module
0337     WASM_SEC_ORDER_DYLINK,
0338     // "linking" section requires DATA section in order to validate data symbols
0339     WASM_SEC_ORDER_LINKING,
0340     // Must come after "linking" section in order to validate reloc indexes.
0341     WASM_SEC_ORDER_RELOC,
0342     // "name" section must appear after DATA. Comes after "linking" to allow
0343     // symbol table to set default function name.
0344     WASM_SEC_ORDER_NAME,
0345     // "producers" section must appear after "name" section.
0346     WASM_SEC_ORDER_PRODUCERS,
0347     // "target_features" section must appear after producers section
0348     WASM_SEC_ORDER_TARGET_FEATURES,
0349 
0350     // Must be last
0351     WASM_NUM_SEC_ORDERS
0352 
0353   };
0354 
0355   // Sections that may or may not be present, but cannot be predecessors
0356   static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS];
0357 
0358   bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName = "");
0359 
0360 private:
0361   bool Seen[WASM_NUM_SEC_ORDERS] = {}; // Sections that have been seen already
0362 
0363   // Returns -1 for unknown sections.
0364   int getSectionOrder(unsigned ID, StringRef CustomSectionName = "");
0365 };
0366 
0367 } // end namespace object
0368 
0369 inline raw_ostream &operator<<(raw_ostream &OS, const object::WasmSymbol &Sym) {
0370   Sym.print(OS);
0371   return OS;
0372 }
0373 
0374 } // end namespace llvm
0375 
0376 #endif // LLVM_OBJECT_WASM_H