| author | |
| committer | |
| log | a54ac0888542d027b09e5c43729a7cfbe4a51393 |
| tree | 432385a06a91e71f022e674a5d51f53c1974be9d |
| parent | f56ae69edd8c96a5f6525f20bf0a22704a826f00 |
| signature | Commit is signed but in an unrecognized format. |
We now resolve relocations for globals, memory addresses and function indexes.
Besides above, we now also emit imported functions correctly and create a
corresponding undefined symbol for it, where as we create a defined symbol
for all other cases.
TODO: Make incrememental compilation work again with new linker infrastructure5 files changed, 115 insertions(+), 86 deletions(-)
src/arch/wasm/CodeGen.zig+1-10| ... | @@ -1363,16 +1363,7 @@ fn emitConstant(self: *Self, val: Value, ty: Type) InnerError!void { | ... | @@ -1363,16 +1363,7 @@ fn emitConstant(self: *Self, val: Value, ty: Type) InnerError!void { |
| 1363 | if (val.castTag(.decl_ref)) |payload| { | 1363 | if (val.castTag(.decl_ref)) |payload| { |
| 1364 | const decl = payload.data; | 1364 | const decl = payload.data; |
| 1365 | decl.alive = true; | 1365 | decl.alive = true; |
| 1366 | 1366 | try self.addLabel(.memory_address, decl.link.wasm.sym_index); | |
| 1367 | // offset into the offset table within the 'data' section | ||
| 1368 | // const ptr_width = self.target.cpu.arch.ptrBitWidth() / 8; | ||
| 1369 | // try self.addImm32(@bitCast(i32, decl.link.wasm.offset_index * ptr_width)); | ||
| 1370 | |||
| 1371 | // memory instruction followed by their memarg immediate | ||
| 1372 | // memarg ::== x:u32, y:u32 => {align x, offset y} | ||
| 1373 | const extra_index = try self.addExtra(Mir.MemArg{ .offset = 0, .alignment = 4 }); | ||
| 1374 | try self.addInst(.{ .tag = .i32_load, .data = .{ .payload = extra_index } }); | ||
| 1375 | @panic("REDO!\n"); | ||
| 1376 | } else return self.fail("Wasm TODO: emitConstant for other const pointer tag {s}", .{val.tag()}); | 1367 | } else return self.fail("Wasm TODO: emitConstant for other const pointer tag {s}", .{val.tag()}); |
| 1377 | }, | 1368 | }, |
| 1378 | .Void => {}, | 1369 | .Void => {}, |
src/arch/wasm/Emit.zig+28-6| ... | @@ -49,6 +49,7 @@ pub fn emitMir(emit: *Emit) InnerError!void { | ... | @@ -49,6 +49,7 @@ pub fn emitMir(emit: *Emit) InnerError!void { |
| 49 | .call => try emit.emitCall(inst), | 49 | .call => try emit.emitCall(inst), |
| 50 | .global_get => try emit.emitGlobal(tag, inst), | 50 | .global_get => try emit.emitGlobal(tag, inst), |
| 51 | .global_set => try emit.emitGlobal(tag, inst), | 51 | .global_set => try emit.emitGlobal(tag, inst), |
| 52 | .memory_address => try emit.emitMemAddress(inst), | ||
| 52 | 53 | ||
| 53 | // immediates | 54 | // immediates |
| 54 | .f32_const => try emit.emitFloat32(inst), | 55 | .f32_const => try emit.emitFloat32(inst), |
| ... | @@ -157,6 +158,10 @@ pub fn emitMir(emit: *Emit) InnerError!void { | ... | @@ -157,6 +158,10 @@ pub fn emitMir(emit: *Emit) InnerError!void { |
| 157 | } | 158 | } |
| 158 | } | 159 | } |
| 159 | 160 | ||
| 161 | fn offset(self: Emit) u32 { | ||
| 162 | return @intCast(u32, self.code.items.len); | ||
| 163 | } | ||
| 164 | |||
| 160 | fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { | 165 | fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { |
| 161 | @setCold(true); | 166 | @setCold(true); |
| 162 | std.debug.assert(emit.error_msg == null); | 167 | std.debug.assert(emit.error_msg == null); |
| ... | @@ -209,9 +214,14 @@ fn emitGlobal(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) !void { | ... | @@ -209,9 +214,14 @@ fn emitGlobal(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) !void { |
| 209 | try emit.code.append(@enumToInt(tag)); | 214 | try emit.code.append(@enumToInt(tag)); |
| 210 | var buf: [5]u8 = undefined; | 215 | var buf: [5]u8 = undefined; |
| 211 | leb128.writeUnsignedFixed(5, &buf, label); | 216 | leb128.writeUnsignedFixed(5, &buf, label); |
| 217 | const global_offset = emit.offset(); | ||
| 212 | try emit.code.appendSlice(&buf); | 218 | try emit.code.appendSlice(&buf); |
| 213 | 219 | ||
| 214 | // TODO: Append label to the relocation list of this function | 220 | try emit.decl.link.wasm.relocs.append(emit.bin_file.allocator, .{ |
| 221 | .index = label, | ||
| 222 | .offset = global_offset, | ||
| 223 | .relocation_type = .R_WASM_GLOBAL_INDEX_LEB, | ||
| 224 | }); | ||
| 215 | } | 225 | } |
| 216 | 226 | ||
| 217 | fn emitImm32(emit: *Emit, inst: Mir.Inst.Index) !void { | 227 | fn emitImm32(emit: *Emit, inst: Mir.Inst.Index) !void { |
| ... | @@ -254,17 +264,29 @@ fn emitMemArg(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) !void { | ... | @@ -254,17 +264,29 @@ fn emitMemArg(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) !void { |
| 254 | fn emitCall(emit: *Emit, inst: Mir.Inst.Index) !void { | 264 | fn emitCall(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 255 | const label = emit.mir.instructions.items(.data)[inst].label; | 265 | const label = emit.mir.instructions.items(.data)[inst].label; |
| 256 | try emit.code.append(std.wasm.opcode(.call)); | 266 | try emit.code.append(std.wasm.opcode(.call)); |
| 257 | const offset = @intCast(u32, emit.code.items.len); | 267 | const call_offset = emit.offset(); |
| 258 | var buf: [5]u8 = undefined; | 268 | var buf: [5]u8 = undefined; |
| 259 | leb128.writeUnsignedFixed(5, &buf, label); | 269 | leb128.writeUnsignedFixed(5, &buf, label); |
| 260 | try emit.code.appendSlice(&buf); | 270 | try emit.code.appendSlice(&buf); |
| 261 | 271 | ||
| 262 | // The function index immediate argument will be filled in using this data | ||
| 263 | // in link.Wasm.flush(). | ||
| 264 | // TODO: Replace this with proper relocations saved in the Atom. | ||
| 265 | try emit.decl.link.wasm.relocs.append(emit.bin_file.allocator, .{ | 272 | try emit.decl.link.wasm.relocs.append(emit.bin_file.allocator, .{ |
| 266 | .offset = offset, | 273 | .offset = call_offset, |
| 267 | .index = label, | 274 | .index = label, |
| 268 | .relocation_type = .R_WASM_FUNCTION_INDEX_LEB, | 275 | .relocation_type = .R_WASM_FUNCTION_INDEX_LEB, |
| 269 | }); | 276 | }); |
| 270 | } | 277 | } |
| 278 | |||
| 279 | fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void { | ||
| 280 | const symbol_index = emit.mir.instructions.items(.data)[inst].label; | ||
| 281 | try emit.code.append(std.wasm.opcode(.i32_const)); | ||
| 282 | const mem_offset = emit.offset(); | ||
| 283 | var buf: [5]u8 = undefined; | ||
| 284 | leb128.writeUnsignedFixed(5, &buf, symbol_index); | ||
| 285 | try emit.code.appendSlice(&buf); | ||
| 286 | |||
| 287 | try emit.decl.link.wasm.relocs.append(emit.bin_file.allocator, .{ | ||
| 288 | .offset = mem_offset, | ||
| 289 | .index = symbol_index, | ||
| 290 | .relocation_type = .R_WASM_MEMORY_ADDR_LEB, | ||
| 291 | }); | ||
| 292 | } |
src/arch/wasm/Mir.zig+6| ... | @@ -358,6 +358,12 @@ pub const Inst = struct { | ... | @@ -358,6 +358,12 @@ pub const Inst = struct { |
| 358 | i64_extend16_s = 0xC3, | 358 | i64_extend16_s = 0xC3, |
| 359 | /// Uses `tag` | 359 | /// Uses `tag` |
| 360 | i64_extend32_s = 0xC4, | 360 | i64_extend32_s = 0xC4, |
| 361 | /// Contains a symbol to a memory address | ||
| 362 | /// Uses `label` | ||
| 363 | /// | ||
| 364 | /// Note: This uses `0xFF` as value as it is unused and not-reserved | ||
| 365 | /// by the wasm specification, making it safe to use | ||
| 366 | memory_address = 0xFF, | ||
| 361 | 367 | ||
| 362 | /// From a given wasm opcode, returns a MIR tag. | 368 | /// From a given wasm opcode, returns a MIR tag. |
| 363 | pub fn fromOpcode(opcode: std.wasm.Opcode) Tag { | 369 | pub fn fromOpcode(opcode: std.wasm.Opcode) Tag { |
src/link/Wasm.zig+64-52| ... | @@ -301,10 +301,66 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, result: CodeGen.Result, cod | ... | @@ -301,10 +301,66 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, result: CodeGen.Result, cod |
| 301 | // to avoid infinite loops due to earlier links | 301 | // to avoid infinite loops due to earlier links |
| 302 | atom.unplug(); | 302 | atom.unplug(); |
| 303 | 303 | ||
| 304 | const symbol: *Symbol = &self.symbols.items[atom.sym_index]; | ||
| 305 | if (decl.isExtern()) { | 304 | if (decl.isExtern()) { |
| 306 | symbol.setUndefined(true); | 305 | try self.createUndefinedSymbol(decl, atom.sym_index); |
| 306 | } else { | ||
| 307 | try self.createDefinedSymbol(decl, atom.sym_index, atom); | ||
| 308 | } | ||
| 309 | } | ||
| 310 | |||
| 311 | pub fn updateDeclExports( | ||
| 312 | self: *Wasm, | ||
| 313 | module: *Module, | ||
| 314 | decl: *const Module.Decl, | ||
| 315 | exports: []const *Module.Export, | ||
| 316 | ) !void { | ||
| 317 | if (build_options.skip_non_native and builtin.object_format != .wasm) { | ||
| 318 | @panic("Attempted to compile for object format that was disabled by build configuration"); | ||
| 319 | } | ||
| 320 | if (build_options.have_llvm) { | ||
| 321 | if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl, exports); | ||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 325 | pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void { | ||
| 326 | if (build_options.have_llvm) { | ||
| 327 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl); | ||
| 328 | } | ||
| 329 | |||
| 330 | const atom = &decl.link.wasm; | ||
| 331 | |||
| 332 | if (self.last_atom == atom) { | ||
| 333 | self.last_atom = atom.prev; | ||
| 307 | } | 334 | } |
| 335 | |||
| 336 | atom.unplug(); | ||
| 337 | self.symbols_free_list.append(self.base.allocator, atom.sym_index) catch {}; | ||
| 338 | atom.deinit(self.base.allocator); | ||
| 339 | _ = self.decls.remove(decl); | ||
| 340 | } | ||
| 341 | |||
| 342 | fn createUndefinedSymbol(self: *Wasm, decl: *Module.Decl, symbol_index: u32) !void { | ||
| 343 | var symbol: *Symbol = &self.symbols.items[symbol_index]; | ||
| 344 | symbol.name = decl.name; | ||
| 345 | symbol.setUndefined(true); | ||
| 346 | switch (decl.ty.zigTypeTag()) { | ||
| 347 | .Fn => { | ||
| 348 | symbol.index = self.imported_functions_count; | ||
| 349 | self.imported_functions_count += 1; | ||
| 350 | try self.import_symbols.append(self.base.allocator, symbol_index); | ||
| 351 | try self.imports.append(self.base.allocator, .{ | ||
| 352 | .module_name = self.host_name, | ||
| 353 | .name = std.mem.span(decl.name), | ||
| 354 | .kind = .{ .function = decl.fn_link.wasm.type_index }, | ||
| 355 | }); | ||
| 356 | }, | ||
| 357 | else => @panic("TODO: Implement undefined symbols for non-function declarations"), | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | /// Creates a defined symbol, as well as inserts the given `atom` into the chain | ||
| 362 | fn createDefinedSymbol(self: *Wasm, decl: *Module.Decl, symbol_index: u32, atom: *Atom) !void { | ||
| 363 | const symbol: *Symbol = &self.symbols.items[symbol_index]; | ||
| 308 | symbol.name = decl.name; | 364 | symbol.name = decl.name; |
| 309 | const final_index = switch (decl.ty.zigTypeTag()) { | 365 | const final_index = switch (decl.ty.zigTypeTag()) { |
| 310 | .Fn => result: { | 366 | .Fn => result: { |
| ... | @@ -371,49 +427,6 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, result: CodeGen.Result, cod | ... | @@ -371,49 +427,6 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, result: CodeGen.Result, cod |
| 371 | } | 427 | } |
| 372 | } | 428 | } |
| 373 | 429 | ||
| 374 | pub fn updateDeclExports( | ||
| 375 | self: *Wasm, | ||
| 376 | module: *Module, | ||
| 377 | decl: *const Module.Decl, | ||
| 378 | exports: []const *Module.Export, | ||
| 379 | ) !void { | ||
| 380 | if (build_options.skip_non_native and builtin.object_format != .wasm) { | ||
| 381 | @panic("Attempted to compile for object format that was disabled by build configuration"); | ||
| 382 | } | ||
| 383 | if (build_options.have_llvm) { | ||
| 384 | if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl, exports); | ||
| 385 | } | ||
| 386 | } | ||
| 387 | |||
| 388 | pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void { | ||
| 389 | if (build_options.have_llvm) { | ||
| 390 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl); | ||
| 391 | } | ||
| 392 | |||
| 393 | const atom = &decl.link.wasm; | ||
| 394 | |||
| 395 | if (self.last_atom == atom) { | ||
| 396 | self.last_atom = atom.prev; | ||
| 397 | } | ||
| 398 | |||
| 399 | atom.unplug(); | ||
| 400 | self.symbols_free_list.append(self.base.allocator, atom.sym_index) catch {}; | ||
| 401 | atom.deinit(self.base.allocator); | ||
| 402 | _ = self.decls.remove(decl); | ||
| 403 | } | ||
| 404 | |||
| 405 | fn createUndefinedSymbol(self: *Wasm, decl: *Module.Decl, symbol_index: u32) !void { | ||
| 406 | var symbol: *Symbol = &self.symbols.items[symbol_index]; | ||
| 407 | symbol.setUndefined(true); | ||
| 408 | switch (decl.ty.zigTypeTag()) { | ||
| 409 | .Fn => { | ||
| 410 | symbol.setIndex(self.imported_functions_count); | ||
| 411 | self.imported_functions_count += 1; | ||
| 412 | }, | ||
| 413 | else => @panic("TODO: Wasm implement extern non-function types"), | ||
| 414 | } | ||
| 415 | } | ||
| 416 | |||
| 417 | pub fn flush(self: *Wasm, comp: *Compilation) !void { | 430 | pub fn flush(self: *Wasm, comp: *Compilation) !void { |
| 418 | if (build_options.have_llvm and self.base.options.use_lld) { | 431 | if (build_options.have_llvm and self.base.options.use_lld) { |
| 419 | return self.linkWithLLD(comp); | 432 | return self.linkWithLLD(comp); |
| ... | @@ -442,7 +455,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -442,7 +455,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 442 | } | 455 | } |
| 443 | 456 | ||
| 444 | // set the stack size on the global | 457 | // set the stack size on the global |
| 445 | self.globals.items[0].init = .{ .i32_const = @bitCast(i32, data_size + stack_size) }; | 458 | self.globals.items[0].init.i32_const = @bitCast(i32, data_size + stack_size); |
| 446 | 459 | ||
| 447 | // No need to rewrite the magic/version header | 460 | // No need to rewrite the magic/version header |
| 448 | try file.setEndPos(@sizeOf(@TypeOf(wasm.magic ++ wasm.version))); | 461 | try file.setEndPos(@sizeOf(@TypeOf(wasm.magic ++ wasm.version))); |
| ... | @@ -515,10 +528,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -515,10 +528,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 515 | const header_offset = try reserveVecSectionHeader(file); | 528 | const header_offset = try reserveVecSectionHeader(file); |
| 516 | const writer = file.writer(); | 529 | const writer = file.writer(); |
| 517 | for (self.functions.items) |function| { | 530 | for (self.functions.items) |function| { |
| 518 | try leb.writeULEB128( | 531 | try leb.writeULEB128(writer, function.type_index); |
| 519 | writer, | ||
| 520 | @intCast(u32, function.type_index), | ||
| 521 | ); | ||
| 522 | } | 532 | } |
| 523 | 533 | ||
| 524 | try writeVecSectionHeader( | 534 | try writeVecSectionHeader( |
| ... | @@ -580,7 +590,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -580,7 +590,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 580 | const header_offset = try reserveVecSectionHeader(file); | 590 | const header_offset = try reserveVecSectionHeader(file); |
| 581 | const writer = file.writer(); | 591 | const writer = file.writer(); |
| 582 | var count: u32 = 0; | 592 | var count: u32 = 0; |
| 583 | var func_index: u32 = 0; | 593 | var func_index: u32 = self.imported_functions_count; |
| 584 | for (module.decl_exports.values()) |exports| { | 594 | for (module.decl_exports.values()) |exports| { |
| 585 | for (exports) |exprt| { | 595 | for (exports) |exprt| { |
| 586 | // Export name length + name | 596 | // Export name length + name |
| ... | @@ -624,8 +634,9 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -624,8 +634,9 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 624 | if (self.code_section_index) |code_index| { | 634 | if (self.code_section_index) |code_index| { |
| 625 | const header_offset = try reserveVecSectionHeader(file); | 635 | const header_offset = try reserveVecSectionHeader(file); |
| 626 | const writer = file.writer(); | 636 | const writer = file.writer(); |
| 627 | var atom = self.atoms.get(code_index).?.getFirst(); | 637 | var atom: *Atom = self.atoms.get(code_index).?.getFirst(); |
| 628 | while (true) { | 638 | while (true) { |
| 639 | try atom.resolveRelocs(self); | ||
| 629 | try leb.writeULEB128(writer, atom.size); | 640 | try leb.writeULEB128(writer, atom.size); |
| 630 | try writer.writeAll(atom.code.items); | 641 | try writer.writeAll(atom.code.items); |
| 631 | 642 | ||
| ... | @@ -667,6 +678,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { | ... | @@ -667,6 +678,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 667 | // fill in the offset table and the data segments | 678 | // fill in the offset table and the data segments |
| 668 | var current_offset: u32 = 0; | 679 | var current_offset: u32 = 0; |
| 669 | while (true) { | 680 | while (true) { |
| 681 | try atom.resolveRelocs(self); | ||
| 670 | std.debug.assert(current_offset == atom.offset); | 682 | std.debug.assert(current_offset == atom.offset); |
| 671 | std.debug.assert(atom.code.items.len == atom.size); | 683 | std.debug.assert(atom.code.items.len == atom.size); |
| 672 | 684 |
src/link/Wasm/Atom.zig+16-18| ... | @@ -72,6 +72,7 @@ pub fn getLast(self: *Atom) *Atom { | ... | @@ -72,6 +72,7 @@ pub fn getLast(self: *Atom) *Atom { |
| 72 | while (tmp.next) |next| tmp = next; | 72 | while (tmp.next) |next| tmp = next; |
| 73 | return tmp; | 73 | return tmp; |
| 74 | } | 74 | } |
| 75 | |||
| 75 | /// Unplugs the `Atom` from the chain | 76 | /// Unplugs the `Atom` from the chain |
| 76 | pub fn unplug(self: *Atom) void { | 77 | pub fn unplug(self: *Atom) void { |
| 77 | if (self.prev) |prev| { | 78 | if (self.prev) |prev| { |
| ... | @@ -88,18 +89,16 @@ pub fn unplug(self: *Atom) void { | ... | @@ -88,18 +89,16 @@ pub fn unplug(self: *Atom) void { |
| 88 | /// Resolves the relocations within the atom, writing the new value | 89 | /// Resolves the relocations within the atom, writing the new value |
| 89 | /// at the calculated offset. | 90 | /// at the calculated offset. |
| 90 | pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) !void { | 91 | pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) !void { |
| 91 | const object = wasm_bin.objects.items[self.file]; | 92 | const symbol: Symbol = wasm_bin.symbols.items[self.sym_index]; |
| 92 | const symbol: Symbol = object.symtable[self.sym_index]; | ||
| 93 | |||
| 94 | log.debug("Resolving relocs in atom '{s}' count({d})", .{ | 93 | log.debug("Resolving relocs in atom '{s}' count({d})", .{ |
| 95 | symbol.name, | 94 | symbol.name, |
| 96 | self.relocs.items.len, | 95 | self.relocs.items.len, |
| 97 | }); | 96 | }); |
| 98 | 97 | ||
| 99 | for (self.relocs.items) |reloc| { | 98 | for (self.relocs.items) |reloc| { |
| 100 | const value = self.relocationValue(reloc, wasm_bin); | 99 | const value = try relocationValue(reloc, wasm_bin); |
| 101 | log.debug("Relocating '{s}' referenced in '{s}' offset=0x{x:0>8} value={d}", .{ | 100 | log.debug("Relocating '{s}' referenced in '{s}' offset=0x{x:0>8} value={d}\n", .{ |
| 102 | object.symtable[reloc.index].name, | 101 | wasm_bin.symbols.items[reloc.index].name, |
| 103 | symbol.name, | 102 | symbol.name, |
| 104 | reloc.offset, | 103 | reloc.offset, |
| 105 | value, | 104 | value, |
| ... | @@ -135,21 +134,20 @@ pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) !void { | ... | @@ -135,21 +134,20 @@ pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) !void { |
| 135 | /// From a given `relocation` will return the new value to be written. | 134 | /// From a given `relocation` will return the new value to be written. |
| 136 | /// All values will be represented as a `u64` as all values can fit within it. | 135 | /// All values will be represented as a `u64` as all values can fit within it. |
| 137 | /// The final value must be casted to the correct size. | 136 | /// The final value must be casted to the correct size. |
| 138 | fn relocationValue(self: *Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 { | 137 | fn relocationValue(relocation: types.Relocation, wasm_bin: *const Wasm) !u64 { |
| 139 | const object = wasm_bin.objects.items[self.file]; | 138 | const symbol: Symbol = wasm_bin.symbols.items[relocation.index]; |
| 140 | const symbol: Symbol = object.symtable[relocation.index]; | ||
| 141 | return switch (relocation.relocation_type) { | 139 | return switch (relocation.relocation_type) { |
| 142 | .R_WASM_FUNCTION_INDEX_LEB => symbol.kind.function.functionIndex(), | 140 | .R_WASM_FUNCTION_INDEX_LEB => symbol.index, |
| 143 | .R_WASM_TABLE_NUMBER_LEB => symbol.kind.table.table.table_idx, | 141 | .R_WASM_TABLE_NUMBER_LEB => symbol.index, |
| 144 | .R_WASM_TABLE_INDEX_I32, | 142 | .R_WASM_TABLE_INDEX_I32, |
| 145 | .R_WASM_TABLE_INDEX_I64, | 143 | .R_WASM_TABLE_INDEX_I64, |
| 146 | .R_WASM_TABLE_INDEX_SLEB, | 144 | .R_WASM_TABLE_INDEX_SLEB, |
| 147 | .R_WASM_TABLE_INDEX_SLEB64, | 145 | .R_WASM_TABLE_INDEX_SLEB64, |
| 148 | => symbol.getTableIndex() orelse 0, | 146 | => return error.TodoImplementTableIndex, // find table index from a function symbol |
| 149 | .R_WASM_TYPE_INDEX_LEB => symbol.kind.function.func.type_idx, | 147 | .R_WASM_TYPE_INDEX_LEB => wasm_bin.functions.items[symbol.index].type_index, |
| 150 | .R_WASM_GLOBAL_INDEX_I32, | 148 | .R_WASM_GLOBAL_INDEX_I32, |
| 151 | .R_WASM_GLOBAL_INDEX_LEB, | 149 | .R_WASM_GLOBAL_INDEX_LEB, |
| 152 | => symbol.kind.global.global.global_idx, | 150 | => symbol.index, |
| 153 | .R_WASM_MEMORY_ADDR_I32, | 151 | .R_WASM_MEMORY_ADDR_I32, |
| 154 | .R_WASM_MEMORY_ADDR_I64, | 152 | .R_WASM_MEMORY_ADDR_I64, |
| 155 | .R_WASM_MEMORY_ADDR_LEB, | 153 | .R_WASM_MEMORY_ADDR_LEB, |
| ... | @@ -157,10 +155,10 @@ fn relocationValue(self: *Atom, relocation: types.Relocation, wasm_bin: *const W | ... | @@ -157,10 +155,10 @@ fn relocationValue(self: *Atom, relocation: types.Relocation, wasm_bin: *const W |
| 157 | .R_WASM_MEMORY_ADDR_SLEB, | 155 | .R_WASM_MEMORY_ADDR_SLEB, |
| 158 | .R_WASM_MEMORY_ADDR_SLEB64, | 156 | .R_WASM_MEMORY_ADDR_SLEB64, |
| 159 | => blk: { | 157 | => blk: { |
| 160 | if (symbol.isUndefined() and (symbol.kind == .data or symbol.isWeak())) { | 158 | if (symbol.isUndefined() and (symbol.tag == .data or symbol.isWeak())) { |
| 161 | return 0; | 159 | return 0; |
| 162 | } | 160 | } |
| 163 | const segment_name = object.segment_info[symbol.index().?].outputName(); | 161 | const segment_name = wasm_bin.segment_info.items[symbol.index].outputName(); |
| 164 | const atom_index = wasm_bin.data_segments.get(segment_name).?; | 162 | const atom_index = wasm_bin.data_segments.get(segment_name).?; |
| 165 | var target_atom = wasm_bin.atoms.getPtr(atom_index).?.*.getFirst(); | 163 | var target_atom = wasm_bin.atoms.getPtr(atom_index).?.*.getFirst(); |
| 166 | while (true) { | 164 | while (true) { |
| ... | @@ -170,11 +168,11 @@ fn relocationValue(self: *Atom, relocation: types.Relocation, wasm_bin: *const W | ... | @@ -170,11 +168,11 @@ fn relocationValue(self: *Atom, relocation: types.Relocation, wasm_bin: *const W |
| 170 | } else break; | 168 | } else break; |
| 171 | } | 169 | } |
| 172 | const segment = wasm_bin.segments.items[atom_index]; | 170 | const segment = wasm_bin.segments.items[atom_index]; |
| 173 | const base = wasm_bin.options.global_base orelse 1024; | 171 | const base = wasm_bin.base.options.global_base orelse 0; |
| 174 | const offset = target_atom.offset + segment.offset; | 172 | const offset = target_atom.offset + segment.offset; |
| 175 | break :blk offset + base + (relocation.addend orelse 0); | 173 | break :blk offset + base + (relocation.addend orelse 0); |
| 176 | }, | 174 | }, |
| 177 | .R_WASM_EVENT_INDEX_LEB => symbol.kind.event.index, | 175 | .R_WASM_EVENT_INDEX_LEB => symbol.index, |
| 178 | .R_WASM_SECTION_OFFSET_I32, | 176 | .R_WASM_SECTION_OFFSET_I32, |
| 179 | .R_WASM_FUNCTION_OFFSET_I32, | 177 | .R_WASM_FUNCTION_OFFSET_I32, |
| 180 | => relocation.offset, | 178 | => relocation.offset, |