Wasm.h 14 KB

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