authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2023-06-14 15:43:46-04:00
committergravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2023-06-16 08:34:30-04:00
log5343a2f566a5c235055f4aebb4ab9c10773e57f0
tree308e605be58fb7f63a283fb13d1fd6691bbb4c23
parent4dac9f54ddfcd6036b8b2b0704d0b9aa3ed9bd6d

plan9: revamp the relocation system to allow decl refs


4 files changed, 139 insertions(+), 78 deletions(-)

src/arch/x86_64/CodeGen.zig+5
...@@ -130,6 +130,8 @@ const Owner = union(enum) {...@@ -130,6 +130,8 @@ const Owner = union(enum) {
130 } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| {130 } else if (ctx.bin_file.cast(link.File.Coff)) |coff_file| {
131 const atom = try coff_file.getOrCreateAtomForDecl(decl_index);131 const atom = try coff_file.getOrCreateAtomForDecl(decl_index);
132 return coff_file.getAtom(atom).getSymbolIndex().?;132 return coff_file.getAtom(atom).getSymbolIndex().?;
133 } else if (ctx.bin_file.cast(link.File.Plan9)) |p9_file| {
134 return p9_file.seeDecl(decl_index);
133 } else unreachable;135 } else unreachable;
134 },136 },
135 .lazy_sym => |lazy_sym| {137 .lazy_sym => |lazy_sym| {
...@@ -141,6 +143,9 @@ const Owner = union(enum) {...@@ -141,6 +143,9 @@ const Owner = union(enum) {
141 const atom = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|143 const atom = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
142 return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});144 return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
143 return coff_file.getAtom(atom).getSymbolIndex().?;145 return coff_file.getAtom(atom).getSymbolIndex().?;
146 } else if (ctx.bin_file.cast(link.File.Plan9)) |p9_file| {
147 return p9_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
148 return ctx.fail("{s} creating lazy symbol", .{@errorName(err)});
144 } else unreachable;149 } else unreachable;
145 },150 },
146 }151 }
src/arch/x86_64/Emit.zig+8
...@@ -118,6 +118,14 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -118,6 +118,14 @@ pub fn emitMir(emit: *Emit) Error!void {
118 .pcrel = true,118 .pcrel = true,
119 .length = 2,119 .length = 2,
120 });120 });
121 } else if (emit.bin_file.cast(link.File.Plan9)) |p9_file| {
122 const atom_index = symbol.atom_index;
123 try p9_file.addReloc(atom_index, .{ // TODO we may need to add a .type field to the relocs if they are .linker_got instead of just .linker_direct
124 .target = symbol.sym_index, // we set sym_index to just be the atom index
125 .offset = @intCast(u32, end_offset - 4),
126 .addend = 0,
127 .pcrel = true,
128 });
121 } else return emit.fail("TODO implement linker reloc for {s}", .{129 } else return emit.fail("TODO implement linker reloc for {s}", .{
122 @tagName(emit.bin_file.tag),130 @tagName(emit.bin_file.tag),
123 }),131 }),
src/codegen.zig+3-6
...@@ -879,12 +879,9 @@ fn genUnnamedConst(...@@ -879,12 +879,9 @@ fn genUnnamedConst(
879 return GenResult.mcv(.{ .load_direct = local_sym_index });879 return GenResult.mcv(.{ .load_direct = local_sym_index });
880 } else if (bin_file.cast(link.File.Coff)) |_| {880 } else if (bin_file.cast(link.File.Coff)) |_| {
881 return GenResult.mcv(.{ .load_direct = local_sym_index });881 return GenResult.mcv(.{ .load_direct = local_sym_index });
882 } else if (bin_file.cast(link.File.Plan9)) |p9| {882 } else if (bin_file.cast(link.File.Plan9)) |_| {
883 const ptr_bits = target.ptrBitWidth();883 const atom_index = local_sym_index; // plan9 returns the atom_index
884 const ptr_bytes: u64 = @divExact(ptr_bits, 8);884 return GenResult.mcv(.{ .load_direct = atom_index });
885 const got_index = local_sym_index; // the plan9 backend returns the got_index
886 const got_addr = p9.bases.data + got_index * ptr_bytes;
887 return GenResult.mcv(.{ .memory = got_addr });
888 } else {885 } else {
889 return GenResult.fail(bin_file.allocator, src_loc, "TODO genUnnamedConst for target {}", .{target});886 return GenResult.fail(bin_file.allocator, src_loc, "TODO genUnnamedConst for target {}", .{target});
890 }887 }
src/link/Plan9.zig+123-72
...@@ -81,7 +81,7 @@ unnamed_const_atoms: UnnamedConstTable = .{},...@@ -81,7 +81,7 @@ unnamed_const_atoms: UnnamedConstTable = .{},
8181
82lazy_syms: LazySymbolTable = .{},82lazy_syms: LazySymbolTable = .{},
8383
84relocs: std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Reloc)) = .{},84relocs: std.AutoHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Reloc)) = .{},
85hdr: aout.ExecHdr = undefined,85hdr: aout.ExecHdr = undefined,
8686
87// relocs: std.87// relocs: std.
...@@ -100,9 +100,10 @@ atoms: std.ArrayListUnmanaged(Atom) = .{},...@@ -100,9 +100,10 @@ atoms: std.ArrayListUnmanaged(Atom) = .{},
100decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},100decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},
101101
102const Reloc = struct {102const Reloc = struct {
103 target: Module.Decl.Index,103 target: Atom.Index,
104 offset: u64,104 offset: u64,
105 addend: u32,105 addend: u32,
106 pcrel: bool = false,
106};107};
107108
108const Bases = struct {109const Bases = struct {
...@@ -111,7 +112,7 @@ const Bases = struct {...@@ -111,7 +112,7 @@ const Bases = struct {
111 data: u64,112 data: u64,
112};113};
113114
114const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(struct { info: Atom, code: []const u8 }));115const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index));
115116
116const LazySymbolTable = std.AutoArrayHashMapUnmanaged(Module.Decl.OptionalIndex, LazySymbolMetadata);117const LazySymbolTable = std.AutoArrayHashMapUnmanaged(Module.Decl.OptionalIndex, LazySymbolMetadata);
117118
...@@ -140,12 +141,36 @@ pub const Atom = struct {...@@ -140,12 +141,36 @@ pub const Atom = struct {
140 sym_index: ?usize,141 sym_index: ?usize,
141 /// offset into got142 /// offset into got
142 got_index: ?usize,143 got_index: ?usize,
143 /// We can optionally store code with the atom144 /// We include the code here to be use in relocs
144 /// It is still owned by whatever created it145 /// In the case of unnamed_const_atoms and lazy_syms, this atom owns the code.
145 /// This can be useful so that we don't need146 /// But, in the case of function and data decls, they own the code and this field
146 /// to setup so much infrastructure just to store code147 /// is just a pointer for convience.
147 /// for stuff like LazySymbols.148 code: CodePtr,
148 code: ?[]const u8 = null,149
150 const CodePtr = struct {
151 code_ptr: ?[*]u8,
152 other: union {
153 code_len: usize,
154 decl_index: Module.Decl.Index,
155 },
156 fn getCode(self: CodePtr, plan9: *const Plan9) []u8 {
157 const mod = plan9.base.options.module.?;
158 return if (self.code_ptr) |p| p[0..self.other.code_len] else blk: {
159 const decl_index = self.other.decl_index;
160 const decl = mod.declPtr(decl_index);
161 if (decl.ty.zigTypeTag(mod) == .Fn) {
162 const table = plan9.fn_decl_table.get(decl.getFileScope(mod)).?.functions;
163 const output = table.get(decl_index).?;
164 break :blk output.code;
165 } else {
166 break :blk plan9.data_decl_table.get(decl_index).?;
167 }
168 };
169 }
170 fn getOwnedCode(self: CodePtr) ?[]u8 {
171 return if (self.code_ptr) |p| p[0..self.other.code_len] else null;
172 }
173 };
149174
150 pub const Index = u32;175 pub const Index = u32;
151176
...@@ -329,7 +354,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: Module.Fn.Index, air:...@@ -329,7 +354,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: Module.Fn.Index, air:
329 const decl = mod.declPtr(decl_index);354 const decl = mod.declPtr(decl_index);
330 self.freeUnnamedConsts(decl_index);355 self.freeUnnamedConsts(decl_index);
331356
332 _ = try self.seeDecl(decl_index);357 const atom_idx = try self.seeDecl(decl_index);
333358
334 var code_buffer = std.ArrayList(u8).init(self.base.allocator);359 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
335 defer code_buffer.deinit();360 defer code_buffer.deinit();
...@@ -363,6 +388,10 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: Module.Fn.Index, air:...@@ -363,6 +388,10 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: Module.Fn.Index, air:
363 return;388 return;
364 },389 },
365 };390 };
391 self.getAtomPtr(atom_idx).code = .{
392 .code_ptr = null,
393 .other = .{ .decl_index = decl_index },
394 };
366 const out: FnDeclOutput = .{395 const out: FnDeclOutput = .{
367 .code = code,396 .code = code,
368 .lineinfo = try dbg_line_buffer.toOwnedSlice(),397 .lineinfo = try dbg_line_buffer.toOwnedSlice(),
...@@ -394,12 +423,13 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I...@@ -394,12 +423,13 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
394 const name = try std.fmt.allocPrint(self.base.allocator, "__unnamed_{s}_{d}", .{ decl_name, index });423 const name = try std.fmt.allocPrint(self.base.allocator, "__unnamed_{s}_{d}", .{ decl_name, index });
395424
396 const sym_index = try self.allocateSymbolIndex();425 const sym_index = try self.allocateSymbolIndex();
397426 const new_atom_idx = try self.createAtom();
398 const info: Atom = .{427 var info: Atom = .{
399 .type = .d,428 .type = .d,
400 .offset = null,429 .offset = null,
401 .sym_index = sym_index,430 .sym_index = sym_index,
402 .got_index = self.allocateGotIndex(),431 .got_index = self.allocateGotIndex(),
432 .code = undefined, // filled in later
403 };433 };
404 const sym: aout.Sym = .{434 const sym: aout.Sym = .{
405 .value = undefined,435 .value = undefined,
...@@ -411,7 +441,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I...@@ -411,7 +441,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
411 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), tv, &code_buffer, .{441 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), tv, &code_buffer, .{
412 .none = {},442 .none = {},
413 }, .{443 }, .{
414 .parent_atom_index = @enumToInt(decl_index),444 .parent_atom_index = new_atom_idx,
415 });445 });
416 const code = switch (res) {446 const code = switch (res) {
417 .ok => code_buffer.items,447 .ok => code_buffer.items,
...@@ -425,9 +455,12 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I...@@ -425,9 +455,12 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
425 // duped_code is freed when the unnamed const is freed455 // duped_code is freed when the unnamed const is freed
426 var duped_code = try self.base.allocator.dupe(u8, code);456 var duped_code = try self.base.allocator.dupe(u8, code);
427 errdefer self.base.allocator.free(duped_code);457 errdefer self.base.allocator.free(duped_code);
428 try unnamed_consts.append(self.base.allocator, .{ .info = info, .code = duped_code });458 const new_atom = self.getAtomPtr(new_atom_idx);
429 // we return the got_index to codegen so that it can reference to the place of the data in the got459 new_atom.* = info;
430 return @intCast(u32, info.got_index.?);460 new_atom.code = .{ .code_ptr = duped_code.ptr, .other = .{ .code_len = duped_code.len } };
461 try unnamed_consts.append(self.base.allocator, new_atom_idx);
462 // we return the new_atom_idx to codegen
463 return new_atom_idx;
431}464}
432465
433pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !void {466pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !void {
...@@ -442,7 +475,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !vo...@@ -442,7 +475,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !vo
442 }475 }
443 }476 }
444477
445 _ = try self.seeDecl(decl_index);478 const atom_idx = try self.seeDecl(decl_index);
446479
447 var code_buffer = std.ArrayList(u8).init(self.base.allocator);480 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
448 defer code_buffer.deinit();481 defer code_buffer.deinit();
...@@ -452,7 +485,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !vo...@@ -452,7 +485,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !vo
452 .ty = decl.ty,485 .ty = decl.ty,
453 .val = decl_val,486 .val = decl_val,
454 }, &code_buffer, .{ .none = {} }, .{487 }, &code_buffer, .{ .none = {} }, .{
455 .parent_atom_index = @enumToInt(decl_index),488 .parent_atom_index = @intCast(Atom.Index, atom_idx),
456 });489 });
457 const code = switch (res) {490 const code = switch (res) {
458 .ok => code_buffer.items,491 .ok => code_buffer.items,
...@@ -464,6 +497,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !vo...@@ -464,6 +497,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !vo
464 };497 };
465 try self.data_decl_table.ensureUnusedCapacity(self.base.allocator, 1);498 try self.data_decl_table.ensureUnusedCapacity(self.base.allocator, 1);
466 const duped_code = try self.base.allocator.dupe(u8, code);499 const duped_code = try self.base.allocator.dupe(u8, code);
500 self.getAtomPtr(self.decls.get(decl_index).?.index).code = .{ .code_ptr = null, .other = .{ .decl_index = decl_index } };
467 if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| {501 if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| {
468 self.base.allocator.free(old_entry.value);502 self.base.allocator.free(old_entry.value);
469 }503 }
...@@ -636,6 +670,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No...@@ -636,6 +670,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
636 var it = fentry.value_ptr.functions.iterator();670 var it = fentry.value_ptr.functions.iterator();
637 while (it.next()) |entry| {671 while (it.next()) |entry| {
638 const decl_index = entry.key_ptr.*;672 const decl_index = entry.key_ptr.*;
673 const decl = mod.declPtr(decl_index);
639 const atom = self.getAtomPtr(self.decls.get(decl_index).?.index);674 const atom = self.getAtomPtr(self.decls.get(decl_index).?.index);
640 const out = entry.value_ptr.*;675 const out = entry.value_ptr.*;
641 {676 {
...@@ -655,6 +690,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No...@@ -655,6 +690,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
655 const off = self.getAddr(text_i, .t);690 const off = self.getAddr(text_i, .t);
656 text_i += out.code.len;691 text_i += out.code.len;
657 atom.offset = off;692 atom.offset = off;
693 log.debug("write text decl {*} ({}), lines {d} to {d}.;__GOT+0x{x} vaddr: 0x{x}", .{ decl, decl.name.fmt(&mod.intern_pool), out.start_line + 1, out.end_line, atom.got_index.? * 8, off });
658 if (!self.sixtyfour_bit) {694 if (!self.sixtyfour_bit) {
659 mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian());695 mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian());
660 } else {696 } else {
...@@ -677,7 +713,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No...@@ -677,7 +713,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
677 while (it.next()) |kv| {713 while (it.next()) |kv| {
678 const meta = kv.value_ptr;714 const meta = kv.value_ptr;
679 const text_atom = if (meta.text_state != .unused) self.getAtomPtr(meta.text_atom) else continue;715 const text_atom = if (meta.text_state != .unused) self.getAtomPtr(meta.text_atom) else continue;
680 const code = text_atom.code.?;716 const code = text_atom.code.getOwnedCode().?;
681 foff += code.len;717 foff += code.len;
682 iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len };718 iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len };
683 iovecs_i += 1;719 iovecs_i += 1;
...@@ -725,21 +761,22 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No...@@ -725,21 +761,22 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
725 // write the unnamed constants after the other data decls761 // write the unnamed constants after the other data decls
726 var it_unc = self.unnamed_const_atoms.iterator();762 var it_unc = self.unnamed_const_atoms.iterator();
727 while (it_unc.next()) |unnamed_consts| {763 while (it_unc.next()) |unnamed_consts| {
728 for (unnamed_consts.value_ptr.items) |*unnamed_const| {764 for (unnamed_consts.value_ptr.items) |atom_idx| {
729 const code = unnamed_const.code;765 const atom = self.getAtomPtr(atom_idx);
730 log.debug("write unnamed const: ({s})", .{self.syms.items[unnamed_const.info.sym_index.?].name});766 const code = atom.code.getOwnedCode().?; // unnamed consts must own their code
767 log.debug("write unnamed const: ({s})", .{self.syms.items[atom.sym_index.?].name});
731 foff += code.len;768 foff += code.len;
732 iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len };769 iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len };
733 iovecs_i += 1;770 iovecs_i += 1;
734 const off = self.getAddr(data_i, .d);771 const off = self.getAddr(data_i, .d);
735 data_i += code.len;772 data_i += code.len;
736 unnamed_const.info.offset = off;773 atom.offset = off;
737 if (!self.sixtyfour_bit) {774 if (!self.sixtyfour_bit) {
738 mem.writeInt(u32, got_table[unnamed_const.info.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian());775 mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian());
739 } else {776 } else {
740 mem.writeInt(u64, got_table[unnamed_const.info.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian());777 mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian());
741 }778 }
742 self.syms.items[unnamed_const.info.sym_index.?].value = off;779 self.syms.items[atom.sym_index.?].value = off;
743 }780 }
744 }781 }
745 // the lazy data symbols782 // the lazy data symbols
...@@ -747,7 +784,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No...@@ -747,7 +784,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
747 while (it_lazy.next()) |kv| {784 while (it_lazy.next()) |kv| {
748 const meta = kv.value_ptr;785 const meta = kv.value_ptr;
749 const data_atom = if (meta.rodata_state != .unused) self.getAtomPtr(meta.rodata_atom) else continue;786 const data_atom = if (meta.rodata_state != .unused) self.getAtomPtr(meta.rodata_atom) else continue;
750 const code = data_atom.code.?;787 const code = data_atom.code.getOwnedCode().?; // lazy symbols must own their code
751 foff += code.len;788 foff += code.len;
752 iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len };789 iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len };
753 iovecs_i += 1;790 iovecs_i += 1;
...@@ -795,35 +832,31 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No...@@ -795,35 +832,31 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
795 {832 {
796 var it = self.relocs.iterator();833 var it = self.relocs.iterator();
797 while (it.next()) |kv| {834 while (it.next()) |kv| {
798 const source_decl_index = kv.key_ptr.*;835 const source_atom_index = kv.key_ptr.*;
799 const source_decl = mod.declPtr(source_decl_index);836 const source_atom = self.getAtom(source_atom_index);
837 const source_atom_symbol = self.syms.items[source_atom.sym_index.?];
800 for (kv.value_ptr.items) |reloc| {838 for (kv.value_ptr.items) |reloc| {
801 const target_decl_index = reloc.target;839 const target_atom_index = reloc.target;
802 const target_decl = mod.declPtr(target_decl_index);840 const target_atom = self.getAtomPtr(target_atom_index);
803 _ = target_decl;841 const target_symbol = self.syms.items[target_atom.sym_index.?];
804 const target_atom = self.getAtom(self.decls.get(target_decl_index).?.index);842 const target_offset = target_atom.offset.?;
805 const target_decl_offset = target_atom.offset.?;
806843
807 const offset = reloc.offset;844 const offset = reloc.offset;
808 const addend = reloc.addend;845 const addend = reloc.addend;
809846
810 const code = blk: {847 const code = source_atom.code.getCode(self);
811 const is_fn = source_decl.ty.zigTypeTag(mod) == .Fn;
812 if (is_fn) {
813 const table = self.fn_decl_table.get(source_decl.getFileScope(mod)).?.functions;
814 const output = table.get(source_decl_index).?;
815 break :blk output.code;
816 } else {
817 const code = self.data_decl_table.get(source_decl_index).?;
818 break :blk code;
819 }
820 };
821848
822 if (!self.sixtyfour_bit) {849 if (reloc.pcrel) {
823 mem.writeInt(u32, code[@intCast(usize, offset)..][0..4], @intCast(u32, target_decl_offset + addend), self.base.options.target.cpu.arch.endian());850 const disp = @intCast(i32, target_offset) - @intCast(i32, source_atom.offset.?) - 4 - @intCast(i32, offset);
851 mem.writeInt(i32, code[@intCast(usize, offset)..][0..4], @intCast(i32, disp), self.base.options.target.cpu.arch.endian());
824 } else {852 } else {
825 mem.writeInt(u64, code[@intCast(usize, offset)..][0..8], target_decl_offset + addend, self.base.options.target.cpu.arch.endian());853 if (!self.sixtyfour_bit) {
854 mem.writeInt(u32, code[@intCast(usize, offset)..][0..4], @intCast(u32, target_offset + addend), self.base.options.target.cpu.arch.endian());
855 } else {
856 mem.writeInt(u64, code[@intCast(usize, offset)..][0..8], target_offset + addend, self.base.options.target.cpu.arch.endian());
857 }
826 }858 }
859 log.debug("relocating the address of '{s}' + {d} into '{s}' + {d} (({s}[{d}] = 0x{x} + 0x{x})", .{ target_symbol.name, addend, source_atom_symbol.name, offset, source_atom_symbol.name, offset, target_offset, addend });
827 }860 }
828 }861 }
829 }862 }
...@@ -908,18 +941,19 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {...@@ -908,18 +941,19 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
908 }941 }
909 self.freeUnnamedConsts(decl_index);942 self.freeUnnamedConsts(decl_index);
910 {943 {
911 const relocs = self.relocs.getPtr(decl_index) orelse return;944 const atom_index = self.decls.get(decl_index).?.index;
945 const relocs = self.relocs.getPtr(atom_index) orelse return;
912 relocs.clearAndFree(self.base.allocator);946 relocs.clearAndFree(self.base.allocator);
913 assert(self.relocs.remove(decl_index));947 assert(self.relocs.remove(atom_index));
914 }948 }
915}949}
916fn freeUnnamedConsts(self: *Plan9, decl_index: Module.Decl.Index) void {950fn freeUnnamedConsts(self: *Plan9, decl_index: Module.Decl.Index) void {
917 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;951 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;
918 for (unnamed_consts.items) |c| {952 for (unnamed_consts.items) |atom_idx| {
919 self.base.allocator.free(self.syms.items[c.info.sym_index.?].name);953 const atom = self.getAtom(atom_idx);
920 self.base.allocator.free(c.code);954 self.base.allocator.free(self.syms.items[atom.sym_index.?].name);
921 self.syms.items[c.info.sym_index.?] = aout.Sym.undefined_symbol;955 self.syms.items[atom.sym_index.?] = aout.Sym.undefined_symbol;
922 self.syms_index_free_list.append(self.base.allocator, c.info.sym_index.?) catch {};956 self.syms_index_free_list.append(self.base.allocator, atom.sym_index.?) catch {};
923 }957 }
924 unnamed_consts.clearAndFree(self.base.allocator);958 unnamed_consts.clearAndFree(self.base.allocator);
925}959}
...@@ -933,6 +967,7 @@ fn createAtom(self: *Plan9) !Atom.Index {...@@ -933,6 +967,7 @@ fn createAtom(self: *Plan9) !Atom.Index {
933 .offset = null,967 .offset = null,
934 .sym_index = null,968 .sym_index = null,
935 .got_index = null,969 .got_index = null,
970 .code = undefined,
936 };971 };
937 return index;972 return index;
938}973}
...@@ -992,9 +1027,6 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind...@@ -992,9 +1027,6 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind
992 const gpa = self.base.allocator;1027 const gpa = self.base.allocator;
993 const mod = self.base.options.module.?;1028 const mod = self.base.options.module.?;
9941029
995 const atom = self.getAtomPtr(atom_index);
996 const local_sym_index = atom.sym_index.?;
997
998 var required_alignment: u32 = undefined;1030 var required_alignment: u32 = undefined;
999 var code_buffer = std.ArrayList(u8).init(gpa);1031 var code_buffer = std.ArrayList(u8).init(gpa);
1000 defer code_buffer.deinit();1032 defer code_buffer.deinit();
...@@ -1010,7 +1042,7 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind...@@ -1010,7 +1042,7 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind
1010 .type = if (sym.kind == .code) .t else .d,1042 .type = if (sym.kind == .code) .t else .d,
1011 .name = name,1043 .name = name,
1012 };1044 };
1013 self.syms.items[atom.sym_index.?] = symbol;1045 self.syms.items[self.getAtomPtr(atom_index).sym_index.?] = symbol;
10141046
1015 // generate the code1047 // generate the code
1016 const src = if (sym.ty.getOwnerDeclOrNull(mod)) |owner_decl|1048 const src = if (sym.ty.getOwnerDeclOrNull(mod)) |owner_decl|
...@@ -1028,7 +1060,7 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind...@@ -1028,7 +1060,7 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind
1028 &required_alignment,1060 &required_alignment,
1029 &code_buffer,1061 &code_buffer,
1030 .none,1062 .none,
1031 .{ .parent_atom_index = @intCast(u32, local_sym_index) },1063 .{ .parent_atom_index = @intCast(Atom.Index, atom_index) },
1032 );1064 );
1033 const code = switch (res) {1065 const code = switch (res) {
1034 .ok => code_buffer.items,1066 .ok => code_buffer.items,
...@@ -1040,8 +1072,10 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind...@@ -1040,8 +1072,10 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind
1040 // duped_code is freed when the atom is freed1072 // duped_code is freed when the atom is freed
1041 var duped_code = try self.base.allocator.dupe(u8, code);1073 var duped_code = try self.base.allocator.dupe(u8, code);
1042 errdefer self.base.allocator.free(duped_code);1074 errdefer self.base.allocator.free(duped_code);
10431075 self.getAtomPtr(atom_index).code = .{
1044 atom.code = duped_code;1076 .code_ptr = duped_code.ptr,
1077 .other = .{ .code_len = duped_code.len },
1078 };
1045}1079}
10461080
1047pub fn deinit(self: *Plan9) void {1081pub fn deinit(self: *Plan9) void {
...@@ -1089,8 +1123,8 @@ pub fn deinit(self: *Plan9) void {...@@ -1089,8 +1123,8 @@ pub fn deinit(self: *Plan9) void {
1089 self.syms_index_free_list.deinit(gpa);1123 self.syms_index_free_list.deinit(gpa);
1090 self.file_segments.deinit(gpa);1124 self.file_segments.deinit(gpa);
1091 self.path_arena.deinit();1125 self.path_arena.deinit();
1092 for (self.atoms.items) |atom| {1126 for (self.atoms.items) |a| {
1093 if (atom.code) |c| {1127 if (a.code.getOwnedCode()) |c| {
1094 gpa.free(c);1128 gpa.free(c);
1095 }1129 }
1096 }1130 }
...@@ -1151,7 +1185,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -1151,7 +1185,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
1151}1185}
11521186
1153pub fn writeSym(self: *Plan9, w: anytype, sym: aout.Sym) !void {1187pub fn writeSym(self: *Plan9, w: anytype, sym: aout.Sym) !void {
1154 log.debug("write sym{{name: {s}, value: {x}}}", .{ sym.name, sym.value });1188 // log.debug("write sym{{name: {s}, value: {x}}}", .{ sym.name, sym.value });
1155 if (sym.type == .bad) return; // we don't want to write free'd symbols1189 if (sym.type == .bad) return; // we don't want to write free'd symbols
1156 if (!self.sixtyfour_bit) {1190 if (!self.sixtyfour_bit) {
1157 try w.writeIntBig(u32, @intCast(u32, sym.value));1191 try w.writeIntBig(u32, @intCast(u32, sym.value));
...@@ -1210,6 +1244,17 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -1210,6 +1244,17 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1210 try self.writeSym(writer, sym);1244 try self.writeSym(writer, sym);
1211 }1245 }
1212 }1246 }
1247 // unnamed consts
1248 {
1249 var it = self.unnamed_const_atoms.iterator();
1250 while (it.next()) |kv| {
1251 const consts = kv.value_ptr;
1252 for (consts.items) |atom_index| {
1253 const sym = self.syms.items[self.getAtom(atom_index).sym_index.?];
1254 try self.writeSym(writer, sym);
1255 }
1256 }
1257 }
1213 // text symbols are the hardest:1258 // text symbols are the hardest:
1214 // the file of a text symbol is the .z symbol before it1259 // the file of a text symbol is the .z symbol before it
1215 // so we have to write everything in the right order1260 // so we have to write everything in the right order
...@@ -1266,6 +1311,7 @@ pub fn getDeclVAddr(...@@ -1266,6 +1311,7 @@ pub fn getDeclVAddr(
1266) !u64 {1311) !u64 {
1267 const mod = self.base.options.module.?;1312 const mod = self.base.options.module.?;
1268 const decl = mod.declPtr(decl_index);1313 const decl = mod.declPtr(decl_index);
1314 // we might already know the vaddr
1269 if (decl.ty.zigTypeTag(mod) == .Fn) {1315 if (decl.ty.zigTypeTag(mod) == .Fn) {
1270 var start = self.bases.text;1316 var start = self.bases.text;
1271 var it_file = self.fn_decl_table.iterator();1317 var it_file = self.fn_decl_table.iterator();
...@@ -1285,17 +1331,22 @@ pub fn getDeclVAddr(...@@ -1285,17 +1331,22 @@ pub fn getDeclVAddr(
1285 start += kv.value_ptr.len;1331 start += kv.value_ptr.len;
1286 }1332 }
1287 }1333 }
1334 const atom_index = try self.seeDecl(decl_index);
1288 // the parent_atom_index in this case is just the decl_index of the parent1335 // the parent_atom_index in this case is just the decl_index of the parent
1289 const gop = try self.relocs.getOrPut(self.base.allocator, @intToEnum(Module.Decl.Index, reloc_info.parent_atom_index));1336 try self.addReloc(reloc_info.parent_atom_index, .{
1290 if (!gop.found_existing) {1337 .target = atom_index,
1291 gop.value_ptr.* = .{};
1292 }
1293 try gop.value_ptr.append(self.base.allocator, .{
1294 .target = decl_index,
1295 .offset = reloc_info.offset,1338 .offset = reloc_info.offset,
1296 .addend = reloc_info.addend,1339 .addend = reloc_info.addend,
1297 });1340 });
1298 return 0;1341 return 0xcafebabe;
1342}
1343
1344pub fn addReloc(self: *Plan9, parent_index: Atom.Index, reloc: Reloc) !void {
1345 const gop = try self.relocs.getOrPut(self.base.allocator, parent_index);
1346 if (!gop.found_existing) {
1347 gop.value_ptr.* = .{};
1348 }
1349 try gop.value_ptr.append(self.base.allocator, reloc);
1299}1350}
13001351
1301pub fn getAtom(self: *const Plan9, index: Atom.Index) Atom {1352pub fn getAtom(self: *const Plan9, index: Atom.Index) Atom {