From b9b1ab024063105a9adfe3828692867c91015dc6 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 10 Feb 2022 14:41:07 +0100 Subject: [PATCH] elf: store pointer relocations indexed by containing atom In `getDeclVAddr`, it may happen that the target `Decl` has not been allocated space in virtual memory. In this case, we store a relocation in the linker-global table which we will iterate over when flushing the module, and fill in any missing address in the final binary. Note that for optimisation, if the address was resolved at the time of a call to `getDeclVAddr`, we skip relocating this atom. This commit also adds the glue code for lowering const slices in the ARM backend. --- src/arch/arm/CodeGen.zig | 25 ++++----- src/codegen.zig | 30 +++++------ src/link.zig | 14 +++-- src/link/Coff.zig | 8 +-- src/link/Elf.zig | 113 ++++++++++++++++++++++++++++++++------- src/link/MachO.zig | 53 +++++++++--------- src/link/Plan9.zig | 6 ++- 7 files changed, 163 insertions(+), 86 deletions(-) diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 711e2a96f05c32548f128bf56d29cf5316f8cdcc..2c60027d974f1e3d552fb1f894e88a85df6d475d 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -3931,23 +3931,20 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { switch (typed_value.ty.zigTypeTag()) { .Pointer => switch (typed_value.ty.ptrSize()) { .Slice => { - var buf: Type.SlicePtrFieldTypeBuffer = undefined; - const ptr_type = typed_value.ty.slicePtrFieldType(&buf); - const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val }); - const slice_len = typed_value.val.sliceLen(); - // Codegen can't handle some kinds of indirection. If the wrong union field is accessed here it may mean - // the Sema code needs to use anonymous Decls or alloca instructions to store data. - const ptr_imm = ptr_mcv.memory; - _ = slice_len; - _ = ptr_imm; - // We need more general support for const data being stored in memory to make this work. - return self.fail("TODO codegen for const slices", .{}); + return self.lowerUnnamedConst(typed_value); }, else => { - if (typed_value.val.tag() == .int_u64) { - return MCValue{ .immediate = @intCast(u32, typed_value.val.toUnsignedInt()) }; + switch (typed_value.val.tag()) { + .int_u64 => { + return MCValue{ .immediate = @intCast(u32, typed_value.val.toUnsignedInt()) }; + }, + .slice => { + return self.lowerUnnamedConst(typed_value); + }, + else => { + return self.fail("TODO codegen more kinds of const pointers", .{}); + }, } - return self.fail("TODO codegen more kinds of const pointers", .{}); }, }, .Int => { diff --git a/src/codegen.zig b/src/codegen.zig index 389f38a0204caef6fc10a92104e799cd9ff77304..fd4321fee9fdb889ea1fd1e08f0d494ce206b610 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -142,6 +142,7 @@ pub fn generateFunction( pub fn generateSymbol( bin_file: *link.File, + parent_atom_index: u32, src_loc: Module.SrcLoc, typed_value: TypedValue, code: *std.ArrayList(u8), @@ -177,7 +178,7 @@ pub fn generateSymbol( if (typed_value.ty.sentinel()) |sentinel| { try code.ensureUnusedCapacity(payload.data.len + 1); code.appendSliceAssumeCapacity(payload.data); - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = typed_value.ty.elemType(), .val = sentinel, }, code, debug_output)) { @@ -197,7 +198,7 @@ pub fn generateSymbol( const elem_vals = typed_value.val.castTag(.array).?.data; const elem_ty = typed_value.ty.elemType(); for (elem_vals) |elem_val| { - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = elem_ty, .val = elem_val, }, code, debug_output)) { @@ -223,11 +224,11 @@ pub fn generateSymbol( .Pointer => switch (typed_value.val.tag()) { .variable => { const decl = typed_value.val.castTag(.variable).?.data.owner_decl; - return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output); + return lowerDeclRef(bin_file, parent_atom_index, src_loc, typed_value, decl, code, debug_output); }, .decl_ref => { const decl = typed_value.val.castTag(.decl_ref).?.data; - return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output); + return lowerDeclRef(bin_file, parent_atom_index, src_loc, typed_value, decl, code, debug_output); }, .slice => { const slice = typed_value.val.castTag(.slice).?.data; @@ -235,7 +236,7 @@ pub fn generateSymbol( // generate ptr var buf: Type.SlicePtrFieldTypeBuffer = undefined; const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf); - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = slice_ptr_field_type, .val = slice.ptr, }, code, debug_output)) { @@ -247,7 +248,7 @@ pub fn generateSymbol( } // generate length - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = Type.initTag(.usize), .val = slice.len, }, code, debug_output)) { @@ -391,7 +392,7 @@ pub fn generateSymbol( const field_ty = typed_value.ty.structFieldType(index); if (!field_ty.hasRuntimeBits()) continue; - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = field_ty, .val = field_val, }, code, debug_output)) { @@ -446,6 +447,7 @@ pub fn generateSymbol( fn lowerDeclRef( bin_file: *link.File, + parent_atom_index: u32, src_loc: Module.SrcLoc, typed_value: TypedValue, decl: *Module.Decl, @@ -456,7 +458,7 @@ fn lowerDeclRef( // generate ptr var buf: Type.SlicePtrFieldTypeBuffer = undefined; const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf); - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = slice_ptr_field_type, .val = typed_value.val, }, code, debug_output)) { @@ -472,7 +474,7 @@ fn lowerDeclRef( .base = .{ .tag = .int_u64 }, .data = typed_value.val.sliceLen(), }; - switch (try generateSymbol(bin_file, src_loc, .{ + switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{ .ty = Type.initTag(.usize), .val = Value.initPayload(&slice_len.base), }, code, debug_output)) { @@ -495,15 +497,7 @@ fn lowerDeclRef( } decl.markAlive(); - const vaddr = vaddr: { - if (bin_file.cast(link.File.MachO)) |macho_file| { - break :vaddr try macho_file.getDeclVAddrWithReloc(decl, code.items.len); - } - // TODO handle the dependency of this symbol on the decl's vaddr. - // If the decl changes vaddr, then this symbol needs to get regenerated. - break :vaddr bin_file.getDeclVAddr(decl); - }; - + const vaddr = try bin_file.getDeclVAddr(decl, parent_atom_index, code.items.len); const endian = target.cpu.arch.endian(); switch (ptr_width) { 16 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(u16, vaddr), endian), diff --git a/src/link.zig b/src/link.zig index 56b88bffefc495603038f21c72d5886ac8658faa..c5d14eb75a0ed8497fd873e1e35ac581a7484dc2 100644 --- a/src/link.zig +++ b/src/link.zig @@ -684,12 +684,16 @@ pub const File = struct { } } - pub fn getDeclVAddr(base: *File, decl: *const Module.Decl) u64 { + /// Get allocated `Decl`'s address in virtual memory. + /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's + /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the + /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory. + pub fn getDeclVAddr(base: *File, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 { switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl), - .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl), - .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl), - .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl), + .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl, parent_atom_index, offset), + .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl, parent_atom_index, offset), + .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, parent_atom_index, offset), + .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, parent_atom_index, offset), .c => unreachable, .wasm => unreachable, .spirv => unreachable, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 2f500e6b91bbff9831eb12ffbb417df5d65ca650..32d4d382356865033a042f8583fbe3ed49d9701b 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -726,7 +726,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { var code_buffer = std.ArrayList(u8).init(self.base.allocator); defer code_buffer.deinit(); - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ + const res = try codegen.generateSymbol(&self.base, 0, decl.srcLoc(), .{ .ty = decl.ty, .val = decl.val, }, &code_buffer, .none); @@ -751,7 +751,7 @@ fn finishUpdateDecl(self: *Coff, module: *Module, decl: *Module.Decl, code: []co const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u32, decl.link.coff.text_offset, required_alignment); if (need_realloc) { - const curr_vaddr = self.getDeclVAddr(decl); + const curr_vaddr = self.text_section_virtual_address + decl.link.coff.text_offset; const vaddr = try self.growTextBlock(&decl.link.coff, code.len, required_alignment); log.debug("growing {s} from 0x{x} to 0x{x}\n", .{ decl.name, curr_vaddr, vaddr }); if (vaddr != curr_vaddr) { @@ -1465,7 +1465,9 @@ fn findLib(self: *Coff, arena: Allocator, name: []const u8) !?[]const u8 { return null; } -pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 { +pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 { + _ = parent_atom_index; + _ = offset; assert(self.llvm_object == null); return self.text_section_virtual_address + decl.link.coff.text_offset; } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 23bd5bb2dde50f65a21350202950988106a2c6d9..467bbeee54d346a87f9b3ec45d6c28de55990eb1 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -145,6 +145,7 @@ decls: std.AutoHashMapUnmanaged(*Module.Decl, ?u16) = .{}, /// at present owned by Module.Decl. /// TODO consolidate this. managed_atoms: std.ArrayListUnmanaged(*TextBlock) = .{}, +atom_by_index_table: std.AutoHashMapUnmanaged(u32, *TextBlock) = .{}, /// Table of unnamed constants associated with a parent `Decl`. /// We store them here so that we can free the constants whenever the `Decl` @@ -179,6 +180,18 @@ dbg_info_decl_free_list: std.AutoHashMapUnmanaged(*TextBlock, void) = .{}, dbg_info_decl_first: ?*TextBlock = null, dbg_info_decl_last: ?*TextBlock = null, +/// A table of relocations indexed by the owning them `TextBlock`. +/// Note that once we refactor `TextBlock`'s lifetime and ownership rules, +/// this will be a table indexed by index into the list of Atoms. +relocs: RelocTable = .{}, + +const Reloc = struct { + target: u32, + offset: u64, + prev_vaddr: u64, +}; + +const RelocTable = std.AutoHashMapUnmanaged(*TextBlock, std.ArrayListUnmanaged(Reloc)); const UnnamedConstTable = std.AutoHashMapUnmanaged(*Module.Decl, std.ArrayListUnmanaged(*TextBlock)); /// When allocating, the ideal_capacity is calculated by @@ -397,12 +410,36 @@ pub fn deinit(self: *Elf) void { } self.unnamed_const_atoms.deinit(self.base.allocator); } + + { + var it = self.relocs.valueIterator(); + while (it.next()) |relocs| { + relocs.deinit(self.base.allocator); + } + self.relocs.deinit(self.base.allocator); + } + + self.atom_by_index_table.deinit(self.base.allocator); } -pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 { +pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 { assert(self.llvm_object == null); assert(decl.link.elf.local_sym_index != 0); - return self.local_symbols.items[decl.link.elf.local_sym_index].st_value; + + const target = decl.link.elf.local_sym_index; + const vaddr = self.local_symbols.items[target].st_value; + const atom = self.atom_by_index_table.get(parent_atom_index).?; + const gop = try self.relocs.getOrPut(self.base.allocator, atom); + if (!gop.found_existing) { + gop.value_ptr.* = .{}; + } + try gop.value_ptr.append(self.base.allocator, .{ + .target = target, + .offset = offset, + .prev_vaddr = vaddr, + }); + + return vaddr; } fn getDebugLineProgramOff(self: Elf) u32 { @@ -991,6 +1028,41 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { .p64 => 12, }; + { + var it = self.relocs.iterator(); + while (it.next()) |entry| { + const atom = entry.key_ptr.*; + const relocs = entry.value_ptr.*; + const source_sym = self.local_symbols.items[atom.local_sym_index]; + const source_shdr = self.sections.items[source_sym.st_shndx]; + + log.debug("relocating '{s}'", .{self.getString(source_sym.st_name)}); + + for (relocs.items) |*reloc| { + const target_sym = self.local_symbols.items[reloc.target]; + const target_vaddr = target_sym.st_value; + + if (target_vaddr == reloc.prev_vaddr) continue; + + const section_offset = (source_sym.st_value + reloc.offset) - source_shdr.sh_addr; + const file_offset = source_shdr.sh_offset + section_offset; + + log.debug(" ({x}: [() => 0x{x}] ({s}))", .{ + reloc.offset, + target_vaddr, + self.getString(target_sym.st_name), + }); + + switch (self.ptr_width) { + .p32 => try self.base.file.?.pwriteAll(mem.asBytes(&@intCast(u32, target_vaddr)), file_offset), + .p64 => try self.base.file.?.pwriteAll(mem.asBytes(&target_vaddr), file_offset), + } + + reloc.prev_vaddr = target_vaddr; + } + } + } + // Unfortunately these have to be buffered and done at the end because ELF does not allow // mixing local and global symbols within a symbol table. try self.writeAllGlobalSymbols(); @@ -2508,6 +2580,7 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { log.debug("allocating symbol indexes for {s}", .{decl.name}); decl.link.elf.local_sym_index = try self.allocateLocalSymbol(); + try self.atom_by_index_table.putNoClobber(self.base.allocator, decl.link.elf.local_sym_index, &decl.link.elf); if (self.offset_table_free_list.popOrNull()) |i| { decl.link.elf.offset_table_index = i; @@ -2525,6 +2598,7 @@ fn freeUnnamedConsts(self: *Elf, decl: *Module.Decl) void { self.freeTextBlock(atom, self.phdr_load_ro_index.?); self.local_symbol_free_list.append(self.base.allocator, atom.local_sym_index) catch {}; self.local_symbols.items[atom.local_sym_index].st_info = 0; + _ = self.atom_by_index_table.remove(atom.local_sym_index); } unnamed_consts.clearAndFree(self.base.allocator); } @@ -2543,11 +2617,11 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. if (decl.link.elf.local_sym_index != 0) { self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {}; - self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {}; - self.local_symbols.items[decl.link.elf.local_sym_index].st_info = 0; - + _ = self.atom_by_index_table.remove(decl.link.elf.local_sym_index); decl.link.elf.local_sym_index = 0; + + self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {}; } // TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing // is desired for both. @@ -2993,7 +3067,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { // TODO implement .debug_info for global variables const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ + const res = try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{ .ty = decl.ty, .val = decl_val, }, &code_buffer, .{ @@ -3028,19 +3102,6 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl } const unnamed_consts = gop.value_ptr; - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{ - .none = .{}, - }); - const code = switch (res) { - .externally_managed => |x| x, - .appended => code_buffer.items, - .fail => |em| { - decl.analysis = .codegen_failure; - try module.failed_decls.put(module.gpa, decl, em); - return error.AnalysisFail; - }, - }; - const atom = try self.base.allocator.create(TextBlock); errdefer self.base.allocator.destroy(atom); atom.* = TextBlock.empty; @@ -3056,6 +3117,20 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl log.debug("allocating symbol indexes for {s}", .{name}); atom.local_sym_index = try self.allocateLocalSymbol(); + try self.atom_by_index_table.putNoClobber(self.base.allocator, atom.local_sym_index, atom); + + const res = try codegen.generateSymbol(&self.base, atom.local_sym_index, decl.srcLoc(), typed_value, &code_buffer, .{ + .none = .{}, + }); + const code = switch (res) { + .externally_managed => |x| x, + .appended => code_buffer.items, + .fail => |em| { + decl.analysis = .codegen_failure; + try module.failed_decls.put(module.gpa, decl, em); + return error.AnalysisFail; + }, + }; const required_alignment = typed_value.ty.abiAlignment(self.base.options.target); const phdr_index = self.phdr_load_ro_index.?; diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 065145cdc89ee6c75dc1309064f5ef2025838f4b..37040f267f2f6fb2e5ba290e586f8e53547fe012 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3745,19 +3745,6 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De } const unnamed_consts = gop.value_ptr; - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{ - .none = .{}, - }); - const code = switch (res) { - .externally_managed => |x| x, - .appended => code_buffer.items, - .fail => |em| { - decl.analysis = .codegen_failure; - try module.failed_decls.put(module.gpa, decl, em); - return error.AnalysisFail; - }, - }; - const name_str_index = blk: { const index = unnamed_consts.items.len; const name = try std.fmt.allocPrint(self.base.allocator, "__unnamed_{s}_{d}", .{ decl.name, index }); @@ -3772,12 +3759,27 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De const match = (try self.getMatchingSection(.{ .segname = makeStaticString("__TEXT"), .sectname = makeStaticString("__const"), - .size = code.len, + .size = @sizeOf(u64), .@"align" = math.log2(required_alignment), })).?; const local_sym_index = try self.allocateLocalSymbol(); - const atom = try self.createEmptyAtom(local_sym_index, code.len, math.log2(required_alignment)); - mem.copy(u8, atom.code.items, code); + const atom = try self.createEmptyAtom(local_sym_index, @sizeOf(u64), math.log2(required_alignment)); + + const res = try codegen.generateSymbol(&self.base, local_sym_index, decl.srcLoc(), typed_value, &code_buffer, .{ + .none = .{}, + }); + const code = switch (res) { + .externally_managed => |x| x, + .appended => code_buffer.items, + .fail => |em| { + decl.analysis = .codegen_failure; + try module.failed_decls.put(module.gpa, decl, em); + return error.AnalysisFail; + }, + }; + + atom.code.clearRetainingCapacity(); + try atom.code.appendSlice(self.base.allocator, code); const addr = try self.allocateAtom(atom, code.len, required_alignment, match); log.debug("allocated atom for {s} at 0x{x}", .{ name, addr }); @@ -3841,7 +3843,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; const res = if (debug_buffers) |dbg| - try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ + try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{ .ty = decl.ty, .val = decl_val, }, &code_buffer, .{ @@ -3852,7 +3854,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { }, }) else - try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ + try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{ .ty = decl.ty, .val = decl_val, }, &code_buffer, .none); @@ -4341,16 +4343,17 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { } } -pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 { +pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 { + assert(self.llvm_object == null); assert(decl.link.macho.local_sym_index != 0); - return self.locals.items[decl.link.macho.local_sym_index].n_value; -} -pub fn getDeclVAddrWithReloc(self: *MachO, decl: *const Module.Decl, offset: u64) !u64 { - assert(decl.link.macho.local_sym_index != 0); - assert(self.active_decl != null); + // TODO cache local_sym_index => atom!!! + const atom: *Atom = blk: for (self.managed_atoms.items) |atom| { + if (atom.local_sym_index == parent_atom_index) { + break :blk atom; + } + } else unreachable; - const atom = &self.active_decl.?.link.macho; try atom.relocs.append(self.base.allocator, .{ .offset = @intCast(u32, offset), .target = .{ .local = decl.link.macho.local_sym_index }, diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index c2d6d6106676e33d24394a80ac743d25516d1bd4..ee7272ca8d1a7046d24fff1bdc951b50e230859f 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -302,7 +302,7 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void { var code_buffer = std.ArrayList(u8).init(self.base.allocator); defer code_buffer.deinit(); const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ + const res = try codegen.generateSymbol(&self.base, @intCast(u32, decl.link.plan9.sym_index.?), decl.srcLoc(), .{ .ty = decl.ty, .val = decl_val, }, &code_buffer, .{ .none = .{} }); @@ -749,7 +749,9 @@ pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void { _ = self; _ = decl; } -pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl) u64 { +pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 { + _ = parent_atom_index; + _ = offset; if (decl.ty.zigTypeTag() == .Fn) { var start = self.bases.text; var it_file = self.fn_decl_table.iterator(); -- 2.54.0