authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2021-06-12 16:51:51-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-08 14:10:49-07:00
log72bb6bb1430f0b3b32f0cb5e52054293a59abca6
tree2a9fd4c878ef85491f09ae5290d75e2fe76c2197
parent3e59c1502556493b29171c2d22447dd70670ca02

plan9 linker: produce an object file that can actually work!!!


3 files changed, 76 insertions(+), 31 deletions(-)

lib/std/start.zig+36-23
......@@ -95,30 +95,43 @@ fn _start2() callconv(.Naked) noreturn {
9595}
9696
9797fn exit2(code: usize) noreturn {
98 switch (builtin.stage2_arch) {
99 .x86_64 => {
100 asm volatile ("syscall"
101 :
102 : [number] "{rax}" (231),
103 [arg1] "{rdi}" (code)
104 : "rcx", "r11", "memory"
105 );
106 },
107 .arm => {
108 asm volatile ("svc #0"
109 :
110 : [number] "{r7}" (1),
111 [arg1] "{r0}" (code)
112 : "memory"
113 );
98 switch (builtin.stage2_os) {
99 .linux => switch (builtin.stage2_arch) {
100 .x86_64 => {
101 asm volatile ("syscall"
102 :
103 : [number] "{rax}" (231),
104 [arg1] "{rdi}" (code)
105 : "rcx", "r11", "memory"
106 );
107 },
108 .arm => {
109 asm volatile ("svc #0"
110 :
111 : [number] "{r7}" (1),
112 [arg1] "{r0}" (code)
113 : "memory"
114 );
115 },
116 .aarch64 => {
117 asm volatile ("svc #0"
118 :
119 : [number] "{x8}" (93),
120 [arg1] "{x0}" (code)
121 : "memory", "cc"
122 );
123 },
124 else => @compileError("TODO"),
114125 },
115 .aarch64 => {
116 asm volatile ("svc #0"
117 :
118 : [number] "{x8}" (93),
119 [arg1] "{x0}" (code)
120 : "memory", "cc"
121 );
126 .plan9 => switch (builtin.stage2_arch) {
127 .x86_64 => {
128 asm volatile ("syscall"
129 :
130 : [number] "{rbp}" (8)
131 : "rcx", "r11", "memory"
132 );
133 },
134 else => @compileError("TODO"),
122135 },
123136 else => @compileError("TODO"),
124137 }
src/Compilation.zig+3
......@@ -3556,6 +3556,8 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc
35563556 \\pub const zig_is_stage2 = {};
35573557 \\/// Temporary until self-hosted supports the `cpu.arch` value.
35583558 \\pub const stage2_arch: std.Target.Cpu.Arch = .{};
3559 \\/// Temporary until self-hosted supports the `os.tag` value.
3560 \\pub const stage2_os: std.Target.Os.Tag = .{};
35593561 \\
35603562 \\pub const output_mode = std.builtin.OutputMode.{};
35613563 \\pub const link_mode = std.builtin.LinkMode.{};
......@@ -3571,6 +3573,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Alloc
35713573 build_options.version,
35723574 !use_stage1,
35733575 std.zig.fmtId(@tagName(target.cpu.arch)),
3576 std.zig.fmtId(@tagName(target.os.tag)),
35743577 std.zig.fmtId(@tagName(comp.bin_file.options.output_mode)),
35753578 std.zig.fmtId(@tagName(comp.bin_file.options.link_mode)),
35763579 comp.bin_file.options.is_test,
src/link/Plan9.zig+37-8
......@@ -48,8 +48,8 @@ pub const DeclBlock = struct {
4848 };
4949};
5050
51// TODO change base addr based on target (right now it just works on amd64)
52const default_base_addr = 0x00200000;
51// TODO change base addr based on target (and section?) (right now it just works on amd64)
52const default_base_addr = 0x00200028;
5353
5454pub const CallReloc = struct {
5555 caller: *Module.Decl,
......@@ -157,11 +157,13 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void {
157157 return;
158158 },
159159 };
160 if (is_fn)
161 try self.text_buf.appendSlice(self.base.allocator, code)
162 else
160 if (is_fn) {
161 try self.text_buf.appendSlice(self.base.allocator, code);
162 try code_buffer.resize(0);
163 } else {
163164 try self.data_buf.appendSlice(self.base.allocator, code);
164 code_buffer.items.len = 0;
165 try code_buffer.resize(0);
166 }
165167 }
166168 }
167169
......@@ -176,7 +178,6 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void {
176178 const off = reloc.offset_in_caller + l.offset;
177179 std.mem.writeInt(u32, self.text_buf.items[off - 4 ..][0..4], callee_offset, endian);
178180 } else {
179 // what we are writing
180181 const callee_offset = reloc.callee.link.plan9.offset + default_base_addr; // TODO this is different if its data
181182 const off = reloc.offset_in_caller + l.offset;
182183 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 {
184185 }
185186 }
186187
188 // edata, end, etext
189 self.syms.items[0].value = 0x200000; // TODO make this number other place, and what is it?
190 self.syms.items[1].value = 0x200000; // TODO make this number other place, and what is it?
191 self.syms.items[2].value = self.text_buf.items.len;
192
187193 var sym_buf = std.ArrayList(u8).init(self.base.allocator);
188194 defer sym_buf.deinit();
189195 try self.writeSyms(&sym_buf);
......@@ -202,10 +208,14 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void {
202208
203209 const file = self.base.file.?;
204210
205 const hdr_buf = self.hdr.toU8s();
211 var hdr_buf = self.hdr.toU8s();
206212 const hdr_slice: []const u8 = &hdr_buf;
207213 // account for the fat header
208214 const hdr_size: u8 = if (self.ptr_width == .p32) 32 else 40;
215 // write the fat header for debug info
216 if (self.ptr_width == .p64) {
217 mem.writeIntSliceBig(u64, hdr_buf[32..40], self.hdr.entry);
218 }
209219 // write it all!
210220 var vectors: [4]std.os.iovec_const = .{
211221 .{ .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
290300 if (std.builtin.mode == .Debug or std.builtin.mode == .ReleaseSafe)
291301 self.hdr.entry = 0x0;
292302
303 // first 3 symbols in our table are edata, end, etext
304 try self.syms.appendSlice(self.base.allocator, &.{
305 .{
306 .value = 0xcafebabe,
307 .type = .B,
308 .name = "edata",
309 },
310 .{
311 .value = 0xcafebabe,
312 .type = .B,
313 .name = "end",
314 },
315 .{
316 .value = 0xcafebabe,
317 .type = .T,
318 .name = "etext",
319 },
320 });
321
293322 self.base.file = file;
294323 return self;
295324}