blob: 66a53becbb056187f2cf1348d1501d6296581f0f [file] [log] [blame]
Eugene Zelenko3a124c02017-02-09 01:09:54 +00001//===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
Derek Schuff7a578c92016-11-30 16:49:11 +00002//
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
Eugene Zelenko3a124c02017-02-09 01:09:54 +000010#include "llvm/ADT/ArrayRef.h"
Sam Cleggd4e08e12018-01-12 02:11:31 +000011#include "llvm/ADT/DenseSet.h"
Eugene Zelenko3a124c02017-02-09 01:09:54 +000012#include "llvm/ADT/STLExtras.h"
13#include "llvm/ADT/StringRef.h"
Sam Clegge92250a2018-01-09 23:43:14 +000014#include "llvm/ADT/StringSet.h"
Eugene Zelenko3a124c02017-02-09 01:09:54 +000015#include "llvm/ADT/Triple.h"
Zachary Turner19ca2b02017-06-07 03:48:56 +000016#include "llvm/BinaryFormat/Wasm.h"
Eugene Zelenko903f87e2017-04-21 22:03:05 +000017#include "llvm/MC/SubtargetFeature.h"
Eugene Zelenko3a124c02017-02-09 01:09:54 +000018#include "llvm/Object/Binary.h"
19#include "llvm/Object/Error.h"
20#include "llvm/Object/ObjectFile.h"
21#include "llvm/Object/SymbolicFile.h"
Derek Schuff7a578c92016-11-30 16:49:11 +000022#include "llvm/Object/Wasm.h"
23#include "llvm/Support/Endian.h"
Eugene Zelenko3a124c02017-02-09 01:09:54 +000024#include "llvm/Support/Error.h"
25#include "llvm/Support/ErrorHandling.h"
Derek Schuff7a578c92016-11-30 16:49:11 +000026#include "llvm/Support/LEB128.h"
Heejin Ahne2f3e502018-12-15 00:58:12 +000027#include "llvm/Support/ScopedPrinter.h"
Eugene Zelenko3a124c02017-02-09 01:09:54 +000028#include <algorithm>
Eugene Zelenko903f87e2017-04-21 22:03:05 +000029#include <cassert>
Eugene Zelenko3a124c02017-02-09 01:09:54 +000030#include <cstdint>
Eugene Zelenko903f87e2017-04-21 22:03:05 +000031#include <cstring>
Eugene Zelenko3a124c02017-02-09 01:09:54 +000032#include <system_error>
Derek Schuff7a578c92016-11-30 16:49:11 +000033
Sam Clegg1e975c12017-06-20 04:04:59 +000034#define DEBUG_TYPE "wasm-object"
35
Eugene Zelenko3a124c02017-02-09 01:09:54 +000036using namespace llvm;
37using namespace object;
Derek Schuff7a578c92016-11-30 16:49:11 +000038
JF Bastien62014b82018-05-16 21:24:03 +000039void WasmSymbol::print(raw_ostream &Out) const {
40 Out << "Name=" << Info.Name
Heejin Ahn581d2312018-09-05 01:27:38 +000041 << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
42 << ", Flags=" << Info.Flags;
JF Bastien62014b82018-05-16 21:24:03 +000043 if (!isTypeData()) {
44 Out << ", ElemIndex=" << Info.ElementIndex;
45 } else if (isDefined()) {
46 Out << ", Segment=" << Info.DataRef.Segment;
47 Out << ", Offset=" << Info.DataRef.Offset;
48 Out << ", Size=" << Info.DataRef.Size;
49 }
50}
51
JF Bastien2a77a182018-05-16 22:31:42 +000052#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
53LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
54#endif
55
Derek Schuff7a578c92016-11-30 16:49:11 +000056Expected<std::unique_ptr<WasmObjectFile>>
57ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
58 Error Err = Error::success();
59 auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
60 if (Err)
61 return std::move(Err);
62
63 return std::move(ObjectFile);
64}
65
Heejin Ahn581d2312018-09-05 01:27:38 +000066#define VARINT7_MAX ((1 << 7) - 1)
67#define VARINT7_MIN (-(1 << 7))
68#define VARUINT7_MAX (1 << 7)
Derek Schuff349a48f2017-03-30 19:44:09 +000069#define VARUINT1_MAX (1)
70
Sam Clegg50617cf2018-05-29 19:58:59 +000071static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
72 if (Ctx.Ptr == Ctx.End)
73 report_fatal_error("EOF while reading uint8");
74 return *Ctx.Ptr++;
75}
Derek Schuff349a48f2017-03-30 19:44:09 +000076
Sam Clegg50617cf2018-05-29 19:58:59 +000077static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
78 if (Ctx.Ptr + 4 > Ctx.End)
79 report_fatal_error("EOF while reading uint32");
80 uint32_t Result = support::endian::read32le(Ctx.Ptr);
81 Ctx.Ptr += 4;
Derek Schuff7a578c92016-11-30 16:49:11 +000082 return Result;
83}
84
Sam Clegg50617cf2018-05-29 19:58:59 +000085static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
Jonas Devlieghere1dc41812018-08-31 14:54:01 +000086 if (Ctx.Ptr + 4 > Ctx.End)
87 report_fatal_error("EOF while reading float64");
Derek Schuff349a48f2017-03-30 19:44:09 +000088 int32_t Result = 0;
Sam Clegg50617cf2018-05-29 19:58:59 +000089 memcpy(&Result, Ctx.Ptr, sizeof(Result));
90 Ctx.Ptr += sizeof(Result);
Derek Schuff349a48f2017-03-30 19:44:09 +000091 return Result;
92}
93
Sam Clegg50617cf2018-05-29 19:58:59 +000094static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
Jonas Devlieghere1dc41812018-08-31 14:54:01 +000095 if (Ctx.Ptr + 8 > Ctx.End)
96 report_fatal_error("EOF while reading float64");
Derek Schuff349a48f2017-03-30 19:44:09 +000097 int64_t Result = 0;
Sam Clegg50617cf2018-05-29 19:58:59 +000098 memcpy(&Result, Ctx.Ptr, sizeof(Result));
99 Ctx.Ptr += sizeof(Result);
Derek Schuff349a48f2017-03-30 19:44:09 +0000100 return Result;
101}
102
Sam Clegg50617cf2018-05-29 19:58:59 +0000103static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
Derek Schuff7a578c92016-11-30 16:49:11 +0000104 unsigned Count;
Heejin Ahn581d2312018-09-05 01:27:38 +0000105 const char *Error = nullptr;
Sam Clegg50617cf2018-05-29 19:58:59 +0000106 uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
107 if (Error)
108 report_fatal_error(Error);
109 Ctx.Ptr += Count;
Derek Schuff7a578c92016-11-30 16:49:11 +0000110 return Result;
111}
112
Sam Clegg50617cf2018-05-29 19:58:59 +0000113static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
114 uint32_t StringLen = readULEB128(Ctx);
115 if (Ctx.Ptr + StringLen > Ctx.End)
116 report_fatal_error("EOF while reading string");
117 StringRef Return =
118 StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
119 Ctx.Ptr += StringLen;
Derek Schuff7a578c92016-11-30 16:49:11 +0000120 return Return;
121}
122
Sam Clegg50617cf2018-05-29 19:58:59 +0000123static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
Derek Schuff349a48f2017-03-30 19:44:09 +0000124 unsigned Count;
Heejin Ahn581d2312018-09-05 01:27:38 +0000125 const char *Error = nullptr;
Sam Clegg50617cf2018-05-29 19:58:59 +0000126 uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
127 if (Error)
128 report_fatal_error(Error);
129 Ctx.Ptr += Count;
Derek Schuff349a48f2017-03-30 19:44:09 +0000130 return Result;
131}
132
Sam Clegg50617cf2018-05-29 19:58:59 +0000133static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
134 int64_t result = readLEB128(Ctx);
Sam Cleggd0adb142018-05-18 21:08:26 +0000135 if (result > VARUINT1_MAX || result < 0)
136 report_fatal_error("LEB is outside Varuint1 range");
Derek Schuff349a48f2017-03-30 19:44:09 +0000137 return result;
138}
139
Sam Clegg50617cf2018-05-29 19:58:59 +0000140static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
141 int64_t result = readLEB128(Ctx);
Sam Cleggd0adb142018-05-18 21:08:26 +0000142 if (result > INT32_MAX || result < INT32_MIN)
143 report_fatal_error("LEB is outside Varint32 range");
Derek Schuff349a48f2017-03-30 19:44:09 +0000144 return result;
145}
146
Sam Clegg50617cf2018-05-29 19:58:59 +0000147static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
148 uint64_t result = readULEB128(Ctx);
Sam Cleggd0adb142018-05-18 21:08:26 +0000149 if (result > UINT32_MAX)
150 report_fatal_error("LEB is outside Varuint32 range");
Derek Schuff349a48f2017-03-30 19:44:09 +0000151 return result;
152}
153
Sam Clegg50617cf2018-05-29 19:58:59 +0000154static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
155 return readLEB128(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000156}
157
Sam Clegg50617cf2018-05-29 19:58:59 +0000158static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
159 return readUint8(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000160}
161
Sam Clegg50617cf2018-05-29 19:58:59 +0000162static Error readInitExpr(wasm::WasmInitExpr &Expr,
163 WasmObjectFile::ReadContext &Ctx) {
164 Expr.Opcode = readOpcode(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000165
166 switch (Expr.Opcode) {
167 case wasm::WASM_OPCODE_I32_CONST:
Sam Clegg50617cf2018-05-29 19:58:59 +0000168 Expr.Value.Int32 = readVarint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000169 break;
170 case wasm::WASM_OPCODE_I64_CONST:
Sam Clegg50617cf2018-05-29 19:58:59 +0000171 Expr.Value.Int64 = readVarint64(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000172 break;
173 case wasm::WASM_OPCODE_F32_CONST:
Sam Clegg50617cf2018-05-29 19:58:59 +0000174 Expr.Value.Float32 = readFloat32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000175 break;
176 case wasm::WASM_OPCODE_F64_CONST:
Sam Clegg50617cf2018-05-29 19:58:59 +0000177 Expr.Value.Float64 = readFloat64(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000178 break;
Thomas Lively37a984b2019-01-08 06:25:55 +0000179 case wasm::WASM_OPCODE_GLOBAL_GET:
Sam Clegg50617cf2018-05-29 19:58:59 +0000180 Expr.Value.Global = readULEB128(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000181 break;
182 default:
183 return make_error<GenericBinaryError>("Invalid opcode in init_expr",
184 object_error::parse_failed);
185 }
186
Sam Clegg50617cf2018-05-29 19:58:59 +0000187 uint8_t EndOpcode = readOpcode(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000188 if (EndOpcode != wasm::WASM_OPCODE_END) {
189 return make_error<GenericBinaryError>("Invalid init_expr",
190 object_error::parse_failed);
191 }
192 return Error::success();
193}
194
Sam Clegg50617cf2018-05-29 19:58:59 +0000195static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
Derek Schuff349a48f2017-03-30 19:44:09 +0000196 wasm::WasmLimits Result;
Derek Schuff992cf172018-11-06 17:27:25 +0000197 Result.Flags = readVaruint32(Ctx);
Sam Clegg50617cf2018-05-29 19:58:59 +0000198 Result.Initial = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000199 if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
Sam Clegg50617cf2018-05-29 19:58:59 +0000200 Result.Maximum = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000201 return Result;
202}
203
Sam Clegg50617cf2018-05-29 19:58:59 +0000204static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
Sam Clegg65e284e2017-05-09 23:48:41 +0000205 wasm::WasmTable Table;
Sam Clegg50617cf2018-05-29 19:58:59 +0000206 Table.ElemType = readUint8(Ctx);
207 Table.Limits = readLimits(Ctx);
Sam Clegg65e284e2017-05-09 23:48:41 +0000208 return Table;
209}
210
Heejin Ahne2f3e502018-12-15 00:58:12 +0000211static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
212 WasmSectionOrderChecker &Checker) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000213 Section.Offset = Ctx.Ptr - Ctx.Start;
214 Section.Type = readUint8(Ctx);
Sam Cleggcb122502018-05-29 20:16:47 +0000215 LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
Sam Clegg50617cf2018-05-29 19:58:59 +0000216 uint32_t Size = readVaruint32(Ctx);
Derek Schuff7a578c92016-11-30 16:49:11 +0000217 if (Size == 0)
218 return make_error<StringError>("Zero length section",
219 object_error::parse_failed);
Sam Clegg50617cf2018-05-29 19:58:59 +0000220 if (Ctx.Ptr + Size > Ctx.End)
Vedant Kumarf9ce75b2017-10-23 18:04:34 +0000221 return make_error<StringError>("Section too large",
222 object_error::parse_failed);
Sam Cleggb068ce92018-04-12 20:31:12 +0000223 if (Section.Type == wasm::WASM_SEC_CUSTOM) {
Jonas Devlieghere7689b8d2018-08-08 16:34:03 +0000224 WasmObjectFile::ReadContext SectionCtx;
225 SectionCtx.Start = Ctx.Ptr;
226 SectionCtx.Ptr = Ctx.Ptr;
227 SectionCtx.End = Ctx.Ptr + Size;
228
229 Section.Name = readString(SectionCtx);
230
231 uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
232 Ctx.Ptr += SectionNameSize;
233 Size -= SectionNameSize;
Sam Cleggb068ce92018-04-12 20:31:12 +0000234 }
Heejin Ahne2f3e502018-12-15 00:58:12 +0000235
236 if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
237 return make_error<StringError>("Out of order section type: " +
238 llvm::to_string(Section.Type),
239 object_error::parse_failed);
240 }
241
Sam Clegg50617cf2018-05-29 19:58:59 +0000242 Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
243 Ctx.Ptr += Size;
Derek Schuff7a578c92016-11-30 16:49:11 +0000244 return Error::success();
245}
Derek Schuff7a578c92016-11-30 16:49:11 +0000246
247WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
Eugene Zelenko903f87e2017-04-21 22:03:05 +0000248 : ObjectFile(Binary::ID_Wasm, Buffer) {
Derek Schuff7a578c92016-11-30 16:49:11 +0000249 ErrorAsOutParameter ErrAsOutParam(&Err);
250 Header.Magic = getData().substr(0, 4);
251 if (Header.Magic != StringRef("\0asm", 4)) {
Heejin Ahn581d2312018-09-05 01:27:38 +0000252 Err =
253 make_error<StringError>("Bad magic number", object_error::parse_failed);
Derek Schuff7a578c92016-11-30 16:49:11 +0000254 return;
255 }
Jonas Devliegheree69aa182017-08-23 21:36:04 +0000256
Sam Clegg50617cf2018-05-29 19:58:59 +0000257 ReadContext Ctx;
258 Ctx.Start = getPtr(0);
259 Ctx.Ptr = Ctx.Start + 4;
260 Ctx.End = Ctx.Start + getData().size();
Jonas Devliegheree69aa182017-08-23 21:36:04 +0000261
Sam Clegg50617cf2018-05-29 19:58:59 +0000262 if (Ctx.Ptr + 4 > Ctx.End) {
Jonas Devliegheree69aa182017-08-23 21:36:04 +0000263 Err = make_error<StringError>("Missing version number",
264 object_error::parse_failed);
265 return;
266 }
267
Sam Clegg50617cf2018-05-29 19:58:59 +0000268 Header.Version = readUint32(Ctx);
Derek Schuff7a578c92016-11-30 16:49:11 +0000269 if (Header.Version != wasm::WasmVersion) {
270 Err = make_error<StringError>("Bad version number",
271 object_error::parse_failed);
272 return;
273 }
274
Derek Schuff349a48f2017-03-30 19:44:09 +0000275 WasmSection Sec;
Heejin Ahne2f3e502018-12-15 00:58:12 +0000276 WasmSectionOrderChecker Checker;
Sam Clegg50617cf2018-05-29 19:58:59 +0000277 while (Ctx.Ptr < Ctx.End) {
Heejin Ahne2f3e502018-12-15 00:58:12 +0000278 if ((Err = readSection(Sec, Ctx, Checker)))
Derek Schuff7a578c92016-11-30 16:49:11 +0000279 return;
Derek Schuff349a48f2017-03-30 19:44:09 +0000280 if ((Err = parseSection(Sec)))
281 return;
282
Derek Schuff7a578c92016-11-30 16:49:11 +0000283 Sections.push_back(Sec);
284 }
285}
286
Derek Schuff349a48f2017-03-30 19:44:09 +0000287Error WasmObjectFile::parseSection(WasmSection &Sec) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000288 ReadContext Ctx;
289 Ctx.Start = Sec.Content.data();
290 Ctx.End = Ctx.Start + Sec.Content.size();
291 Ctx.Ptr = Ctx.Start;
Derek Schuff349a48f2017-03-30 19:44:09 +0000292 switch (Sec.Type) {
293 case wasm::WASM_SEC_CUSTOM:
Sam Clegg50617cf2018-05-29 19:58:59 +0000294 return parseCustomSection(Sec, Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000295 case wasm::WASM_SEC_TYPE:
Sam Clegg50617cf2018-05-29 19:58:59 +0000296 return parseTypeSection(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000297 case wasm::WASM_SEC_IMPORT:
Sam Clegg50617cf2018-05-29 19:58:59 +0000298 return parseImportSection(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000299 case wasm::WASM_SEC_FUNCTION:
Sam Clegg50617cf2018-05-29 19:58:59 +0000300 return parseFunctionSection(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000301 case wasm::WASM_SEC_TABLE:
Sam Clegg50617cf2018-05-29 19:58:59 +0000302 return parseTableSection(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000303 case wasm::WASM_SEC_MEMORY:
Sam Clegg50617cf2018-05-29 19:58:59 +0000304 return parseMemorySection(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000305 case wasm::WASM_SEC_GLOBAL:
Sam Clegg50617cf2018-05-29 19:58:59 +0000306 return parseGlobalSection(Ctx);
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000307 case wasm::WASM_SEC_EVENT:
308 return parseEventSection(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000309 case wasm::WASM_SEC_EXPORT:
Sam Clegg50617cf2018-05-29 19:58:59 +0000310 return parseExportSection(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000311 case wasm::WASM_SEC_START:
Sam Clegg50617cf2018-05-29 19:58:59 +0000312 return parseStartSection(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000313 case wasm::WASM_SEC_ELEM:
Sam Clegg50617cf2018-05-29 19:58:59 +0000314 return parseElemSection(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000315 case wasm::WASM_SEC_CODE:
Sam Clegg50617cf2018-05-29 19:58:59 +0000316 return parseCodeSection(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000317 case wasm::WASM_SEC_DATA:
Sam Clegg50617cf2018-05-29 19:58:59 +0000318 return parseDataSection(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000319 default:
320 return make_error<GenericBinaryError>("Bad section type",
321 object_error::parse_failed);
322 }
323}
324
Sam Clegg45c215a2018-11-14 18:36:24 +0000325Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
326 // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
327 DylinkInfo.MemorySize = readVaruint32(Ctx);
328 DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
329 DylinkInfo.TableSize = readVaruint32(Ctx);
330 DylinkInfo.TableAlignment = readVaruint32(Ctx);
Sam Clegg559201d2018-12-12 23:40:58 +0000331 uint32_t Count = readVaruint32(Ctx);
332 while (Count--) {
333 DylinkInfo.Needed.push_back(readString(Ctx));
334 }
Sam Clegg45c215a2018-11-14 18:36:24 +0000335 if (Ctx.Ptr != Ctx.End)
336 return make_error<GenericBinaryError>("dylink section ended prematurely",
337 object_error::parse_failed);
338 return Error::success();
339}
340
Sam Clegg50617cf2018-05-29 19:58:59 +0000341Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
Sam Cleggd4e08e12018-01-12 02:11:31 +0000342 llvm::DenseSet<uint64_t> Seen;
Sam Cleggeb7fd732018-01-17 19:28:43 +0000343 if (Functions.size() != FunctionTypes.size()) {
344 return make_error<GenericBinaryError>("Names must come after code section",
345 object_error::parse_failed);
346 }
Sam Cleggd4e08e12018-01-12 02:11:31 +0000347
Sam Clegg50617cf2018-05-29 19:58:59 +0000348 while (Ctx.Ptr < Ctx.End) {
349 uint8_t Type = readUint8(Ctx);
350 uint32_t Size = readVaruint32(Ctx);
351 const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
Derek Schuff349a48f2017-03-30 19:44:09 +0000352 switch (Type) {
353 case wasm::WASM_NAMES_FUNCTION: {
Sam Clegg50617cf2018-05-29 19:58:59 +0000354 uint32_t Count = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000355 while (Count--) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000356 uint32_t Index = readVaruint32(Ctx);
Sam Cleggd4e08e12018-01-12 02:11:31 +0000357 if (!Seen.insert(Index).second)
358 return make_error<GenericBinaryError>("Function named more than once",
359 object_error::parse_failed);
Sam Clegg50617cf2018-05-29 19:58:59 +0000360 StringRef Name = readString(Ctx);
Sam Cleggeb7fd732018-01-17 19:28:43 +0000361 if (!isValidFunctionIndex(Index) || Name.empty())
362 return make_error<GenericBinaryError>("Invalid name entry",
363 object_error::parse_failed);
364 DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
Nicholas Wilsonbb033002018-04-20 17:07:24 +0000365 if (isDefinedFunctionIndex(Index))
366 getDefinedFunction(Index).DebugName = Name;
Derek Schuff349a48f2017-03-30 19:44:09 +0000367 }
368 break;
369 }
370 // Ignore local names for now
371 case wasm::WASM_NAMES_LOCAL:
372 default:
Sam Clegg50617cf2018-05-29 19:58:59 +0000373 Ctx.Ptr += Size;
Derek Schuff349a48f2017-03-30 19:44:09 +0000374 break;
375 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000376 if (Ctx.Ptr != SubSectionEnd)
Heejin Ahn581d2312018-09-05 01:27:38 +0000377 return make_error<GenericBinaryError>(
378 "Name sub-section ended prematurely", object_error::parse_failed);
Derek Schuff349a48f2017-03-30 19:44:09 +0000379 }
380
Sam Clegg50617cf2018-05-29 19:58:59 +0000381 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +0000382 return make_error<GenericBinaryError>("Name section ended prematurely",
383 object_error::parse_failed);
384 return Error::success();
385}
386
Sam Clegg50617cf2018-05-29 19:58:59 +0000387Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
Sam Clegg08da5c52017-06-27 20:40:53 +0000388 HasLinkingSection = true;
Sam Cleggeb7fd732018-01-17 19:28:43 +0000389 if (Functions.size() != FunctionTypes.size()) {
390 return make_error<GenericBinaryError>(
Heejin Ahn581d2312018-09-05 01:27:38 +0000391 "Linking data must come after code section",
392 object_error::parse_failed);
Sam Cleggeb7fd732018-01-17 19:28:43 +0000393 }
Sam Clegg9f8cb472017-09-06 22:05:41 +0000394
Sam Clegg50617cf2018-05-29 19:58:59 +0000395 LinkingData.Version = readVaruint32(Ctx);
Sam Clegg14598cb2018-04-26 18:15:32 +0000396 if (LinkingData.Version != wasm::WasmMetadataVersion) {
397 return make_error<GenericBinaryError>(
398 "Unexpected metadata version: " + Twine(LinkingData.Version) +
399 " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
400 object_error::parse_failed);
401 }
402
Sam Clegg50617cf2018-05-29 19:58:59 +0000403 const uint8_t *OrigEnd = Ctx.End;
404 while (Ctx.Ptr < OrigEnd) {
405 Ctx.End = OrigEnd;
406 uint8_t Type = readUint8(Ctx);
407 uint32_t Size = readVaruint32(Ctx);
Sam Cleggcb122502018-05-29 20:16:47 +0000408 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
409 << "\n");
Sam Clegg50617cf2018-05-29 19:58:59 +0000410 Ctx.End = Ctx.Ptr + Size;
Sam Clegg1e975c12017-06-20 04:04:59 +0000411 switch (Type) {
Sam Cleggd5784792018-02-23 05:08:34 +0000412 case wasm::WASM_SYMBOL_TABLE:
Sam Clegg50617cf2018-05-29 19:58:59 +0000413 if (Error Err = parseLinkingSectionSymtab(Ctx))
Sam Cleggd5784792018-02-23 05:08:34 +0000414 return Err;
Sam Clegg1e975c12017-06-20 04:04:59 +0000415 break;
Sam Clegge2864172017-09-29 16:50:08 +0000416 case wasm::WASM_SEGMENT_INFO: {
Sam Clegg50617cf2018-05-29 19:58:59 +0000417 uint32_t Count = readVaruint32(Ctx);
Sam Clegg81e38242017-09-20 19:03:35 +0000418 if (Count > DataSegments.size())
419 return make_error<GenericBinaryError>("Too many segment names",
420 object_error::parse_failed);
Sam Clegge2864172017-09-29 16:50:08 +0000421 for (uint32_t i = 0; i < Count; i++) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000422 DataSegments[i].Data.Name = readString(Ctx);
423 DataSegments[i].Data.Alignment = readVaruint32(Ctx);
424 DataSegments[i].Data.Flags = readVaruint32(Ctx);
Sam Clegge2864172017-09-29 16:50:08 +0000425 }
Sam Clegg81e38242017-09-20 19:03:35 +0000426 break;
427 }
Sam Clegge1acb562017-12-14 21:10:03 +0000428 case wasm::WASM_INIT_FUNCS: {
Sam Clegg50617cf2018-05-29 19:58:59 +0000429 uint32_t Count = readVaruint32(Ctx);
Sam Clegge1acb562017-12-14 21:10:03 +0000430 LinkingData.InitFunctions.reserve(Count);
431 for (uint32_t i = 0; i < Count; i++) {
432 wasm::WasmInitFunc Init;
Sam Clegg50617cf2018-05-29 19:58:59 +0000433 Init.Priority = readVaruint32(Ctx);
434 Init.Symbol = readVaruint32(Ctx);
Nicholas Wilsone0316ce2018-03-05 13:32:38 +0000435 if (!isValidFunctionSymbol(Init.Symbol))
Sam Cleggd5784792018-02-23 05:08:34 +0000436 return make_error<GenericBinaryError>("Invalid function symbol: " +
437 Twine(Init.Symbol),
Sam Clegge1acb562017-12-14 21:10:03 +0000438 object_error::parse_failed);
439 LinkingData.InitFunctions.emplace_back(Init);
440 }
441 break;
442 }
Sam Clegge92250a2018-01-09 23:43:14 +0000443 case wasm::WASM_COMDAT_INFO:
Sam Clegg50617cf2018-05-29 19:58:59 +0000444 if (Error Err = parseLinkingSectionComdat(Ctx))
Sam Clegge92250a2018-01-09 23:43:14 +0000445 return Err;
446 break;
Sam Clegg1e975c12017-06-20 04:04:59 +0000447 default:
Sam Clegg50617cf2018-05-29 19:58:59 +0000448 Ctx.Ptr += Size;
Sam Clegg1e975c12017-06-20 04:04:59 +0000449 break;
450 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000451 if (Ctx.Ptr != Ctx.End)
Sam Clegg1e975c12017-06-20 04:04:59 +0000452 return make_error<GenericBinaryError>(
453 "Linking sub-section ended prematurely", object_error::parse_failed);
454 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000455 if (Ctx.Ptr != OrigEnd)
Sam Clegg1e975c12017-06-20 04:04:59 +0000456 return make_error<GenericBinaryError>("Linking section ended prematurely",
457 object_error::parse_failed);
458 return Error::success();
459}
460
Sam Clegg50617cf2018-05-29 19:58:59 +0000461Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
462 uint32_t Count = readVaruint32(Ctx);
Sam Cleggd5784792018-02-23 05:08:34 +0000463 LinkingData.SymbolTable.reserve(Count);
464 Symbols.reserve(Count);
465 StringSet<> SymbolNames;
466
467 std::vector<wasm::WasmImport *> ImportedGlobals;
468 std::vector<wasm::WasmImport *> ImportedFunctions;
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000469 std::vector<wasm::WasmImport *> ImportedEvents;
Sam Cleggd5784792018-02-23 05:08:34 +0000470 ImportedGlobals.reserve(Imports.size());
471 ImportedFunctions.reserve(Imports.size());
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000472 ImportedEvents.reserve(Imports.size());
Sam Cleggd5784792018-02-23 05:08:34 +0000473 for (auto &I : Imports) {
474 if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
475 ImportedFunctions.emplace_back(&I);
476 else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
477 ImportedGlobals.emplace_back(&I);
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000478 else if (I.Kind == wasm::WASM_EXTERNAL_EVENT)
479 ImportedEvents.emplace_back(&I);
Sam Cleggd5784792018-02-23 05:08:34 +0000480 }
481
482 while (Count--) {
483 wasm::WasmSymbolInfo Info;
Heejin Ahn0123db82018-12-08 06:16:13 +0000484 const wasm::WasmSignature *Signature = nullptr;
Sam Cleggd5784792018-02-23 05:08:34 +0000485 const wasm::WasmGlobalType *GlobalType = nullptr;
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000486 const wasm::WasmEventType *EventType = nullptr;
Sam Cleggd5784792018-02-23 05:08:34 +0000487
Sam Clegg50617cf2018-05-29 19:58:59 +0000488 Info.Kind = readUint8(Ctx);
489 Info.Flags = readVaruint32(Ctx);
Sam Cleggd5784792018-02-23 05:08:34 +0000490 bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
491
492 switch (Info.Kind) {
493 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
Sam Clegg50617cf2018-05-29 19:58:59 +0000494 Info.ElementIndex = readVaruint32(Ctx);
Sam Cleggd5784792018-02-23 05:08:34 +0000495 if (!isValidFunctionIndex(Info.ElementIndex) ||
496 IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
497 return make_error<GenericBinaryError>("invalid function symbol index",
498 object_error::parse_failed);
499 if (IsDefined) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000500 Info.Name = readString(Ctx);
Sam Cleggd5784792018-02-23 05:08:34 +0000501 unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
Heejin Ahn0123db82018-12-08 06:16:13 +0000502 Signature = &Signatures[FunctionTypes[FuncIndex]];
Nicholas Wilson54767672018-03-05 12:16:32 +0000503 wasm::WasmFunction &Function = Functions[FuncIndex];
Nicholas Wilsonbb033002018-04-20 17:07:24 +0000504 if (Function.SymbolName.empty())
505 Function.SymbolName = Info.Name;
Sam Cleggd5784792018-02-23 05:08:34 +0000506 } else {
507 wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
Hans Wennborg831b2042019-02-12 12:27:08 +0000508 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
509 Info.Name = readString(Ctx);
510 else
511 Info.Name = Import.Field;
Heejin Ahn0123db82018-12-08 06:16:13 +0000512 Signature = &Signatures[Import.SigIndex];
Hans Wennborg831b2042019-02-12 12:27:08 +0000513 Info.ImportName = Import.Field;
514 Info.ImportModule = Import.Module;
Sam Cleggd5784792018-02-23 05:08:34 +0000515 }
516 break;
517
518 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
Sam Clegg50617cf2018-05-29 19:58:59 +0000519 Info.ElementIndex = readVaruint32(Ctx);
Sam Cleggd5784792018-02-23 05:08:34 +0000520 if (!isValidGlobalIndex(Info.ElementIndex) ||
521 IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
522 return make_error<GenericBinaryError>("invalid global symbol index",
523 object_error::parse_failed);
Heejin Ahn581d2312018-09-05 01:27:38 +0000524 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
525 wasm::WASM_SYMBOL_BINDING_WEAK)
Nicholas Wilson44818a32018-03-09 16:30:44 +0000526 return make_error<GenericBinaryError>("undefined weak global symbol",
527 object_error::parse_failed);
Sam Cleggd5784792018-02-23 05:08:34 +0000528 if (IsDefined) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000529 Info.Name = readString(Ctx);
Sam Cleggd5784792018-02-23 05:08:34 +0000530 unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
Nicholas Wilson54767672018-03-05 12:16:32 +0000531 wasm::WasmGlobal &Global = Globals[GlobalIndex];
532 GlobalType = &Global.Type;
Nicholas Wilsonbb033002018-04-20 17:07:24 +0000533 if (Global.SymbolName.empty())
534 Global.SymbolName = Info.Name;
Sam Cleggd5784792018-02-23 05:08:34 +0000535 } else {
536 wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
Hans Wennborg831b2042019-02-12 12:27:08 +0000537 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
538 Info.Name = readString(Ctx);
539 else
540 Info.Name = Import.Field;
Sam Cleggd5784792018-02-23 05:08:34 +0000541 GlobalType = &Import.Global;
Hans Wennborg831b2042019-02-12 12:27:08 +0000542 Info.ImportName = Import.Field;
543 Info.ImportModule = Import.Module;
Sam Cleggd5784792018-02-23 05:08:34 +0000544 }
545 break;
546
547 case wasm::WASM_SYMBOL_TYPE_DATA:
Sam Clegg50617cf2018-05-29 19:58:59 +0000548 Info.Name = readString(Ctx);
Sam Cleggd5784792018-02-23 05:08:34 +0000549 if (IsDefined) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000550 uint32_t Index = readVaruint32(Ctx);
Sam Cleggd5784792018-02-23 05:08:34 +0000551 if (Index >= DataSegments.size())
552 return make_error<GenericBinaryError>("invalid data symbol index",
553 object_error::parse_failed);
Sam Clegg50617cf2018-05-29 19:58:59 +0000554 uint32_t Offset = readVaruint32(Ctx);
555 uint32_t Size = readVaruint32(Ctx);
Sam Cleggd5784792018-02-23 05:08:34 +0000556 if (Offset + Size > DataSegments[Index].Data.Content.size())
Nicholas Wilsonc28e9492018-02-28 14:03:18 +0000557 return make_error<GenericBinaryError>("invalid data symbol offset",
Sam Cleggd5784792018-02-23 05:08:34 +0000558 object_error::parse_failed);
559 Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
560 }
561 break;
562
Sam Cleggdb159752018-04-26 19:27:28 +0000563 case wasm::WASM_SYMBOL_TYPE_SECTION: {
Sam Cleggbfeca0b2018-04-27 00:17:21 +0000564 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
565 wasm::WASM_SYMBOL_BINDING_LOCAL)
Sam Clegg4f72fc12018-04-27 00:17:24 +0000566 return make_error<GenericBinaryError>(
567 "Section symbols must have local binding",
568 object_error::parse_failed);
Sam Clegg50617cf2018-05-29 19:58:59 +0000569 Info.ElementIndex = readVaruint32(Ctx);
Sam Cleggdb159752018-04-26 19:27:28 +0000570 // Use somewhat unique section name as symbol name.
571 StringRef SectionName = Sections[Info.ElementIndex].Name;
572 Info.Name = SectionName;
573 break;
574 }
575
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000576 case wasm::WASM_SYMBOL_TYPE_EVENT: {
577 Info.ElementIndex = readVaruint32(Ctx);
578 if (!isValidEventIndex(Info.ElementIndex) ||
579 IsDefined != isDefinedEventIndex(Info.ElementIndex))
580 return make_error<GenericBinaryError>("invalid event symbol index",
581 object_error::parse_failed);
582 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
583 wasm::WASM_SYMBOL_BINDING_WEAK)
584 return make_error<GenericBinaryError>("undefined weak global symbol",
585 object_error::parse_failed);
586 if (IsDefined) {
587 Info.Name = readString(Ctx);
588 unsigned EventIndex = Info.ElementIndex - NumImportedEvents;
589 wasm::WasmEvent &Event = Events[EventIndex];
Heejin Ahn0123db82018-12-08 06:16:13 +0000590 Signature = &Signatures[Event.Type.SigIndex];
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000591 EventType = &Event.Type;
592 if (Event.SymbolName.empty())
593 Event.SymbolName = Info.Name;
594
595 } else {
596 wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
Hans Wennborg831b2042019-02-12 12:27:08 +0000597 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
598 Info.Name = readString(Ctx);
599 else
600 Info.Name = Import.Field;
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000601 EventType = &Import.Event;
Heejin Ahn0123db82018-12-08 06:16:13 +0000602 Signature = &Signatures[EventType->SigIndex];
Hans Wennborg831b2042019-02-12 12:27:08 +0000603 Info.ImportName = Import.Field;
604 Info.ImportModule = Import.Module;
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000605 }
606 break;
607 }
608
Sam Cleggd5784792018-02-23 05:08:34 +0000609 default:
610 return make_error<GenericBinaryError>("Invalid symbol type",
611 object_error::parse_failed);
612 }
613
614 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
615 wasm::WASM_SYMBOL_BINDING_LOCAL &&
616 !SymbolNames.insert(Info.Name).second)
617 return make_error<GenericBinaryError>("Duplicate symbol name " +
618 Twine(Info.Name),
619 object_error::parse_failed);
620 LinkingData.SymbolTable.emplace_back(Info);
Heejin Ahn0123db82018-12-08 06:16:13 +0000621 Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, EventType,
622 Signature);
Nicola Zaghen0818e782018-05-14 12:53:11 +0000623 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
Sam Cleggd5784792018-02-23 05:08:34 +0000624 }
625
626 return Error::success();
627}
628
Sam Clegg50617cf2018-05-29 19:58:59 +0000629Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
630 uint32_t ComdatCount = readVaruint32(Ctx);
Sam Clegge92250a2018-01-09 23:43:14 +0000631 StringSet<> ComdatSet;
Nicholas Wilsondc84b5c2018-03-14 15:44:45 +0000632 for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000633 StringRef Name = readString(Ctx);
Sam Clegge92250a2018-01-09 23:43:14 +0000634 if (Name.empty() || !ComdatSet.insert(Name).second)
Heejin Ahn581d2312018-09-05 01:27:38 +0000635 return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
636 Twine(Name),
Sam Clegge92250a2018-01-09 23:43:14 +0000637 object_error::parse_failed);
Nicholas Wilsondc84b5c2018-03-14 15:44:45 +0000638 LinkingData.Comdats.emplace_back(Name);
Sam Clegg50617cf2018-05-29 19:58:59 +0000639 uint32_t Flags = readVaruint32(Ctx);
Sam Clegge92250a2018-01-09 23:43:14 +0000640 if (Flags != 0)
641 return make_error<GenericBinaryError>("Unsupported COMDAT flags",
642 object_error::parse_failed);
643
Sam Clegg50617cf2018-05-29 19:58:59 +0000644 uint32_t EntryCount = readVaruint32(Ctx);
Sam Clegge92250a2018-01-09 23:43:14 +0000645 while (EntryCount--) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000646 unsigned Kind = readVaruint32(Ctx);
647 unsigned Index = readVaruint32(Ctx);
Sam Clegge92250a2018-01-09 23:43:14 +0000648 switch (Kind) {
649 default:
650 return make_error<GenericBinaryError>("Invalid COMDAT entry type",
651 object_error::parse_failed);
652 case wasm::WASM_COMDAT_DATA:
653 if (Index >= DataSegments.size())
Heejin Ahn581d2312018-09-05 01:27:38 +0000654 return make_error<GenericBinaryError>(
655 "COMDAT data index out of range", object_error::parse_failed);
Nicholas Wilsondc84b5c2018-03-14 15:44:45 +0000656 if (DataSegments[Index].Data.Comdat != UINT32_MAX)
Sam Clegge92250a2018-01-09 23:43:14 +0000657 return make_error<GenericBinaryError>("Data segment in two COMDATs",
658 object_error::parse_failed);
Nicholas Wilsondc84b5c2018-03-14 15:44:45 +0000659 DataSegments[Index].Data.Comdat = ComdatIndex;
Sam Clegge92250a2018-01-09 23:43:14 +0000660 break;
661 case wasm::WASM_COMDAT_FUNCTION:
Sam Clegg9a49b21c2018-01-24 01:27:17 +0000662 if (!isDefinedFunctionIndex(Index))
Heejin Ahn581d2312018-09-05 01:27:38 +0000663 return make_error<GenericBinaryError>(
664 "COMDAT function index out of range", object_error::parse_failed);
Nicholas Wilsondc84b5c2018-03-14 15:44:45 +0000665 if (getDefinedFunction(Index).Comdat != UINT32_MAX)
Sam Clegge92250a2018-01-09 23:43:14 +0000666 return make_error<GenericBinaryError>("Function in two COMDATs",
667 object_error::parse_failed);
Nicholas Wilsondc84b5c2018-03-14 15:44:45 +0000668 getDefinedFunction(Index).Comdat = ComdatIndex;
Sam Clegge92250a2018-01-09 23:43:14 +0000669 break;
670 }
671 }
672 }
673 return Error::success();
674}
675
Sam Clegg50617cf2018-05-29 19:58:59 +0000676Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
677 uint32_t SectionIndex = readVaruint32(Ctx);
Sam Clegg194a4e02018-04-24 18:11:36 +0000678 if (SectionIndex >= Sections.size())
679 return make_error<GenericBinaryError>("Invalid section index",
Derek Schuff349a48f2017-03-30 19:44:09 +0000680 object_error::parse_failed);
Heejin Ahn581d2312018-09-05 01:27:38 +0000681 WasmSection &Section = Sections[SectionIndex];
Sam Clegg50617cf2018-05-29 19:58:59 +0000682 uint32_t RelocCount = readVaruint32(Ctx);
Sam Clegg194a4e02018-04-24 18:11:36 +0000683 uint32_t EndOffset = Section.Content.size();
Sam Cleggb4dc85b2018-08-22 17:27:31 +0000684 uint32_t PreviousOffset = 0;
Derek Schuff349a48f2017-03-30 19:44:09 +0000685 while (RelocCount--) {
Nicholas Wilsone0316ce2018-03-05 13:32:38 +0000686 wasm::WasmRelocation Reloc = {};
Sam Clegg50617cf2018-05-29 19:58:59 +0000687 Reloc.Type = readVaruint32(Ctx);
688 Reloc.Offset = readVaruint32(Ctx);
Sam Cleggb4dc85b2018-08-22 17:27:31 +0000689 if (Reloc.Offset < PreviousOffset)
690 return make_error<GenericBinaryError>("Relocations not in offset order",
691 object_error::parse_failed);
692 PreviousOffset = Reloc.Offset;
Sam Clegg50617cf2018-05-29 19:58:59 +0000693 Reloc.Index = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000694 switch (Reloc.Type) {
695 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
696 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
697 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
Nicholas Wilsone0316ce2018-03-05 13:32:38 +0000698 if (!isValidFunctionSymbol(Reloc.Index))
699 return make_error<GenericBinaryError>("Bad relocation function index",
700 object_error::parse_failed);
701 break;
Sam Cleggd420e402017-04-26 00:02:31 +0000702 case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
Nicholas Wilsone0316ce2018-03-05 13:32:38 +0000703 if (Reloc.Index >= Signatures.size())
704 return make_error<GenericBinaryError>("Bad relocation type index",
705 object_error::parse_failed);
706 break;
Sam Clegg46016f22017-06-16 23:59:10 +0000707 case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
Nicholas Wilsone0316ce2018-03-05 13:32:38 +0000708 if (!isValidGlobalSymbol(Reloc.Index))
709 return make_error<GenericBinaryError>("Bad relocation global index",
710 object_error::parse_failed);
Derek Schuff349a48f2017-03-30 19:44:09 +0000711 break;
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000712 case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
713 if (!isValidEventSymbol(Reloc.Index))
714 return make_error<GenericBinaryError>("Bad relocation event index",
715 object_error::parse_failed);
716 break;
Sam Clegg8b020d72017-09-01 17:32:01 +0000717 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
718 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
719 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
Nicholas Wilsone0316ce2018-03-05 13:32:38 +0000720 if (!isValidDataSymbol(Reloc.Index))
721 return make_error<GenericBinaryError>("Bad relocation data index",
722 object_error::parse_failed);
Sam Clegg50617cf2018-05-29 19:58:59 +0000723 Reloc.Addend = readVarint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000724 break;
Sam Cleggdb159752018-04-26 19:27:28 +0000725 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
726 if (!isValidFunctionSymbol(Reloc.Index))
727 return make_error<GenericBinaryError>("Bad relocation function index",
728 object_error::parse_failed);
Sam Clegg50617cf2018-05-29 19:58:59 +0000729 Reloc.Addend = readVarint32(Ctx);
Sam Cleggdb159752018-04-26 19:27:28 +0000730 break;
731 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
732 if (!isValidSectionSymbol(Reloc.Index))
733 return make_error<GenericBinaryError>("Bad relocation section index",
734 object_error::parse_failed);
Sam Clegg50617cf2018-05-29 19:58:59 +0000735 Reloc.Addend = readVarint32(Ctx);
Sam Cleggdb159752018-04-26 19:27:28 +0000736 break;
Derek Schuff349a48f2017-03-30 19:44:09 +0000737 default:
Sam Clegg46016f22017-06-16 23:59:10 +0000738 return make_error<GenericBinaryError>("Bad relocation type: " +
739 Twine(Reloc.Type),
Derek Schuff349a48f2017-03-30 19:44:09 +0000740 object_error::parse_failed);
741 }
Nicholas Wilsone0316ce2018-03-05 13:32:38 +0000742
743 // Relocations must fit inside the section, and must appear in order. They
744 // also shouldn't overlap a function/element boundary, but we don't bother
745 // to check that.
746 uint64_t Size = 5;
747 if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 ||
Sam Cleggdb159752018-04-26 19:27:28 +0000748 Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32 ||
749 Reloc.Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32 ||
750 Reloc.Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32)
Nicholas Wilsone0316ce2018-03-05 13:32:38 +0000751 Size = 4;
Sam Clegg068c05a2018-03-06 07:13:10 +0000752 if (Reloc.Offset + Size > EndOffset)
Nicholas Wilsone0316ce2018-03-05 13:32:38 +0000753 return make_error<GenericBinaryError>("Bad relocation offset",
754 object_error::parse_failed);
Nicholas Wilsone0316ce2018-03-05 13:32:38 +0000755
Sam Clegg194a4e02018-04-24 18:11:36 +0000756 Section.Relocations.push_back(Reloc);
Derek Schuff349a48f2017-03-30 19:44:09 +0000757 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000758 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +0000759 return make_error<GenericBinaryError>("Reloc section ended prematurely",
760 object_error::parse_failed);
761 return Error::success();
762}
763
Sam Clegg50617cf2018-05-29 19:58:59 +0000764Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
Sam Clegg45c215a2018-11-14 18:36:24 +0000765 if (Sec.Name == "dylink") {
766 if (Error Err = parseDylinkSection(Ctx))
767 return Err;
768 } else if (Sec.Name == "name") {
Sam Clegg50617cf2018-05-29 19:58:59 +0000769 if (Error Err = parseNameSection(Ctx))
Derek Schuff349a48f2017-03-30 19:44:09 +0000770 return Err;
Sam Clegg1e975c12017-06-20 04:04:59 +0000771 } else if (Sec.Name == "linking") {
Sam Clegg50617cf2018-05-29 19:58:59 +0000772 if (Error Err = parseLinkingSection(Ctx))
Sam Clegg1e975c12017-06-20 04:04:59 +0000773 return Err;
Derek Schuff349a48f2017-03-30 19:44:09 +0000774 } else if (Sec.Name.startswith("reloc.")) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000775 if (Error Err = parseRelocSection(Sec.Name, Ctx))
Derek Schuff349a48f2017-03-30 19:44:09 +0000776 return Err;
777 }
778 return Error::success();
779}
780
Sam Clegg50617cf2018-05-29 19:58:59 +0000781Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
782 uint32_t Count = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000783 Signatures.reserve(Count);
784 while (Count--) {
785 wasm::WasmSignature Sig;
Sam Clegg50617cf2018-05-29 19:58:59 +0000786 uint8_t Form = readUint8(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000787 if (Form != wasm::WASM_TYPE_FUNC) {
788 return make_error<GenericBinaryError>("Invalid signature type",
789 object_error::parse_failed);
790 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000791 uint32_t ParamCount = readVaruint32(Ctx);
Derek Schuffab9755b2018-10-03 22:22:48 +0000792 Sig.Params.reserve(ParamCount);
Derek Schuff349a48f2017-03-30 19:44:09 +0000793 while (ParamCount--) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000794 uint32_t ParamType = readUint8(Ctx);
Derek Schuffab9755b2018-10-03 22:22:48 +0000795 Sig.Params.push_back(wasm::ValType(ParamType));
Derek Schuff349a48f2017-03-30 19:44:09 +0000796 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000797 uint32_t ReturnCount = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000798 if (ReturnCount) {
799 if (ReturnCount != 1) {
800 return make_error<GenericBinaryError>(
801 "Multiple return types not supported", object_error::parse_failed);
802 }
Derek Schuffab9755b2018-10-03 22:22:48 +0000803 Sig.Returns.push_back(wasm::ValType(readUint8(Ctx)));
Derek Schuff349a48f2017-03-30 19:44:09 +0000804 }
Derek Schuffab9755b2018-10-03 22:22:48 +0000805 Signatures.push_back(std::move(Sig));
Derek Schuff349a48f2017-03-30 19:44:09 +0000806 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000807 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +0000808 return make_error<GenericBinaryError>("Type section ended prematurely",
809 object_error::parse_failed);
810 return Error::success();
811}
812
Sam Clegg50617cf2018-05-29 19:58:59 +0000813Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
814 uint32_t Count = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000815 Imports.reserve(Count);
Sam Clegg740b80d2017-05-04 19:32:43 +0000816 for (uint32_t i = 0; i < Count; i++) {
Derek Schuff349a48f2017-03-30 19:44:09 +0000817 wasm::WasmImport Im;
Sam Clegg50617cf2018-05-29 19:58:59 +0000818 Im.Module = readString(Ctx);
819 Im.Field = readString(Ctx);
820 Im.Kind = readUint8(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000821 switch (Im.Kind) {
822 case wasm::WASM_EXTERNAL_FUNCTION:
Sam Clegg209d3c22017-08-31 21:43:45 +0000823 NumImportedFunctions++;
Sam Clegg50617cf2018-05-29 19:58:59 +0000824 Im.SigIndex = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000825 break;
826 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg209d3c22017-08-31 21:43:45 +0000827 NumImportedGlobals++;
Sam Clegg50617cf2018-05-29 19:58:59 +0000828 Im.Global.Type = readUint8(Ctx);
829 Im.Global.Mutable = readVaruint1(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000830 break;
Sam Clegg65e284e2017-05-09 23:48:41 +0000831 case wasm::WASM_EXTERNAL_MEMORY:
Sam Clegg50617cf2018-05-29 19:58:59 +0000832 Im.Memory = readLimits(Ctx);
Sam Clegg65e284e2017-05-09 23:48:41 +0000833 break;
834 case wasm::WASM_EXTERNAL_TABLE:
Sam Clegg50617cf2018-05-29 19:58:59 +0000835 Im.Table = readTable(Ctx);
Thomas Lively37a984b2019-01-08 06:25:55 +0000836 if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF)
Sam Clegg65e284e2017-05-09 23:48:41 +0000837 return make_error<GenericBinaryError>("Invalid table element type",
838 object_error::parse_failed);
Sam Clegg65e284e2017-05-09 23:48:41 +0000839 break;
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000840 case wasm::WASM_EXTERNAL_EVENT:
841 NumImportedEvents++;
842 Im.Event.Attribute = readVarint32(Ctx);
843 Im.Event.SigIndex = readVarint32(Ctx);
844 break;
Derek Schuff349a48f2017-03-30 19:44:09 +0000845 default:
Heejin Ahn581d2312018-09-05 01:27:38 +0000846 return make_error<GenericBinaryError>("Unexpected import kind",
847 object_error::parse_failed);
Derek Schuff349a48f2017-03-30 19:44:09 +0000848 }
849 Imports.push_back(Im);
850 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000851 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +0000852 return make_error<GenericBinaryError>("Import section ended prematurely",
853 object_error::parse_failed);
854 return Error::success();
855}
856
Sam Clegg50617cf2018-05-29 19:58:59 +0000857Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
858 uint32_t Count = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000859 FunctionTypes.reserve(Count);
Nicholas Wilson22b62da2018-03-02 14:35:29 +0000860 uint32_t NumTypes = Signatures.size();
Derek Schuff349a48f2017-03-30 19:44:09 +0000861 while (Count--) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000862 uint32_t Type = readVaruint32(Ctx);
Nicholas Wilson22b62da2018-03-02 14:35:29 +0000863 if (Type >= NumTypes)
864 return make_error<GenericBinaryError>("Invalid function type",
865 object_error::parse_failed);
866 FunctionTypes.push_back(Type);
Derek Schuff349a48f2017-03-30 19:44:09 +0000867 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000868 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +0000869 return make_error<GenericBinaryError>("Function section ended prematurely",
870 object_error::parse_failed);
871 return Error::success();
872}
873
Sam Clegg50617cf2018-05-29 19:58:59 +0000874Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
875 uint32_t Count = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000876 Tables.reserve(Count);
877 while (Count--) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000878 Tables.push_back(readTable(Ctx));
Thomas Lively37a984b2019-01-08 06:25:55 +0000879 if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) {
Derek Schuff349a48f2017-03-30 19:44:09 +0000880 return make_error<GenericBinaryError>("Invalid table element type",
881 object_error::parse_failed);
882 }
Derek Schuff349a48f2017-03-30 19:44:09 +0000883 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000884 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +0000885 return make_error<GenericBinaryError>("Table section ended prematurely",
886 object_error::parse_failed);
887 return Error::success();
888}
889
Sam Clegg50617cf2018-05-29 19:58:59 +0000890Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
891 uint32_t Count = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000892 Memories.reserve(Count);
893 while (Count--) {
Sam Clegg50617cf2018-05-29 19:58:59 +0000894 Memories.push_back(readLimits(Ctx));
Derek Schuff349a48f2017-03-30 19:44:09 +0000895 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000896 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +0000897 return make_error<GenericBinaryError>("Memory section ended prematurely",
898 object_error::parse_failed);
899 return Error::success();
900}
901
Sam Clegg50617cf2018-05-29 19:58:59 +0000902Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
Sam Cleggd5784792018-02-23 05:08:34 +0000903 GlobalSection = Sections.size();
Sam Clegg50617cf2018-05-29 19:58:59 +0000904 uint32_t Count = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000905 Globals.reserve(Count);
906 while (Count--) {
907 wasm::WasmGlobal Global;
Sam Clegg6b54fc32018-01-09 21:38:53 +0000908 Global.Index = NumImportedGlobals + Globals.size();
Sam Clegg50617cf2018-05-29 19:58:59 +0000909 Global.Type.Type = readUint8(Ctx);
910 Global.Type.Mutable = readVaruint1(Ctx);
911 if (Error Err = readInitExpr(Global.InitExpr, Ctx))
Derek Schuff349a48f2017-03-30 19:44:09 +0000912 return Err;
Derek Schuff349a48f2017-03-30 19:44:09 +0000913 Globals.push_back(Global);
914 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000915 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +0000916 return make_error<GenericBinaryError>("Global section ended prematurely",
917 object_error::parse_failed);
918 return Error::success();
919}
920
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000921Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
922 EventSection = Sections.size();
923 uint32_t Count = readVarint32(Ctx);
924 Events.reserve(Count);
925 while (Count--) {
926 wasm::WasmEvent Event;
927 Event.Index = NumImportedEvents + Events.size();
928 Event.Type.Attribute = readVaruint32(Ctx);
929 Event.Type.SigIndex = readVarint32(Ctx);
930 Events.push_back(Event);
931 }
932
933 if (Ctx.Ptr != Ctx.End)
934 return make_error<GenericBinaryError>("Event section ended prematurely",
935 object_error::parse_failed);
936 return Error::success();
937}
938
Sam Clegg50617cf2018-05-29 19:58:59 +0000939Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
940 uint32_t Count = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000941 Exports.reserve(Count);
Sam Clegg740b80d2017-05-04 19:32:43 +0000942 for (uint32_t i = 0; i < Count; i++) {
Derek Schuff349a48f2017-03-30 19:44:09 +0000943 wasm::WasmExport Ex;
Sam Clegg50617cf2018-05-29 19:58:59 +0000944 Ex.Name = readString(Ctx);
945 Ex.Kind = readUint8(Ctx);
946 Ex.Index = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +0000947 switch (Ex.Kind) {
948 case wasm::WASM_EXTERNAL_FUNCTION:
Sam Clegg9a49b21c2018-01-24 01:27:17 +0000949 if (!isValidFunctionIndex(Ex.Index))
Sam Clegg209d3c22017-08-31 21:43:45 +0000950 return make_error<GenericBinaryError>("Invalid function export",
951 object_error::parse_failed);
Derek Schuff349a48f2017-03-30 19:44:09 +0000952 break;
Sam Cleggd5784792018-02-23 05:08:34 +0000953 case wasm::WASM_EXTERNAL_GLOBAL:
954 if (!isValidGlobalIndex(Ex.Index))
Sam Clegg209d3c22017-08-31 21:43:45 +0000955 return make_error<GenericBinaryError>("Invalid global export",
956 object_error::parse_failed);
Derek Schuff349a48f2017-03-30 19:44:09 +0000957 break;
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000958 case wasm::WASM_EXTERNAL_EVENT:
959 if (!isValidEventIndex(Ex.Index))
960 return make_error<GenericBinaryError>("Invalid event export",
961 object_error::parse_failed);
962 break;
Sam Clegg65e284e2017-05-09 23:48:41 +0000963 case wasm::WASM_EXTERNAL_MEMORY:
964 case wasm::WASM_EXTERNAL_TABLE:
965 break;
Derek Schuff349a48f2017-03-30 19:44:09 +0000966 default:
Heejin Ahn581d2312018-09-05 01:27:38 +0000967 return make_error<GenericBinaryError>("Unexpected export kind",
968 object_error::parse_failed);
Derek Schuff349a48f2017-03-30 19:44:09 +0000969 }
Sam Clegg1e975c12017-06-20 04:04:59 +0000970 Exports.push_back(Ex);
Derek Schuff349a48f2017-03-30 19:44:09 +0000971 }
Sam Clegg50617cf2018-05-29 19:58:59 +0000972 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +0000973 return make_error<GenericBinaryError>("Export section ended prematurely",
974 object_error::parse_failed);
975 return Error::success();
976}
977
Sam Clegge1acb562017-12-14 21:10:03 +0000978bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
Sam Cleggd5784792018-02-23 05:08:34 +0000979 return Index < NumImportedFunctions + FunctionTypes.size();
Sam Clegge1acb562017-12-14 21:10:03 +0000980}
981
Sam Clegg9a49b21c2018-01-24 01:27:17 +0000982bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
983 return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
984}
985
Sam Cleggd5784792018-02-23 05:08:34 +0000986bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
987 return Index < NumImportedGlobals + Globals.size();
988}
989
990bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
991 return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
992}
993
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000994bool WasmObjectFile::isValidEventIndex(uint32_t Index) const {
995 return Index < NumImportedEvents + Events.size();
996}
997
998bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const {
999 return Index >= NumImportedEvents && isValidEventIndex(Index);
1000}
1001
Nicholas Wilsone0316ce2018-03-05 13:32:38 +00001002bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
Sam Cleggd5784792018-02-23 05:08:34 +00001003 return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1004}
1005
Nicholas Wilsone0316ce2018-03-05 13:32:38 +00001006bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1007 return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1008}
1009
Heejin Ahn8bcdd042018-11-14 02:46:21 +00001010bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const {
1011 return Index < Symbols.size() && Symbols[Index].isTypeEvent();
1012}
1013
Nicholas Wilsone0316ce2018-03-05 13:32:38 +00001014bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1015 return Index < Symbols.size() && Symbols[Index].isTypeData();
1016}
1017
Sam Cleggdb159752018-04-26 19:27:28 +00001018bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1019 return Index < Symbols.size() && Symbols[Index].isTypeSection();
1020}
1021
Sam Cleggd5784792018-02-23 05:08:34 +00001022wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
Sam Clegg9a49b21c2018-01-24 01:27:17 +00001023 assert(isDefinedFunctionIndex(Index));
1024 return Functions[Index - NumImportedFunctions];
1025}
1026
Sam Cleggd5784792018-02-23 05:08:34 +00001027wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
1028 assert(isDefinedGlobalIndex(Index));
1029 return Globals[Index - NumImportedGlobals];
1030}
1031
Heejin Ahn8bcdd042018-11-14 02:46:21 +00001032wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) {
1033 assert(isDefinedEventIndex(Index));
1034 return Events[Index - NumImportedEvents];
1035}
1036
Sam Clegg50617cf2018-05-29 19:58:59 +00001037Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1038 StartFunction = readVaruint32(Ctx);
Sam Clegge1acb562017-12-14 21:10:03 +00001039 if (!isValidFunctionIndex(StartFunction))
Derek Schuff349a48f2017-03-30 19:44:09 +00001040 return make_error<GenericBinaryError>("Invalid start function",
1041 object_error::parse_failed);
1042 return Error::success();
1043}
1044
Sam Clegg50617cf2018-05-29 19:58:59 +00001045Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
Sam Cleggb39f4112018-02-09 20:21:50 +00001046 CodeSection = Sections.size();
Sam Clegg50617cf2018-05-29 19:58:59 +00001047 uint32_t FunctionCount = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +00001048 if (FunctionCount != FunctionTypes.size()) {
1049 return make_error<GenericBinaryError>("Invalid function count",
1050 object_error::parse_failed);
1051 }
1052
Derek Schuff349a48f2017-03-30 19:44:09 +00001053 while (FunctionCount--) {
1054 wasm::WasmFunction Function;
Sam Clegg50617cf2018-05-29 19:58:59 +00001055 const uint8_t *FunctionStart = Ctx.Ptr;
1056 uint32_t Size = readVaruint32(Ctx);
1057 const uint8_t *FunctionEnd = Ctx.Ptr + Size;
Sam Clegg6e6de692017-12-17 17:50:07 +00001058
Sam Clegg50617cf2018-05-29 19:58:59 +00001059 Function.CodeOffset = Ctx.Ptr - FunctionStart;
Sam Clegg6b54fc32018-01-09 21:38:53 +00001060 Function.Index = NumImportedFunctions + Functions.size();
Sam Clegg50617cf2018-05-29 19:58:59 +00001061 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
Sam Clegg6e6de692017-12-17 17:50:07 +00001062 Function.Size = FunctionEnd - FunctionStart;
Derek Schuff349a48f2017-03-30 19:44:09 +00001063
Sam Clegg50617cf2018-05-29 19:58:59 +00001064 uint32_t NumLocalDecls = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +00001065 Function.Locals.reserve(NumLocalDecls);
1066 while (NumLocalDecls--) {
1067 wasm::WasmLocalDecl Decl;
Sam Clegg50617cf2018-05-29 19:58:59 +00001068 Decl.Count = readVaruint32(Ctx);
1069 Decl.Type = readUint8(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +00001070 Function.Locals.push_back(Decl);
1071 }
1072
Sam Clegg50617cf2018-05-29 19:58:59 +00001073 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1074 Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
Nicholas Wilsondc84b5c2018-03-14 15:44:45 +00001075 // This will be set later when reading in the linking metadata section.
1076 Function.Comdat = UINT32_MAX;
Sam Clegg50617cf2018-05-29 19:58:59 +00001077 Ctx.Ptr += BodySize;
1078 assert(Ctx.Ptr == FunctionEnd);
Derek Schuff349a48f2017-03-30 19:44:09 +00001079 Functions.push_back(Function);
1080 }
Sam Clegg50617cf2018-05-29 19:58:59 +00001081 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +00001082 return make_error<GenericBinaryError>("Code section ended prematurely",
1083 object_error::parse_failed);
1084 return Error::success();
1085}
1086
Sam Clegg50617cf2018-05-29 19:58:59 +00001087Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1088 uint32_t Count = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +00001089 ElemSegments.reserve(Count);
1090 while (Count--) {
1091 wasm::WasmElemSegment Segment;
Sam Clegg50617cf2018-05-29 19:58:59 +00001092 Segment.TableIndex = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +00001093 if (Segment.TableIndex != 0) {
1094 return make_error<GenericBinaryError>("Invalid TableIndex",
1095 object_error::parse_failed);
1096 }
Sam Clegg50617cf2018-05-29 19:58:59 +00001097 if (Error Err = readInitExpr(Segment.Offset, Ctx))
Derek Schuff349a48f2017-03-30 19:44:09 +00001098 return Err;
Sam Clegg50617cf2018-05-29 19:58:59 +00001099 uint32_t NumElems = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +00001100 while (NumElems--) {
Sam Clegg50617cf2018-05-29 19:58:59 +00001101 Segment.Functions.push_back(readVaruint32(Ctx));
Derek Schuff349a48f2017-03-30 19:44:09 +00001102 }
1103 ElemSegments.push_back(Segment);
1104 }
Sam Clegg50617cf2018-05-29 19:58:59 +00001105 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +00001106 return make_error<GenericBinaryError>("Elem section ended prematurely",
1107 object_error::parse_failed);
1108 return Error::success();
1109}
1110
Sam Clegg50617cf2018-05-29 19:58:59 +00001111Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
Sam Cleggb39f4112018-02-09 20:21:50 +00001112 DataSection = Sections.size();
Sam Clegg50617cf2018-05-29 19:58:59 +00001113 uint32_t Count = readVaruint32(Ctx);
Derek Schuff349a48f2017-03-30 19:44:09 +00001114 DataSegments.reserve(Count);
1115 while (Count--) {
Sam Cleggc9c28d92017-07-12 00:24:54 +00001116 WasmSegment Segment;
Sam Clegg50617cf2018-05-29 19:58:59 +00001117 Segment.Data.MemoryIndex = readVaruint32(Ctx);
1118 if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
Derek Schuff349a48f2017-03-30 19:44:09 +00001119 return Err;
Sam Clegg50617cf2018-05-29 19:58:59 +00001120 uint32_t Size = readVaruint32(Ctx);
Simon Pilgrimbe2419a2018-06-26 10:02:12 +00001121 if (Size > (size_t)(Ctx.End - Ctx.Ptr))
Sam Cleggd0adb142018-05-18 21:08:26 +00001122 return make_error<GenericBinaryError>("Invalid segment size",
1123 object_error::parse_failed);
Sam Clegg50617cf2018-05-29 19:58:59 +00001124 Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
Nicholas Wilsondc84b5c2018-03-14 15:44:45 +00001125 // The rest of these Data fields are set later, when reading in the linking
1126 // metadata section.
Sam Clegge2864172017-09-29 16:50:08 +00001127 Segment.Data.Alignment = 0;
1128 Segment.Data.Flags = 0;
Nicholas Wilsondc84b5c2018-03-14 15:44:45 +00001129 Segment.Data.Comdat = UINT32_MAX;
Sam Clegg50617cf2018-05-29 19:58:59 +00001130 Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1131 Ctx.Ptr += Size;
Derek Schuff349a48f2017-03-30 19:44:09 +00001132 DataSegments.push_back(Segment);
1133 }
Sam Clegg50617cf2018-05-29 19:58:59 +00001134 if (Ctx.Ptr != Ctx.End)
Derek Schuff349a48f2017-03-30 19:44:09 +00001135 return make_error<GenericBinaryError>("Data section ended prematurely",
1136 object_error::parse_failed);
Derek Schuff7a578c92016-11-30 16:49:11 +00001137 return Error::success();
1138}
1139
1140const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
Sam Clegg45484532018-05-30 03:37:26 +00001141 return reinterpret_cast<const uint8_t *>(getData().data() + Offset);
Derek Schuff7a578c92016-11-30 16:49:11 +00001142}
1143
1144const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1145 return Header;
1146}
1147
Derek Schuff349a48f2017-03-30 19:44:09 +00001148void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
Derek Schuff7a578c92016-11-30 16:49:11 +00001149
1150uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
Sam Clegg740b80d2017-05-04 19:32:43 +00001151 uint32_t Result = SymbolRef::SF_None;
Derek Schuff349a48f2017-03-30 19:44:09 +00001152 const WasmSymbol &Sym = getWasmSymbol(Symb);
Sam Clegg740b80d2017-05-04 19:32:43 +00001153
Nicola Zaghen0818e782018-05-14 12:53:11 +00001154 LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
Sam Cleggbfa1dc62018-01-31 19:50:14 +00001155 if (Sym.isBindingWeak())
Sam Clegg1e975c12017-06-20 04:04:59 +00001156 Result |= SymbolRef::SF_Weak;
Sam Cleggbfa1dc62018-01-31 19:50:14 +00001157 if (!Sym.isBindingLocal())
Sam Cleggb1dd7d62017-09-20 21:17:04 +00001158 Result |= SymbolRef::SF_Global;
Sam Clegg1f4bd622017-12-03 01:19:23 +00001159 if (Sym.isHidden())
1160 Result |= SymbolRef::SF_Hidden;
Sam Cleggd5784792018-02-23 05:08:34 +00001161 if (!Sym.isDefined())
Sam Clegg740b80d2017-05-04 19:32:43 +00001162 Result |= SymbolRef::SF_Undefined;
Sam Cleggd5784792018-02-23 05:08:34 +00001163 if (Sym.isTypeFunction())
1164 Result |= SymbolRef::SF_Executable;
Sam Clegg740b80d2017-05-04 19:32:43 +00001165 return Result;
Derek Schuff7a578c92016-11-30 16:49:11 +00001166}
1167
1168basic_symbol_iterator WasmObjectFile::symbol_begin() const {
Derek Schuff349a48f2017-03-30 19:44:09 +00001169 DataRefImpl Ref;
1170 Ref.d.a = 0;
1171 return BasicSymbolRef(Ref, this);
Derek Schuff7a578c92016-11-30 16:49:11 +00001172}
1173
1174basic_symbol_iterator WasmObjectFile::symbol_end() const {
Derek Schuff349a48f2017-03-30 19:44:09 +00001175 DataRefImpl Ref;
1176 Ref.d.a = Symbols.size();
1177 return BasicSymbolRef(Ref, this);
1178}
1179
Sam Clegg65e284e2017-05-09 23:48:41 +00001180const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
Derek Schuff349a48f2017-03-30 19:44:09 +00001181 return Symbols[Symb.d.a];
Derek Schuff7a578c92016-11-30 16:49:11 +00001182}
1183
Sam Clegg65e284e2017-05-09 23:48:41 +00001184const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1185 return getWasmSymbol(Symb.getRawDataRefImpl());
1186}
1187
Derek Schuff7a578c92016-11-30 16:49:11 +00001188Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
Sam Cleggd5784792018-02-23 05:08:34 +00001189 return getWasmSymbol(Symb).Info.Name;
Derek Schuff7a578c92016-11-30 16:49:11 +00001190}
1191
1192Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
Sam Clegg740b80d2017-05-04 19:32:43 +00001193 return getSymbolValue(Symb);
Derek Schuff7a578c92016-11-30 16:49:11 +00001194}
1195
Heejin Ahn581d2312018-09-05 01:27:38 +00001196uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
Sam Cleggd5784792018-02-23 05:08:34 +00001197 switch (Sym.Info.Kind) {
1198 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1199 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
Heejin Ahn8bcdd042018-11-14 02:46:21 +00001200 case wasm::WASM_SYMBOL_TYPE_EVENT:
Sam Cleggd5784792018-02-23 05:08:34 +00001201 return Sym.Info.ElementIndex;
1202 case wasm::WASM_SYMBOL_TYPE_DATA: {
1203 // The value of a data symbol is the segment offset, plus the symbol
1204 // offset within the segment.
1205 uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1206 const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1207 assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST);
1208 return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
Sam Clegg3ccf5512017-08-31 23:22:44 +00001209 }
Sam Cleggdb159752018-04-26 19:27:28 +00001210 case wasm::WASM_SYMBOL_TYPE_SECTION:
1211 return 0;
Sam Clegg1e975c12017-06-20 04:04:59 +00001212 }
Sam Cleggad60de32017-06-20 04:47:58 +00001213 llvm_unreachable("invalid symbol type");
Derek Schuff7a578c92016-11-30 16:49:11 +00001214}
1215
Sam Cleggb1dd7d62017-09-20 21:17:04 +00001216uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1217 return getWasmSymbolValue(getWasmSymbol(Symb));
1218}
1219
Derek Schuff7a578c92016-11-30 16:49:11 +00001220uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1221 llvm_unreachable("not yet implemented");
1222 return 0;
1223}
1224
1225uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1226 llvm_unreachable("not yet implemented");
1227 return 0;
1228}
1229
1230Expected<SymbolRef::Type>
1231WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
Sam Clegg740b80d2017-05-04 19:32:43 +00001232 const WasmSymbol &Sym = getWasmSymbol(Symb);
1233
Sam Cleggd5784792018-02-23 05:08:34 +00001234 switch (Sym.Info.Kind) {
1235 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
Sam Clegg740b80d2017-05-04 19:32:43 +00001236 return SymbolRef::ST_Function;
Sam Cleggd5784792018-02-23 05:08:34 +00001237 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1238 return SymbolRef::ST_Other;
1239 case wasm::WASM_SYMBOL_TYPE_DATA:
Sam Clegg740b80d2017-05-04 19:32:43 +00001240 return SymbolRef::ST_Data;
Sam Cleggdb159752018-04-26 19:27:28 +00001241 case wasm::WASM_SYMBOL_TYPE_SECTION:
1242 return SymbolRef::ST_Debug;
Heejin Ahn8bcdd042018-11-14 02:46:21 +00001243 case wasm::WASM_SYMBOL_TYPE_EVENT:
1244 return SymbolRef::ST_Other;
Sam Clegg740b80d2017-05-04 19:32:43 +00001245 }
1246
1247 llvm_unreachable("Unknown WasmSymbol::SymbolType");
1248 return SymbolRef::ST_Other;
Derek Schuff7a578c92016-11-30 16:49:11 +00001249}
1250
1251Expected<section_iterator>
1252WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
Heejin Ahn581d2312018-09-05 01:27:38 +00001253 const WasmSymbol &Sym = getWasmSymbol(Symb);
Sam Cleggd5784792018-02-23 05:08:34 +00001254 if (Sym.isUndefined())
Sam Cleggb39f4112018-02-09 20:21:50 +00001255 return section_end();
Sam Cleggd5784792018-02-23 05:08:34 +00001256
1257 DataRefImpl Ref;
1258 switch (Sym.Info.Kind) {
1259 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1260 Ref.d.a = CodeSection;
1261 break;
1262 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1263 Ref.d.a = GlobalSection;
1264 break;
1265 case wasm::WASM_SYMBOL_TYPE_DATA:
1266 Ref.d.a = DataSection;
1267 break;
Heejin Ahn8bcdd042018-11-14 02:46:21 +00001268 case wasm::WASM_SYMBOL_TYPE_SECTION:
Sam Cleggdb159752018-04-26 19:27:28 +00001269 Ref.d.a = Sym.Info.ElementIndex;
1270 break;
Heejin Ahn8bcdd042018-11-14 02:46:21 +00001271 case wasm::WASM_SYMBOL_TYPE_EVENT:
1272 Ref.d.a = EventSection;
1273 break;
Sam Cleggd5784792018-02-23 05:08:34 +00001274 default:
1275 llvm_unreachable("Unknown WasmSymbol::SymbolType");
1276 }
Sam Clegg740b80d2017-05-04 19:32:43 +00001277 return section_iterator(SectionRef(Ref, this));
Derek Schuff7a578c92016-11-30 16:49:11 +00001278}
1279
1280void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1281
1282std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
1283 StringRef &Res) const {
Derek Schuff349a48f2017-03-30 19:44:09 +00001284 const WasmSection &S = Sections[Sec.d.a];
Derek Schuff7a578c92016-11-30 16:49:11 +00001285#define ECase(X) \
1286 case wasm::WASM_SEC_##X: \
1287 Res = #X; \
1288 break
1289 switch (S.Type) {
1290 ECase(TYPE);
1291 ECase(IMPORT);
1292 ECase(FUNCTION);
1293 ECase(TABLE);
1294 ECase(MEMORY);
1295 ECase(GLOBAL);
Heejin Ahn8bcdd042018-11-14 02:46:21 +00001296 ECase(EVENT);
Derek Schuff7a578c92016-11-30 16:49:11 +00001297 ECase(EXPORT);
1298 ECase(START);
1299 ECase(ELEM);
1300 ECase(CODE);
1301 ECase(DATA);
Derek Schuffc20099f2017-01-30 23:30:52 +00001302 case wasm::WASM_SEC_CUSTOM:
Derek Schuff7a578c92016-11-30 16:49:11 +00001303 Res = S.Name;
1304 break;
1305 default:
1306 return object_error::invalid_section_index;
1307 }
1308#undef ECase
1309 return std::error_code();
1310}
1311
1312uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1313
George Rimarb5ac7002017-05-27 18:10:23 +00001314uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1315 return Sec.d.a;
1316}
1317
Derek Schuff7a578c92016-11-30 16:49:11 +00001318uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
Derek Schuff349a48f2017-03-30 19:44:09 +00001319 const WasmSection &S = Sections[Sec.d.a];
Derek Schuff7a578c92016-11-30 16:49:11 +00001320 return S.Content.size();
1321}
1322
1323std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
1324 StringRef &Res) const {
Derek Schuff349a48f2017-03-30 19:44:09 +00001325 const WasmSection &S = Sections[Sec.d.a];
Derek Schuff7a578c92016-11-30 16:49:11 +00001326 // This will never fail since wasm sections can never be empty (user-sections
1327 // must have a name and non-user sections each have a defined structure).
1328 Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
1329 S.Content.size());
1330 return std::error_code();
1331}
1332
1333uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1334 return 1;
1335}
1336
1337bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1338 return false;
1339}
1340
1341bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
Derek Schuff349a48f2017-03-30 19:44:09 +00001342 return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
Derek Schuff7a578c92016-11-30 16:49:11 +00001343}
1344
1345bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
Derek Schuff349a48f2017-03-30 19:44:09 +00001346 return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
Derek Schuff7a578c92016-11-30 16:49:11 +00001347}
1348
1349bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1350
1351bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1352
1353bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1354
Derek Schuff349a48f2017-03-30 19:44:09 +00001355relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1356 DataRefImpl RelocRef;
1357 RelocRef.d.a = Ref.d.a;
1358 RelocRef.d.b = 0;
1359 return relocation_iterator(RelocationRef(RelocRef, this));
Derek Schuff7a578c92016-11-30 16:49:11 +00001360}
1361
Derek Schuff349a48f2017-03-30 19:44:09 +00001362relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1363 const WasmSection &Sec = getWasmSection(Ref);
1364 DataRefImpl RelocRef;
1365 RelocRef.d.a = Ref.d.a;
1366 RelocRef.d.b = Sec.Relocations.size();
1367 return relocation_iterator(RelocationRef(RelocRef, this));
Derek Schuff7a578c92016-11-30 16:49:11 +00001368}
1369
Heejin Ahn581d2312018-09-05 01:27:38 +00001370void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
Derek Schuff7a578c92016-11-30 16:49:11 +00001371
Derek Schuff349a48f2017-03-30 19:44:09 +00001372uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1373 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1374 return Rel.Offset;
Derek Schuff7a578c92016-11-30 16:49:11 +00001375}
1376
Sam Clegg588fa1c2018-04-26 16:41:51 +00001377symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1378 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1379 if (Rel.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
1380 return symbol_end();
1381 DataRefImpl Sym;
1382 Sym.d.a = Rel.Index;
1383 Sym.d.b = 0;
1384 return symbol_iterator(SymbolRef(Sym, this));
Derek Schuff7a578c92016-11-30 16:49:11 +00001385}
1386
Derek Schuff349a48f2017-03-30 19:44:09 +00001387uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1388 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1389 return Rel.Type;
Derek Schuff7a578c92016-11-30 16:49:11 +00001390}
1391
1392void WasmObjectFile::getRelocationTypeName(
Derek Schuff349a48f2017-03-30 19:44:09 +00001393 DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
Heejin Ahn581d2312018-09-05 01:27:38 +00001394 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
Derek Schuff349a48f2017-03-30 19:44:09 +00001395 StringRef Res = "Unknown";
1396
Heejin Ahn581d2312018-09-05 01:27:38 +00001397#define WASM_RELOC(name, value) \
1398 case wasm::name: \
1399 Res = #name; \
Derek Schuff349a48f2017-03-30 19:44:09 +00001400 break;
1401
1402 switch (Rel.Type) {
Sam Cleggead036a2017-12-21 03:16:34 +00001403#include "llvm/BinaryFormat/WasmRelocs.def"
Derek Schuff349a48f2017-03-30 19:44:09 +00001404 }
1405
1406#undef WASM_RELOC
1407
1408 Result.append(Res.begin(), Res.end());
Derek Schuff7a578c92016-11-30 16:49:11 +00001409}
1410
1411section_iterator WasmObjectFile::section_begin() const {
1412 DataRefImpl Ref;
1413 Ref.d.a = 0;
1414 return section_iterator(SectionRef(Ref, this));
1415}
1416
1417section_iterator WasmObjectFile::section_end() const {
1418 DataRefImpl Ref;
1419 Ref.d.a = Sections.size();
1420 return section_iterator(SectionRef(Ref, this));
1421}
1422
1423uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1424
1425StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1426
Zachary Turnerece9b232017-12-14 22:07:03 +00001427Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
Derek Schuff7a578c92016-11-30 16:49:11 +00001428
1429SubtargetFeatures WasmObjectFile::getFeatures() const {
1430 return SubtargetFeatures();
1431}
1432
Heejin Ahn581d2312018-09-05 01:27:38 +00001433bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
Derek Schuff7a578c92016-11-30 16:49:11 +00001434
Sam Clegg559201d2018-12-12 23:40:58 +00001435bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1436
Derek Schuff349a48f2017-03-30 19:44:09 +00001437const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
Davide Italiano084c1ea2017-04-01 19:47:52 +00001438 assert(Ref.d.a < Sections.size());
Derek Schuff349a48f2017-03-30 19:44:09 +00001439 return Sections[Ref.d.a];
1440}
1441
1442const WasmSection &
Derek Schuff7a578c92016-11-30 16:49:11 +00001443WasmObjectFile::getWasmSection(const SectionRef &Section) const {
Derek Schuff349a48f2017-03-30 19:44:09 +00001444 return getWasmSection(Section.getRawDataRefImpl());
1445}
1446
1447const wasm::WasmRelocation &
1448WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1449 return getWasmRelocation(Ref.getRawDataRefImpl());
1450}
1451
1452const wasm::WasmRelocation &
1453WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
Davide Italiano084c1ea2017-04-01 19:47:52 +00001454 assert(Ref.d.a < Sections.size());
Heejin Ahn581d2312018-09-05 01:27:38 +00001455 const WasmSection &Sec = Sections[Ref.d.a];
Davide Italiano084c1ea2017-04-01 19:47:52 +00001456 assert(Ref.d.b < Sec.Relocations.size());
Derek Schuff349a48f2017-03-30 19:44:09 +00001457 return Sec.Relocations[Ref.d.b];
Derek Schuff7a578c92016-11-30 16:49:11 +00001458}
Heejin Ahne2f3e502018-12-15 00:58:12 +00001459
1460int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1461 StringRef CustomSectionName) {
1462 switch (ID) {
1463 case wasm::WASM_SEC_CUSTOM:
1464 return StringSwitch<unsigned>(CustomSectionName)
1465 .Case("dylink", WASM_SEC_ORDER_DYLINK)
1466 .Case("linking", WASM_SEC_ORDER_LINKING)
1467 .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1468 .Case("name", WASM_SEC_ORDER_NAME)
1469 .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1470 .Default(-1);
1471 case wasm::WASM_SEC_TYPE:
1472 return WASM_SEC_ORDER_TYPE;
1473 case wasm::WASM_SEC_IMPORT:
1474 return WASM_SEC_ORDER_IMPORT;
1475 case wasm::WASM_SEC_FUNCTION:
1476 return WASM_SEC_ORDER_FUNCTION;
1477 case wasm::WASM_SEC_TABLE:
1478 return WASM_SEC_ORDER_TABLE;
1479 case wasm::WASM_SEC_MEMORY:
1480 return WASM_SEC_ORDER_MEMORY;
1481 case wasm::WASM_SEC_GLOBAL:
1482 return WASM_SEC_ORDER_GLOBAL;
1483 case wasm::WASM_SEC_EXPORT:
1484 return WASM_SEC_ORDER_EXPORT;
1485 case wasm::WASM_SEC_START:
1486 return WASM_SEC_ORDER_START;
1487 case wasm::WASM_SEC_ELEM:
1488 return WASM_SEC_ORDER_ELEM;
1489 case wasm::WASM_SEC_CODE:
1490 return WASM_SEC_ORDER_CODE;
1491 case wasm::WASM_SEC_DATA:
1492 return WASM_SEC_ORDER_DATA;
1493 case wasm::WASM_SEC_DATACOUNT:
1494 return WASM_SEC_ORDER_DATACOUNT;
1495 case wasm::WASM_SEC_EVENT:
1496 return WASM_SEC_ORDER_EVENT;
1497 default:
1498 llvm_unreachable("invalid section");
1499 }
1500}
1501
1502bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
1503 StringRef CustomSectionName) {
1504 int Order = getSectionOrder(ID, CustomSectionName);
1505 if (Order == -1) // Skip unknown sections
1506 return true;
1507 // There can be multiple "reloc." sections. Otherwise there shouldn't be any
1508 // duplicate section orders.
1509 bool IsValid = (LastOrder == Order && Order == WASM_SEC_ORDER_RELOC) ||
1510 LastOrder < Order;
1511 LastOrder = Order;
1512 return IsValid;
1513}