| ... | @@ -17,7 +17,7 @@ const assert = std.debug.assert; | ... | @@ -17,7 +17,7 @@ const assert = std.debug.assert; |
| 17 | // TODO use incremental compilation | 17 | // TODO use incremental compilation |
| 18 | | 18 | |
| 19 | base: link.File, | 19 | base: link.File, |
| 20 | ptr_width: PtrWidth, | 20 | sixtyfour_bit: bool, |
| 21 | error_flags: File.ErrorFlags = File.ErrorFlags{}, | 21 | error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| 22 | bases: Bases, | 22 | bases: Bases, |
| 23 | | 23 | |
| ... | @@ -33,41 +33,35 @@ entry_decl: ?*Module.Decl = null, | ... | @@ -33,41 +33,35 @@ entry_decl: ?*Module.Decl = null, |
| 33 | | 33 | |
| 34 | got: std.ArrayListUnmanaged(u64) = .{}, | 34 | got: std.ArrayListUnmanaged(u64) = .{}, |
| 35 | const Bases = struct { | 35 | const Bases = struct { |
| 36 | text: u32, | 36 | text: u64, |
| 37 | /// the addr of the got | 37 | /// the addr of the got |
| 38 | data: u32, | 38 | data: u64, |
| 39 | }; | 39 | }; |
| 40 | | 40 | |
| 41 | fn getAddr(self: Plan9, addr: u32, t: aout.SymType) u32 { | 41 | fn getAddr(self: Plan9, addr: u64, t: aout.SymType) u64 { |
| 42 | return addr + switch (t) { | 42 | return addr + switch (t) { |
| 43 | .T, .t => self.bases.text, | 43 | .T, .t, .l, .L => self.bases.text, |
| 44 | .D, .d, .B, .b => self.bases.data, | 44 | .D, .d, .B, .b => self.bases.data, |
| 45 | else => @panic("get address for more symbol types"), | 45 | else => unreachable, |
| 46 | }; | 46 | }; |
| 47 | } | 47 | } |
| 48 | /// opposite of getAddr | 48 | /// opposite of getAddr |
| 49 | fn takeAddr(self: Plan9, addr: u32, t: aout.SymType) u32 { | 49 | fn takeAddr(self: Plan9, addr: u64, t: aout.SymType) u64 { |
| 50 | return addr - switch (t) { | 50 | return addr - switch (t) { |
| 51 | .T, .t => self.bases.text, | 51 | .T, .t, .l, .L => self.bases.text, |
| 52 | .D, .d, .B, .b => self.bases.data, // TODO is .b correct here? | 52 | .D, .d, .B, .b => self.bases.data, |
| 53 | else => @panic("take address for more symbol types"), | 53 | else => unreachable, |
| 54 | }; | 54 | }; |
| 55 | } | 55 | } |
| 56 | | 56 | |
| 57 | fn getSymAddr(self: Plan9, s: aout.Sym) u32 { | 57 | fn getSymAddr(self: Plan9, s: aout.Sym) u64 { |
| 58 | return self.getAddr(@intCast(u32, s.value), s.type); | 58 | return self.getAddr(s.value, s.type); |
| 59 | } | | |
| 60 | | | |
| 61 | fn headerSize(self: Plan9) u32 { | | |
| 62 | // fat header (currently unused) | | |
| 63 | const fat: u8 = if (self.ptr_width == .p64) 8 else 0; | | |
| 64 | return @sizeOf(aout.ExecHdr) + fat; | | |
| 65 | } | 59 | } |
| 66 | | 60 | |
| 67 | pub const DeclBlock = struct { | 61 | pub const DeclBlock = struct { |
| 68 | type: aout.SymType, | 62 | type: aout.SymType, |
| 69 | /// offset in the text or data sects | 63 | /// offset in the text or data sects |
| 70 | offset: ?u32, | 64 | offset: ?u64, |
| 71 | /// offset into syms | 65 | /// offset into syms |
| 72 | sym_index: ?usize, | 66 | sym_index: ?usize, |
| 73 | /// offset into got | 67 | /// offset into got |
| ... | @@ -101,9 +95,9 @@ pub const PtrWidth = enum { p32, p64 }; | ... | @@ -101,9 +95,9 @@ pub const PtrWidth = enum { p32, p64 }; |
| 101 | pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Plan9 { | 95 | pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Plan9 { |
| 102 | if (options.use_llvm) | 96 | if (options.use_llvm) |
| 103 | return error.LLVMBackendDoesNotSupportPlan9; | 97 | return error.LLVMBackendDoesNotSupportPlan9; |
| 104 | const ptr_width: PtrWidth = switch (options.target.cpu.arch.ptrBitWidth()) { | 98 | const sixtyfour_bit: bool = switch (options.target.cpu.arch.ptrBitWidth()) { |
| 105 | 0...32 => .p32, | 99 | 0...32 => false, |
| 106 | 33...64 => .p64, | 100 | 33...64 => true, |
| 107 | else => return error.UnsupportedP9Architecture, | 101 | else => return error.UnsupportedP9Architecture, |
| 108 | }; | 102 | }; |
| 109 | const self = try gpa.create(Plan9); | 103 | const self = try gpa.create(Plan9); |
| ... | @@ -114,7 +108,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Plan9 { | ... | @@ -114,7 +108,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Plan9 { |
| 114 | .allocator = gpa, | 108 | .allocator = gpa, |
| 115 | .file = null, | 109 | .file = null, |
| 116 | }, | 110 | }, |
| 117 | .ptr_width = ptr_width, | 111 | .sixtyfour_bit = sixtyfour_bit, |
| 118 | .bases = undefined, | 112 | .bases = undefined, |
| 119 | }; | 113 | }; |
| 120 | return self; | 114 | return self; |
| ... | @@ -150,7 +144,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -150,7 +144,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 150 | self.data_buf.items.len = 0; | 144 | self.data_buf.items.len = 0; |
| 151 | // ensure space to write the got later | 145 | // ensure space to write the got later |
| 152 | assert(self.got.items.len == self.decl_table.count()); | 146 | assert(self.got.items.len == self.decl_table.count()); |
| 153 | try self.data_buf.appendNTimes(self.base.allocator, 0x69, self.got.items.len * if (self.ptr_width == .p32) @as(u32, 4) else 8); | 147 | try self.data_buf.appendNTimes(self.base.allocator, 0x69, self.got.items.len * if (!self.sixtyfour_bit) @as(u32, 4) else 8); |
| 154 | // temporary buffer | 148 | // temporary buffer |
| 155 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 149 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 156 | defer code_buffer.deinit(); | 150 | defer code_buffer.deinit(); |
| ... | @@ -161,12 +155,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -161,12 +155,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 161 | | 155 | |
| 162 | log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name }); | 156 | log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name }); |
| 163 | decl.link.plan9 = if (is_fn) .{ | 157 | decl.link.plan9 = if (is_fn) .{ |
| 164 | .offset = self.getAddr(@intCast(u32, self.text_buf.items.len), .t), | 158 | .offset = self.getAddr(self.text_buf.items.len, .t), |
| 165 | .type = .t, | 159 | .type = .t, |
| 166 | .sym_index = decl.link.plan9.sym_index, | 160 | .sym_index = decl.link.plan9.sym_index, |
| 167 | .got_index = decl.link.plan9.got_index, | 161 | .got_index = decl.link.plan9.got_index, |
| 168 | } else .{ | 162 | } else .{ |
| 169 | .offset = self.getAddr(@intCast(u32, self.data_buf.items.len), .d), | 163 | .offset = self.getAddr(self.data_buf.items.len, .d), |
| 170 | .type = .d, | 164 | .type = .d, |
| 171 | .sym_index = decl.link.plan9.sym_index, | 165 | .sym_index = decl.link.plan9.sym_index, |
| 172 | .got_index = decl.link.plan9.got_index, | 166 | .got_index = decl.link.plan9.got_index, |
| ... | @@ -243,7 +237,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -243,7 +237,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 243 | } | 237 | } |
| 244 | | 238 | |
| 245 | // write the got | 239 | // write the got |
| 246 | if (self.ptr_width == .p32) { | 240 | if (!self.sixtyfour_bit) { |
| 247 | for (self.got.items) |p, i| { | 241 | for (self.got.items) |p, i| { |
| 248 | mem.writeInt(u32, self.data_buf.items[i * 4 ..][0..4], @intCast(u32, p), self.base.options.target.cpu.arch.endian()); | 242 | mem.writeInt(u32, self.data_buf.items[i * 4 ..][0..4], @intCast(u32, p), self.base.options.target.cpu.arch.endian()); |
| 249 | } | 243 | } |
| ... | @@ -253,15 +247,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -253,15 +247,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 253 | } | 247 | } |
| 254 | } | 248 | } |
| 255 | | 249 | |
| 256 | if (self.entry_decl == null) { | 250 | self.hdr.entry = @truncate(u32, self.entry_decl.?.link.plan9.offset.?); |
| 257 | @panic("TODO we didn't have _start"); | | |
| 258 | } | | |
| 259 | self.hdr.entry = self.entry_decl.?.link.plan9.offset.?; | | |
| 260 | | 251 | |
| 261 | // edata, end, etext | 252 | // edata, end, etext |
| 262 | self.syms.items[0].value = self.getAddr(0x0, .b); // what is this number | 253 | self.syms.items[0].value = self.getAddr(0x0, .b); |
| 263 | self.syms.items[1].value = self.getAddr(0x0, .b); // what is this number | 254 | self.syms.items[1].value = self.getAddr(0x0, .b); |
| 264 | self.syms.items[2].value = self.getAddr(@intCast(u32, self.text_buf.items.len), .t); | 255 | self.syms.items[2].value = self.getAddr(self.text_buf.items.len, .t); |
| 265 | | 256 | |
| 266 | var sym_buf = std.ArrayList(u8).init(self.base.allocator); | 257 | var sym_buf = std.ArrayList(u8).init(self.base.allocator); |
| 267 | defer sym_buf.deinit(); | 258 | defer sym_buf.deinit(); |
| ... | @@ -284,9 +275,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -284,9 +275,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 284 | var hdr_buf = self.hdr.toU8s(); | 275 | var hdr_buf = self.hdr.toU8s(); |
| 285 | const hdr_slice: []const u8 = &hdr_buf; | 276 | const hdr_slice: []const u8 = &hdr_buf; |
| 286 | // account for the fat header | 277 | // account for the fat header |
| 287 | const hdr_size: u8 = if (self.ptr_width == .p32) 32 else 40; | 278 | const hdr_size: u8 = if (!self.sixtyfour_bit) 32 else 40; |
| 288 | // write the fat header for debug info | 279 | // write the fat header for 64 bit entry points |
| 289 | if (self.ptr_width == .p64) { | 280 | if (self.sixtyfour_bit) { |
| 290 | mem.writeIntSliceBig(u64, hdr_buf[32..40], self.hdr.entry); | 281 | mem.writeIntSliceBig(u64, hdr_buf[32..40], self.hdr.entry); |
| 291 | } | 282 | } |
| 292 | // write it all! | 283 | // write it all! |
| ... | @@ -335,9 +326,6 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -335,9 +326,6 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 335 | const self = try createEmpty(allocator, options); | 326 | const self = try createEmpty(allocator, options); |
| 336 | errdefer self.base.destroy(); | 327 | errdefer self.base.destroy(); |
| 337 | | 328 | |
| 338 | if (std.builtin.mode == .Debug or std.builtin.mode == .ReleaseSafe) | | |
| 339 | self.hdr.entry = 0x0; | | |
| 340 | | | |
| 341 | self.bases = defaultBaseAddrs(options.target.cpu.arch); | 329 | self.bases = defaultBaseAddrs(options.target.cpu.arch); |
| 342 | | 330 | |
| 343 | // first 3 symbols in our table are edata, end, etext | 331 | // first 3 symbols in our table are edata, end, etext |
| ... | @@ -366,7 +354,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -366,7 +354,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 366 | pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { | 354 | pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 367 | const writer = buf.writer(); | 355 | const writer = buf.writer(); |
| 368 | for (self.syms.items) |sym| { | 356 | for (self.syms.items) |sym| { |
| 369 | if (self.ptr_width == .p32) { | 357 | if (!self.sixtyfour_bit) { |
| 370 | try writer.writeIntBig(u32, @intCast(u32, sym.value)); | 358 | try writer.writeIntBig(u32, @intCast(u32, sym.value)); |
| 371 | } else { | 359 | } else { |
| 372 | try writer.writeIntBig(u64, sym.value); | 360 | try writer.writeIntBig(u64, sym.value); |