From 72bb6bb1430f0b3b32f0cb5e52054293a59abca6 Mon Sep 17 00:00:00 2001 From: Jacob G-W Date: Sat, 12 Jun 2021 16:51:51 -0400 Subject: [PATCH] plan9 linker: produce an object file that can actually work!!! --- lib/std/start.zig | 59 +++++++++++++++++++++++++++------------------ src/Compilation.zig | 3 +++ src/link/Plan9.zig | 45 ++++++++++++++++++++++++++++------ 3 files changed, 76 insertions(+), 31 deletions(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index 0a6c0320d6..608b3997f1 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -95,30 +95,43 @@ fn _start2() callconv(.Naked) noreturn { } fn exit2(code: usize) noreturn { - switch (builtin.stage2_arch) { - .x86_64 => { - asm volatile ("syscall" - : - : [number] "{rax}" (231), - [arg1] "{rdi}" (code) - : "rcx", "r11", "memory" - ); + switch (builtin.stage2_os) { + .linux => switch (builtin.stage2_arch) { + .x86_64 => { + asm volatile ("syscall" + : + : [number] "{rax}" (231), + [arg1] "{rdi}" (code) + : "rcx", "r11", "memory" + ); + }, + .arm => { + asm volatile ("svc #0" + : + : [number] "{r7}" (1), + [arg1] "{r0}" (code) + : "memory" + ); + }, + .aarch64 => { + asm volatile ("svc #0" + : + : [number] "{x8}" (93), + [arg1] "{x0}" (code) + : "memory", "cc" + ); + }, + else => @compileError("TODO"), }, - .arm => { - asm volatile ("svc #0" - : - : [number] "{r7}" (1), - [arg1] "{r0}" (code) - : "memory" - ); - }, - .aarch64 => { - asm volatile ("svc #0" - : - : [number] "{x8}" (93), - [arg1] "{x0}" (code) - : "memory", "cc" - ); + .plan9 => switch (builtin.stage2_arch) { + .x86_64 => { + asm volatile ("syscall" + : + : [number] "{rbp}" (8) + : "rcx", "r11", "memory" + ); + }, + else => @compileError("TODO"), }, else => @compileError("TODO"), } diff --git a/src/Compilation.zig b/src/Compilation.zig index 1cf4151c62..58425197c1 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3556,6 +3556,8 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc \\pub const zig_is_stage2 = {}; \\/// Temporary until self-hosted supports the `cpu.arch` value. \\pub const stage2_arch: std.Target.Cpu.Arch = .{}; + \\/// Temporary until self-hosted supports the `os.tag` value. + \\pub const stage2_os: std.Target.Os.Tag = .{}; \\ \\pub const output_mode = std.builtin.OutputMode.{}; \\pub const link_mode = std.builtin.LinkMode.{}; @@ -3571,6 +3573,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc build_options.version, !use_stage1, std.zig.fmtId(@tagName(target.cpu.arch)), + std.zig.fmtId(@tagName(target.os.tag)), std.zig.fmtId(@tagName(comp.bin_file.options.output_mode)), std.zig.fmtId(@tagName(comp.bin_file.options.link_mode)), comp.bin_file.options.is_test, diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index 5532e056fc..ffd88ddc77 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -48,8 +48,8 @@ pub const DeclBlock = struct { }; }; -// TODO change base addr based on target (right now it just works on amd64) -const default_base_addr = 0x00200000; +// TODO change base addr based on target (and section?) (right now it just works on amd64) +const default_base_addr = 0x00200028; pub const CallReloc = struct { caller: *Module.Decl, @@ -157,11 +157,13 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { return; }, }; - if (is_fn) - try self.text_buf.appendSlice(self.base.allocator, code) - else + if (is_fn) { + try self.text_buf.appendSlice(self.base.allocator, code); + try code_buffer.resize(0); + } else { try self.data_buf.appendSlice(self.base.allocator, code); - code_buffer.items.len = 0; + try code_buffer.resize(0); + } } } @@ -176,7 +178,6 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { const off = reloc.offset_in_caller + l.offset; std.mem.writeInt(u32, self.text_buf.items[off - 4 ..][0..4], callee_offset, endian); } else { - // what we are writing const callee_offset = reloc.callee.link.plan9.offset + default_base_addr; // TODO this is different if its data const off = reloc.offset_in_caller + l.offset; std.mem.writeInt(u64, self.text_buf.items[off - 8 ..][0..8], callee_offset, endian); @@ -184,6 +185,11 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { } } + // edata, end, etext + self.syms.items[0].value = 0x200000; // TODO make this number other place, and what is it? + self.syms.items[1].value = 0x200000; // TODO make this number other place, and what is it? + self.syms.items[2].value = self.text_buf.items.len; + var sym_buf = std.ArrayList(u8).init(self.base.allocator); defer sym_buf.deinit(); try self.writeSyms(&sym_buf); @@ -202,10 +208,14 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { const file = self.base.file.?; - const hdr_buf = self.hdr.toU8s(); + var hdr_buf = self.hdr.toU8s(); const hdr_slice: []const u8 = &hdr_buf; // account for the fat header const hdr_size: u8 = if (self.ptr_width == .p32) 32 else 40; + // write the fat header for debug info + if (self.ptr_width == .p64) { + mem.writeIntSliceBig(u64, hdr_buf[32..40], self.hdr.entry); + } // write it all! var vectors: [4]std.os.iovec_const = .{ .{ .iov_base = hdr_slice.ptr, .iov_len = hdr_size }, @@ -290,6 +300,25 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio if (std.builtin.mode == .Debug or std.builtin.mode == .ReleaseSafe) self.hdr.entry = 0x0; + // first 3 symbols in our table are edata, end, etext + try self.syms.appendSlice(self.base.allocator, &.{ + .{ + .value = 0xcafebabe, + .type = .B, + .name = "edata", + }, + .{ + .value = 0xcafebabe, + .type = .B, + .name = "end", + }, + .{ + .value = 0xcafebabe, + .type = .T, + .name = "etext", + }, + }); + self.base.file = file; return self; }