authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2022-10-04 17:16:30-04:00
committergravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2022-10-24 16:53:12-04:00
log6cba18fe6062f0da277a0b3c94ca8eadb5ab87ca
treede35c30b9a555c0abc594ba8d6e3d6438d373847
parent5cf3d10e35dd9f9e435af318d7c0055e77eee3a1

Add relocations to the plan9 backend


1 files changed, 74 insertions(+), 13 deletions(-)

src/link/Plan9.zig+74-13
...@@ -22,7 +22,8 @@ const log = std.log.scoped(.link);...@@ -22,7 +22,8 @@ const log = std.log.scoped(.link);
22const assert = std.debug.assert;22const assert = std.debug.assert;
2323
24const FnDeclOutput = struct {24const FnDeclOutput = struct {
25 code: []const u8,25 /// this code is modified when relocated so it is mutable
26 code: []u8,
26 /// this might have to be modified in the linker, so thats why its mutable27 /// this might have to be modified in the linker, so thats why its mutable
27 lineinfo: []u8,28 lineinfo: []u8,
28 start_line: u32,29 start_line: u32,
...@@ -61,7 +62,8 @@ fn_decl_table: std.AutoArrayHashMapUnmanaged(...@@ -61,7 +62,8 @@ fn_decl_table: std.AutoArrayHashMapUnmanaged(
61 *Module.File,62 *Module.File,
62 struct { sym_index: u32, functions: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, FnDeclOutput) = .{} },63 struct { sym_index: u32, functions: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, FnDeclOutput) = .{} },
63) = .{},64) = .{},
64data_decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, []const u8) = .{},65/// the code is modified when relocated, so that is why it is mutable
66data_decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, []u8) = .{},
6567
66/// Table of unnamed constants associated with a parent `Decl`.68/// Table of unnamed constants associated with a parent `Decl`.
67/// We store them here so that we can free the constants whenever the `Decl`69/// We store them here so that we can free the constants whenever the `Decl`
...@@ -83,6 +85,8 @@ data_decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, []const u8) =...@@ -83,6 +85,8 @@ data_decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, []const u8) =
83/// value assigned to label `foo` is an unnamed constant belonging/associated85/// value assigned to label `foo` is an unnamed constant belonging/associated
84/// with `Decl` `main`, and lives as long as that `Decl`.86/// with `Decl` `main`, and lives as long as that `Decl`.
85unnamed_const_atoms: UnnamedConstTable = .{},87unnamed_const_atoms: UnnamedConstTable = .{},
88
89relocs: std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Reloc)) = .{},
86hdr: aout.ExecHdr = undefined,90hdr: aout.ExecHdr = undefined,
8791
88// relocs: std.92// relocs: std.
...@@ -97,6 +101,12 @@ got_index_free_list: std.ArrayListUnmanaged(usize) = .{},...@@ -97,6 +101,12 @@ got_index_free_list: std.ArrayListUnmanaged(usize) = .{},
97101
98syms_index_free_list: std.ArrayListUnmanaged(usize) = .{},102syms_index_free_list: std.ArrayListUnmanaged(usize) = .{},
99103
104const Reloc = struct {
105 target: Module.Decl.Index,
106 offset: u64,
107 addend: u32,
108};
109
100const Bases = struct {110const Bases = struct {
101 text: u64,111 text: u64,
102 /// the Global Offset Table starts at the beginning of the data section112 /// the Global Offset Table starts at the beginning of the data section
...@@ -342,7 +352,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I...@@ -342,7 +352,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
342 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), tv, &code_buffer, .{352 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), tv, &code_buffer, .{
343 .none = {},353 .none = {},
344 }, .{354 }, .{
345 .parent_atom_index = undefined,355 .parent_atom_index = @enumToInt(decl_index),
346 });356 });
347 const code = switch (res) {357 const code = switch (res) {
348 .externally_managed => |x| x,358 .externally_managed => |x| x,
...@@ -377,18 +387,17 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)...@@ -377,18 +387,17 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
377387
378 try self.seeDecl(decl_index);388 try self.seeDecl(decl_index);
379389
380 log.debug("codegen decl {*} ({s})", .{ decl, decl.name });390 log.debug("codegen decl {*} ({s}) ({d})", .{ decl, decl.name, decl_index });
381391
382 var code_buffer = std.ArrayList(u8).init(self.base.allocator);392 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
383 defer code_buffer.deinit();393 defer code_buffer.deinit();
384 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;394 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
385 // TODO we need the symbol index for symbol in the table of locals for the containing atom395 // TODO we need the symbol index for symbol in the table of locals for the containing atom
386 const sym_index = decl.link.plan9.sym_index orelse 0;
387 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{396 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
388 .ty = decl.ty,397 .ty = decl.ty,
389 .val = decl_val,398 .val = decl_val,
390 }, &code_buffer, .{ .none = {} }, .{399 }, &code_buffer, .{ .none = {} }, .{
391 .parent_atom_index = @intCast(u32, sym_index),400 .parent_atom_index = @enumToInt(decl_index),
392 });401 });
393 const code = switch (res) {402 const code = switch (res) {
394 .externally_managed => |x| x,403 .externally_managed => |x| x,
...@@ -655,6 +664,42 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No...@@ -655,6 +664,42 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
655 if (self.sixtyfour_bit) {664 if (self.sixtyfour_bit) {
656 mem.writeIntSliceBig(u64, hdr_buf[32..40], self.entry_val.?);665 mem.writeIntSliceBig(u64, hdr_buf[32..40], self.entry_val.?);
657 }666 }
667 // perform the relocs
668 {
669 var it = self.relocs.iterator();
670 while (it.next()) |kv| {
671 const source_decl_index = kv.key_ptr.*;
672 const source_decl = mod.declPtr(source_decl_index);
673 for (kv.value_ptr.items) |reloc| {
674 const target_decl_index = reloc.target;
675 const target_decl = mod.declPtr(target_decl_index);
676 const target_decl_offset = target_decl.link.plan9.offset.?;
677
678 const offset = reloc.offset;
679 const addend = reloc.addend;
680
681 log.debug("relocating the address of '{s}' + {d} into '{s}' + {d}", .{ target_decl.name, addend, source_decl.name, offset });
682
683 const code = blk: {
684 const is_fn = source_decl.ty.zigTypeTag() == .Fn;
685 if (is_fn) {
686 const table = self.fn_decl_table.get(source_decl.getFileScope()).?.functions;
687 const output = table.get(source_decl_index).?;
688 break :blk output.code;
689 } else {
690 const code = self.data_decl_table.get(source_decl_index).?;
691 break :blk code;
692 }
693 };
694
695 if (!self.sixtyfour_bit) {
696 mem.writeInt(u32, code[@intCast(usize, offset)..][0..4], @intCast(u32, target_decl_offset + addend), self.base.options.target.cpu.arch.endian());
697 } else {
698 mem.writeInt(u64, code[@intCast(usize, offset)..][0..8], target_decl_offset + addend, self.base.options.target.cpu.arch.endian());
699 }
700 }
701 }
702 }
658 // write it all!703 // write it all!
659 try file.pwritevAll(iovecs, 0);704 try file.pwritevAll(iovecs, 0);
660}705}
...@@ -716,6 +761,11 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {...@@ -716,6 +761,11 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
716 self.syms.items[i] = aout.Sym.undefined_symbol;761 self.syms.items[i] = aout.Sym.undefined_symbol;
717 }762 }
718 self.freeUnnamedConsts(decl_index);763 self.freeUnnamedConsts(decl_index);
764 {
765 const relocs = self.relocs.getPtr(decl_index) orelse return;
766 relocs.clearAndFree(self.base.allocator);
767 assert(self.relocs.remove(decl_index));
768 }
719}769}
720fn freeUnnamedConsts(self: *Plan9, decl_index: Module.Decl.Index) void {770fn freeUnnamedConsts(self: *Plan9, decl_index: Module.Decl.Index) void {
721 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;771 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;
...@@ -749,6 +799,13 @@ pub fn updateDeclExports(...@@ -749,6 +799,13 @@ pub fn updateDeclExports(
749}799}
750pub fn deinit(self: *Plan9) void {800pub fn deinit(self: *Plan9) void {
751 const gpa = self.base.allocator;801 const gpa = self.base.allocator;
802 {
803 var it = self.relocs.valueIterator();
804 while (it.next()) |relocs| {
805 relocs.deinit(self.base.allocator);
806 }
807 self.relocs.deinit(self.base.allocator);
808 }
752 // free the unnamed consts809 // free the unnamed consts
753 var it_unc = self.unnamed_const_atoms.iterator();810 var it_unc = self.unnamed_const_atoms.iterator();
754 while (it_unc.next()) |kv| {811 while (it_unc.next()) |kv| {
...@@ -904,7 +961,6 @@ pub fn getDeclVAddr(...@@ -904,7 +961,6 @@ pub fn getDeclVAddr(
904 decl_index: Module.Decl.Index,961 decl_index: Module.Decl.Index,
905 reloc_info: link.File.RelocInfo,962 reloc_info: link.File.RelocInfo,
906) !u64 {963) !u64 {
907 _ = reloc_info;
908 const mod = self.base.options.module.?;964 const mod = self.base.options.module.?;
909 const decl = mod.declPtr(decl_index);965 const decl = mod.declPtr(decl_index);
910 if (decl.ty.zigTypeTag() == .Fn) {966 if (decl.ty.zigTypeTag() == .Fn) {
...@@ -918,9 +974,6 @@ pub fn getDeclVAddr(...@@ -918,9 +974,6 @@ pub fn getDeclVAddr(
918 start += entry.value_ptr.code.len;974 start += entry.value_ptr.code.len;
919 }975 }
920 }976 }
921 // TODO
922 return undefined;
923 // unreachable;
924 } else {977 } else {
925 var start = self.bases.data + self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8;978 var start = self.bases.data + self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8;
926 var it = self.data_decl_table.iterator();979 var it = self.data_decl_table.iterator();
...@@ -928,8 +981,16 @@ pub fn getDeclVAddr(...@@ -928,8 +981,16 @@ pub fn getDeclVAddr(
928 if (decl_index == kv.key_ptr.*) return start;981 if (decl_index == kv.key_ptr.*) return start;
929 start += kv.value_ptr.len;982 start += kv.value_ptr.len;
930 }983 }
931 // TODO
932 return undefined;
933 // unreachable;
934 }984 }
985 // the parent_atom_index in this case is just the decl_index of the parent
986 const gop = try self.relocs.getOrPut(self.base.allocator, @intToEnum(Module.Decl.Index, reloc_info.parent_atom_index));
987 if (!gop.found_existing) {
988 gop.value_ptr.* = .{};
989 }
990 try gop.value_ptr.append(self.base.allocator, .{
991 .target = decl_index,
992 .offset = reloc_info.offset,
993 .addend = reloc_info.addend,
994 });
995 return undefined;
935}996}