Commit 72bb6bb143

Jacob G-W <jacoblevgw@gmail.com>
2021-06-12 22:51:51
plan9 linker: produce an object file that can actually work!!!
1 parent 3e59c15
Changed files (3)
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"
-            );
-        },
-        .arm => {
-            asm volatile ("svc #0"
-                :
-                : [number] "{r7}" (1),
-                  [arg1] "{r0}" (code)
-                : "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"),
         },
-        .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"),
     }
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;
 }
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,