Line data Source code
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/StringMap.h"
22 : #include "llvm/ADT/StringRef.h"
23 : #include "llvm/BinaryFormat/Wasm.h"
24 : #include "llvm/Config/llvm-config.h"
25 : #include "llvm/MC/MCSymbolWasm.h"
26 : #include "llvm/Object/Binary.h"
27 : #include "llvm/Object/ObjectFile.h"
28 : #include "llvm/Support/Error.h"
29 : #include "llvm/Support/MemoryBuffer.h"
30 : #include <cstddef>
31 : #include <cstdint>
32 : #include <vector>
33 :
34 : namespace llvm {
35 : namespace object {
36 :
37 : class WasmSymbol {
38 : public:
39 : WasmSymbol(const wasm::WasmSymbolInfo &Info,
40 : const wasm::WasmSignature *FunctionType,
41 : const wasm::WasmGlobalType *GlobalType)
42 1099 : : Info(Info), FunctionType(FunctionType), GlobalType(GlobalType) {}
43 :
44 : const wasm::WasmSymbolInfo &Info;
45 : const wasm::WasmSignature *FunctionType;
46 : const wasm::WasmGlobalType *GlobalType;
47 :
48 0 : bool isTypeFunction() const {
49 553 : return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
50 : }
51 :
52 375 : bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; }
53 :
54 0 : bool isTypeGlobal() const {
55 40 : return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL;
56 : }
57 :
58 0 : bool isTypeSection() const {
59 58 : return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION;
60 : }
61 :
62 637 : bool isDefined() const { return !isUndefined(); }
63 :
64 0 : bool isUndefined() const {
65 855 : return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0;
66 : }
67 :
68 : bool isBindingWeak() const {
69 196 : return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
70 : }
71 :
72 : bool isBindingGlobal() const {
73 : return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL;
74 : }
75 :
76 : bool isBindingLocal() const {
77 442 : return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL;
78 : }
79 :
80 0 : unsigned getBinding() const {
81 721 : return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK;
82 : }
83 :
84 : bool isHidden() const {
85 : return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
86 : }
87 :
88 0 : unsigned getVisibility() const {
89 196 : return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
90 : }
91 :
92 : void print(raw_ostream &Out) const;
93 :
94 : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
95 : LLVM_DUMP_METHOD void dump() const;
96 : #endif
97 : };
98 :
99 10215 : struct WasmSection {
100 357 : WasmSection() = default;
101 :
102 : uint32_t Type = 0; // Section type (See below)
103 : uint32_t Offset = 0; // Offset with in the file
104 : StringRef Name; // Section name (User-defined sections only)
105 : ArrayRef<uint8_t> Content; // Section content
106 : std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
107 : };
108 :
109 : struct WasmSegment {
110 : uint32_t SectionOffset;
111 : wasm::WasmDataSegment Data;
112 : };
113 :
114 : class WasmObjectFile : public ObjectFile {
115 :
116 : public:
117 : WasmObjectFile(MemoryBufferRef Object, Error &Err);
118 :
119 : const wasm::WasmObjectHeader &getHeader() const;
120 : const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const;
121 : const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const;
122 : const WasmSection &getWasmSection(const SectionRef &Section) const;
123 : const wasm::WasmRelocation &getWasmRelocation(const RelocationRef &Ref) const;
124 :
125 206 : static bool classof(const Binary *v) { return v->isWasm(); }
126 :
127 : ArrayRef<wasm::WasmSignature> types() const { return Signatures; }
128 : ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; }
129 : ArrayRef<wasm::WasmImport> imports() const { return Imports; }
130 : ArrayRef<wasm::WasmTable> tables() const { return Tables; }
131 : ArrayRef<wasm::WasmLimits> memories() const { return Memories; }
132 : ArrayRef<wasm::WasmGlobal> globals() const { return Globals; }
133 : ArrayRef<wasm::WasmExport> exports() const { return Exports; }
134 : ArrayRef<WasmSymbol> syms() const { return Symbols; }
135 : const wasm::WasmLinkingData &linkingData() const { return LinkingData; }
136 190 : uint32_t getNumberOfSymbols() const { return Symbols.size(); }
137 : ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
138 : ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
139 : ArrayRef<wasm::WasmFunction> functions() const { return Functions; }
140 : ArrayRef<wasm::WasmFunctionName> debugNames() const { return DebugNames; }
141 0 : uint32_t startFunction() const { return StartFunction; }
142 0 : uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
143 0 : uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
144 :
145 : void moveSymbolNext(DataRefImpl &Symb) const override;
146 :
147 : uint32_t getSymbolFlags(DataRefImpl Symb) const override;
148 :
149 : basic_symbol_iterator symbol_begin() const override;
150 :
151 : basic_symbol_iterator symbol_end() const override;
152 : Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
153 :
154 : Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
155 : uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const;
156 : uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
157 : uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
158 : uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
159 : Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
160 : Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
161 :
162 : // Overrides from SectionRef.
163 : void moveSectionNext(DataRefImpl &Sec) const override;
164 : std::error_code getSectionName(DataRefImpl Sec,
165 : StringRef &Res) const override;
166 : uint64_t getSectionAddress(DataRefImpl Sec) const override;
167 : uint64_t getSectionIndex(DataRefImpl Sec) const override;
168 : uint64_t getSectionSize(DataRefImpl Sec) const override;
169 : std::error_code getSectionContents(DataRefImpl Sec,
170 : StringRef &Res) const override;
171 : uint64_t getSectionAlignment(DataRefImpl Sec) const override;
172 : bool isSectionCompressed(DataRefImpl Sec) const override;
173 : bool isSectionText(DataRefImpl Sec) const override;
174 : bool isSectionData(DataRefImpl Sec) const override;
175 : bool isSectionBSS(DataRefImpl Sec) const override;
176 : bool isSectionVirtual(DataRefImpl Sec) const override;
177 : bool isSectionBitcode(DataRefImpl Sec) const override;
178 : relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
179 : relocation_iterator section_rel_end(DataRefImpl Sec) const override;
180 :
181 : // Overrides from RelocationRef.
182 : void moveRelocationNext(DataRefImpl &Rel) const override;
183 : uint64_t getRelocationOffset(DataRefImpl Rel) const override;
184 : symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
185 : uint64_t getRelocationType(DataRefImpl Rel) const override;
186 : void getRelocationTypeName(DataRefImpl Rel,
187 : SmallVectorImpl<char> &Result) const override;
188 :
189 : section_iterator section_begin() const override;
190 : section_iterator section_end() const override;
191 : uint8_t getBytesInAddress() const override;
192 : StringRef getFileFormatName() const override;
193 : Triple::ArchType getArch() const override;
194 : SubtargetFeatures getFeatures() const override;
195 : bool isRelocatableObject() const override;
196 :
197 : struct ReadContext {
198 : const uint8_t *Start;
199 : const uint8_t *Ptr;
200 : const uint8_t *End;
201 : };
202 :
203 : private:
204 : bool isValidFunctionIndex(uint32_t Index) const;
205 : bool isDefinedFunctionIndex(uint32_t Index) const;
206 : bool isValidGlobalIndex(uint32_t Index) const;
207 : bool isDefinedGlobalIndex(uint32_t Index) const;
208 : bool isValidFunctionSymbol(uint32_t Index) const;
209 : bool isValidGlobalSymbol(uint32_t Index) const;
210 : bool isValidDataSymbol(uint32_t Index) const;
211 : bool isValidSectionSymbol(uint32_t Index) const;
212 : wasm::WasmFunction &getDefinedFunction(uint32_t Index);
213 : wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);
214 :
215 : const WasmSection &getWasmSection(DataRefImpl Ref) const;
216 : const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
217 :
218 : const uint8_t *getPtr(size_t Offset) const;
219 : Error parseSection(WasmSection &Sec);
220 : Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx);
221 :
222 : // Standard section types
223 : Error parseTypeSection(ReadContext &Ctx);
224 : Error parseImportSection(ReadContext &Ctx);
225 : Error parseFunctionSection(ReadContext &Ctx);
226 : Error parseTableSection(ReadContext &Ctx);
227 : Error parseMemorySection(ReadContext &Ctx);
228 : Error parseGlobalSection(ReadContext &Ctx);
229 : Error parseExportSection(ReadContext &Ctx);
230 : Error parseStartSection(ReadContext &Ctx);
231 : Error parseElemSection(ReadContext &Ctx);
232 : Error parseCodeSection(ReadContext &Ctx);
233 : Error parseDataSection(ReadContext &Ctx);
234 :
235 : // Custom section types
236 : Error parseNameSection(ReadContext &Ctx);
237 : Error parseLinkingSection(ReadContext &Ctx);
238 : Error parseLinkingSectionSymtab(ReadContext &Ctx);
239 : Error parseLinkingSectionComdat(ReadContext &Ctx);
240 : Error parseRelocSection(StringRef Name, ReadContext &Ctx);
241 :
242 : wasm::WasmObjectHeader Header;
243 : std::vector<WasmSection> Sections;
244 : std::vector<wasm::WasmSignature> Signatures;
245 : std::vector<uint32_t> FunctionTypes;
246 : std::vector<wasm::WasmTable> Tables;
247 : std::vector<wasm::WasmLimits> Memories;
248 : std::vector<wasm::WasmGlobal> Globals;
249 : std::vector<wasm::WasmImport> Imports;
250 : std::vector<wasm::WasmExport> Exports;
251 : std::vector<wasm::WasmElemSegment> ElemSegments;
252 : std::vector<WasmSegment> DataSegments;
253 : std::vector<wasm::WasmFunction> Functions;
254 : std::vector<WasmSymbol> Symbols;
255 : std::vector<wasm::WasmFunctionName> DebugNames;
256 : uint32_t StartFunction = -1;
257 : bool HasLinkingSection = false;
258 : wasm::WasmLinkingData LinkingData;
259 : uint32_t NumImportedGlobals = 0;
260 : uint32_t NumImportedFunctions = 0;
261 : uint32_t CodeSection = 0;
262 : uint32_t DataSection = 0;
263 : uint32_t GlobalSection = 0;
264 : };
265 :
266 : } // end namespace object
267 :
268 : inline raw_ostream &operator<<(raw_ostream &OS, const object::WasmSymbol &Sym) {
269 : Sym.print(OS);
270 : return OS;
271 : }
272 :
273 : } // end namespace llvm
274 :
275 : #endif // LLVM_OBJECT_WASM_H
|