| ... | ... | @@ -32,16 +32,18 @@ hdr: aout.ExecHdr = undefined, |
| 32 | 32 | |
| 33 | 33 | fn headerSize(self: Plan9) u32 { |
| 34 | 34 | // fat header (currently unused) |
| 35 | | const fat: u4 = if (self.ptr_width == .p64) 8 else 0; |
| 36 | | return aout.ExecHdr.size() + fat; |
| 35 | const fat: u8 = if (self.ptr_width == .p64) 8 else 0; |
| 36 | return @sizeOf(aout.ExecHdr) + fat; |
| 37 | 37 | } |
| 38 | 38 | pub const DeclBlock = struct { |
| 39 | 39 | type: enum { text, data }, |
| 40 | 40 | // offset in the text or data sects |
| 41 | 41 | offset: u32, |
| 42 | sym_index: usize, |
| 42 | 43 | pub const empty = DeclBlock{ |
| 43 | 44 | .type = .text, |
| 44 | 45 | .offset = 0, |
| 46 | .sym_index = 0, |
| 45 | 47 | }; |
| 46 | 48 | }; |
| 47 | 49 | |
| ... | ... | @@ -62,7 +64,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Plan9 { |
| 62 | 64 | const ptr_width: PtrWidth = switch (options.target.cpu.arch.ptrBitWidth()) { |
| 63 | 65 | 0...32 => .p32, |
| 64 | 66 | 33...64 => .p64, |
| 65 | | else => return error.UnsupportedELFArchitecture, |
| 67 | else => return error.UnsupportedP9Architecture, |
| 66 | 68 | }; |
| 67 | 69 | const self = try gpa.create(Plan9); |
| 68 | 70 | self.* = .{ |
| ... | ... | @@ -93,13 +95,14 @@ pub fn flush(self: *Plan9, comp: *Compilation) !void { |
| 93 | 95 | return self.flushModule(comp); |
| 94 | 96 | } |
| 95 | 97 | pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 96 | | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 98 | const tracy = trace(@src()); |
| 99 | defer tracy.end(); |
| 97 | 100 | |
| 98 | | // generate the header |
| 99 | | self.hdr.magic = try aout.magicFromArch(self.base.options.target.cpu.arch); |
| 100 | | const file = self.base.file.?; |
| 101 | | try file.seekTo(self.headerSize()); |
| 101 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 102 | 102 | |
| 103 | self.text_buf.items.len = 0; |
| 104 | self.data_buf.items.len = 0; |
| 105 | self.call_relocs.items.len = 0; |
| 103 | 106 | // temporary buffer |
| 104 | 107 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 105 | 108 | defer code_buffer.deinit(); |
| ... | ... | @@ -111,10 +114,32 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 111 | 114 | decl.link.plan9 = if (is_fn) .{ |
| 112 | 115 | .offset = @intCast(u32, self.text_buf.items.len), |
| 113 | 116 | .type = .text, |
| 117 | .sym_index = decl.link.plan9.sym_index, |
| 114 | 118 | } else .{ |
| 115 | 119 | .offset = @intCast(u32, self.data_buf.items.len), |
| 116 | 120 | .type = .data, |
| 121 | .sym_index = decl.link.plan9.sym_index, |
| 117 | 122 | }; |
| 123 | if (decl.link.plan9.sym_index == 0) { |
| 124 | try self.syms.append(self.base.allocator, .{ |
| 125 | .value = decl.link.plan9.offset, |
| 126 | .type = switch (decl.link.plan9.type) { |
| 127 | .text => .t, |
| 128 | .data => .d, |
| 129 | }, |
| 130 | .name = mem.span(decl.name), |
| 131 | }); |
| 132 | decl.link.plan9.sym_index = self.syms.items.len - 1; |
| 133 | } else { |
| 134 | self.syms.items[decl.link.plan9.sym_index] = .{ |
| 135 | .value = decl.link.plan9.offset, |
| 136 | .type = switch (decl.link.plan9.type) { |
| 137 | .text => .t, |
| 138 | .data => .d, |
| 139 | }, |
| 140 | .name = mem.span(decl.name), |
| 141 | }; |
| 142 | } |
| 118 | 143 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ |
| 119 | 144 | .ty = decl.ty, |
| 120 | 145 | .val = decl.val, |
| ... | ... | @@ -136,16 +161,35 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 136 | 161 | code_buffer.items.len = 0; |
| 137 | 162 | } |
| 138 | 163 | } |
| 139 | | try file.writeAll(self.text_buf.items); |
| 140 | | try file.writeAll(self.data_buf.items); |
| 141 | | try file.seekTo(0); |
| 164 | |
| 165 | var sym_buf = std.ArrayList(u8).init(self.base.allocator); |
| 166 | defer sym_buf.deinit(); |
| 167 | try self.writeSyms(&sym_buf); |
| 168 | |
| 169 | // generate the header |
| 170 | self.hdr.magic = try aout.magicFromArch(self.base.options.target.cpu.arch); |
| 142 | 171 | self.hdr.text = @intCast(u32, self.text_buf.items.len); |
| 143 | 172 | self.hdr.data = @intCast(u32, self.data_buf.items.len); |
| 173 | self.hdr.syms = @intCast(u32, sym_buf.items.len); |
| 174 | self.hdr.bss = 0; |
| 144 | 175 | self.hdr.pcsz = 0; |
| 145 | 176 | self.hdr.spsz = 0; |
| 146 | | inline for (std.meta.fields(aout.ExecHdr)) |f| { |
| 147 | | try file.writer().writeIntBig(f.field_type, @field(self.hdr, f.name)); |
| 148 | | } |
| 177 | |
| 178 | const file = self.base.file.?; |
| 179 | |
| 180 | const hdr_buf = self.hdr.toU8s(); |
| 181 | const hdr_slice: []const u8 = &hdr_buf; |
| 182 | // account for the fat header |
| 183 | const hdr_size: u8 = if (self.ptr_width == .p32) 32 else 40; |
| 184 | // write it all! |
| 185 | var vectors: [4]std.os.iovec_const = .{ |
| 186 | .{ .iov_base = hdr_slice.ptr, .iov_len = hdr_size }, |
| 187 | .{ .iov_base = self.text_buf.items.ptr, .iov_len = self.text_buf.items.len }, |
| 188 | .{ .iov_base = self.data_buf.items.ptr, .iov_len = self.data_buf.items.len }, |
| 189 | .{ .iov_base = sym_buf.items.ptr, .iov_len = sym_buf.items.len }, |
| 190 | // TODO spsz, pcsz |
| 191 | }; |
| 192 | try file.pwritevAll(&vectors, 0); |
| 149 | 193 | } |
| 150 | 194 | pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { |
| 151 | 195 | assert(self.decl_table.swapRemove(decl)); |
| ... | ... | @@ -173,14 +217,13 @@ pub fn updateDeclExports( |
| 173 | 217 | self.hdr.entry = Plan9.default_base_addr + self.headerSize() + decl.link.plan9.offset; |
| 174 | 218 | } |
| 175 | 219 | if (exp.link.plan9) |i| { |
| 176 | | const sym = &self.syms.items[i]; |
| 177 | | sym.* = .{ |
| 220 | self.syms.items[i] = .{ |
| 178 | 221 | .value = decl.link.plan9.offset, |
| 179 | 222 | .type = switch (decl.link.plan9.type) { |
| 180 | 223 | .text => .T, |
| 181 | 224 | .data => .D, |
| 182 | 225 | }, |
| 183 | | .name = decl.name, |
| 226 | .name = exp.options.name, |
| 184 | 227 | }; |
| 185 | 228 | } else { |
| 186 | 229 | try self.syms.append(self.base.allocator, .{ |
| ... | ... | @@ -189,8 +232,9 @@ pub fn updateDeclExports( |
| 189 | 232 | .text => .T, |
| 190 | 233 | .data => .D, |
| 191 | 234 | }, |
| 192 | | .name = decl.name, |
| 235 | .name = exp.options.name, |
| 193 | 236 | }); |
| 237 | exp.link.plan9 = self.syms.items.len - 1; |
| 194 | 238 | } |
| 195 | 239 | } |
| 196 | 240 | } |
| ... | ... | @@ -226,3 +270,17 @@ pub fn addCallReloc(self: *Plan9, code: *std.ArrayList(u8), reloc: CallReloc) !v |
| 226 | 270 | try self.call_relocs.append(self.base.allocator, reloc); |
| 227 | 271 | try code.writer().writeIntBig(u64, 0xdeadbeef); |
| 228 | 272 | } |
| 273 | |
| 274 | pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 275 | const writer = buf.writer(); |
| 276 | for (self.syms.items) |sym| { |
| 277 | if (self.ptr_width == .p32) { |
| 278 | try writer.writeIntBig(u32, @intCast(u32, sym.value)); |
| 279 | } else { |
| 280 | try writer.writeIntBig(u64, sym.value); |
| 281 | } |
| 282 | try writer.writeByte(@enumToInt(sym.type)); |
| 283 | try writer.writeAll(std.mem.span(sym.name)); |
| 284 | try writer.writeByte(0); |
| 285 | } |
| 286 | } |