diff options
| author | Jacob G-W <jacoblevgw@gmail.com> | 2021-06-06 10:27:12 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-07-08 14:10:49 -0700 |
| commit | c114474190fd6fe48b8c74becfb39ed82287d059 (patch) | |
| tree | 75b3493445f2bc409a1bc4a6a57af850afa32750 /src | |
| parent | 798162e5095aff130395ee542c0c0948f95180c9 (diff) | |
| download | zig-c114474190fd6fe48b8c74becfb39ed82287d059.tar.gz zig-c114474190fd6fe48b8c74becfb39ed82287d059.zip | |
plan9 linker: write symbol table
Also switch to iovecs because gotta go fast.
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Plan9.zig | 94 | ||||
| -rw-r--r-- | src/link/plan9/a.out.zig | 56 |
2 files changed, 109 insertions, 41 deletions
diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index d179836fa6..35c0982699 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -32,16 +32,18 @@ hdr: aout.ExecHdr = undefined, fn headerSize(self: Plan9) u32 { // fat header (currently unused) - const fat: u4 = if (self.ptr_width == .p64) 8 else 0; - return aout.ExecHdr.size() + fat; + const fat: u8 = if (self.ptr_width == .p64) 8 else 0; + return @sizeOf(aout.ExecHdr) + fat; } pub const DeclBlock = struct { type: enum { text, data }, // offset in the text or data sects offset: u32, + sym_index: usize, pub const empty = DeclBlock{ .type = .text, .offset = 0, + .sym_index = 0, }; }; @@ -62,7 +64,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Plan9 { const ptr_width: PtrWidth = switch (options.target.cpu.arch.ptrBitWidth()) { 0...32 => .p32, 33...64 => .p64, - else => return error.UnsupportedELFArchitecture, + else => return error.UnsupportedP9Architecture, }; const self = try gpa.create(Plan9); self.* = .{ @@ -93,13 +95,14 @@ pub fn flush(self: *Plan9, comp: *Compilation) !void { return self.flushModule(comp); } pub fn flushModule(self: *Plan9, comp: *Compilation) !void { - const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; + const tracy = trace(@src()); + defer tracy.end(); - // generate the header - self.hdr.magic = try aout.magicFromArch(self.base.options.target.cpu.arch); - const file = self.base.file.?; - try file.seekTo(self.headerSize()); + const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; + self.text_buf.items.len = 0; + self.data_buf.items.len = 0; + self.call_relocs.items.len = 0; // temporary buffer var code_buffer = std.ArrayList(u8).init(self.base.allocator); defer code_buffer.deinit(); @@ -111,10 +114,32 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { decl.link.plan9 = if (is_fn) .{ .offset = @intCast(u32, self.text_buf.items.len), .type = .text, + .sym_index = decl.link.plan9.sym_index, } else .{ .offset = @intCast(u32, self.data_buf.items.len), .type = .data, + .sym_index = decl.link.plan9.sym_index, }; + if (decl.link.plan9.sym_index == 0) { + try self.syms.append(self.base.allocator, .{ + .value = decl.link.plan9.offset, + .type = switch (decl.link.plan9.type) { + .text => .t, + .data => .d, + }, + .name = mem.span(decl.name), + }); + decl.link.plan9.sym_index = self.syms.items.len - 1; + } else { + self.syms.items[decl.link.plan9.sym_index] = .{ + .value = decl.link.plan9.offset, + .type = switch (decl.link.plan9.type) { + .text => .t, + .data => .d, + }, + .name = mem.span(decl.name), + }; + } const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ .ty = decl.ty, .val = decl.val, @@ -136,16 +161,35 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { code_buffer.items.len = 0; } } - try file.writeAll(self.text_buf.items); - try file.writeAll(self.data_buf.items); - try file.seekTo(0); + + var sym_buf = std.ArrayList(u8).init(self.base.allocator); + defer sym_buf.deinit(); + try self.writeSyms(&sym_buf); + + // generate the header + self.hdr.magic = try aout.magicFromArch(self.base.options.target.cpu.arch); self.hdr.text = @intCast(u32, self.text_buf.items.len); self.hdr.data = @intCast(u32, self.data_buf.items.len); + self.hdr.syms = @intCast(u32, sym_buf.items.len); + self.hdr.bss = 0; self.hdr.pcsz = 0; self.hdr.spsz = 0; - inline for (std.meta.fields(aout.ExecHdr)) |f| { - try file.writer().writeIntBig(f.field_type, @field(self.hdr, f.name)); - } + + const file = self.base.file.?; + + const 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 it all! + var vectors: [4]std.os.iovec_const = .{ + .{ .iov_base = hdr_slice.ptr, .iov_len = hdr_size }, + .{ .iov_base = self.text_buf.items.ptr, .iov_len = self.text_buf.items.len }, + .{ .iov_base = self.data_buf.items.ptr, .iov_len = self.data_buf.items.len }, + .{ .iov_base = sym_buf.items.ptr, .iov_len = sym_buf.items.len }, + // TODO spsz, pcsz + }; + try file.pwritevAll(&vectors, 0); } pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { assert(self.decl_table.swapRemove(decl)); @@ -173,14 +217,13 @@ pub fn updateDeclExports( self.hdr.entry = Plan9.default_base_addr + self.headerSize() + decl.link.plan9.offset; } if (exp.link.plan9) |i| { - const sym = &self.syms.items[i]; - sym.* = .{ + self.syms.items[i] = .{ .value = decl.link.plan9.offset, .type = switch (decl.link.plan9.type) { .text => .T, .data => .D, }, - .name = decl.name, + .name = exp.options.name, }; } else { try self.syms.append(self.base.allocator, .{ @@ -189,8 +232,9 @@ pub fn updateDeclExports( .text => .T, .data => .D, }, - .name = decl.name, + .name = exp.options.name, }); + exp.link.plan9 = self.syms.items.len - 1; } } } @@ -226,3 +270,17 @@ pub fn addCallReloc(self: *Plan9, code: *std.ArrayList(u8), reloc: CallReloc) !v try self.call_relocs.append(self.base.allocator, reloc); try code.writer().writeIntBig(u64, 0xdeadbeef); } + +pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { + const writer = buf.writer(); + for (self.syms.items) |sym| { + if (self.ptr_width == .p32) { + try writer.writeIntBig(u32, @intCast(u32, sym.value)); + } else { + try writer.writeIntBig(u64, sym.value); + } + try writer.writeByte(@enumToInt(sym.type)); + try writer.writeAll(std.mem.span(sym.name)); + try writer.writeByte(0); + } +} diff --git a/src/link/plan9/a.out.zig b/src/link/plan9/a.out.zig index 724bd4fa25..3c41862593 100644 --- a/src/link/plan9/a.out.zig +++ b/src/link/plan9/a.out.zig @@ -22,7 +22,7 @@ // Idomatic translation of 9front a.out.h const std = @import("std"); // all integers are in big-endian format (needs a byteswap) -pub const ExecHdr = struct { +pub const ExecHdr = extern struct { magic: u32, text: u32, data: u32, @@ -31,8 +31,18 @@ pub const ExecHdr = struct { entry: u32, spsz: u32, pcsz: u32, - pub fn size() u8 { - return 32; + comptime { + std.debug.assert(@sizeOf(@This()) == 32); + } + /// it is up to the caller to disgard the last 8 bytes if the header is not fat + pub fn toU8s(self: *@This()) [40]u8 { + var buf: [40]u8 = undefined; + var i: u8 = 0; + inline for (std.meta.fields(@This())) |f| { + std.mem.writeIntSliceBig(u32, buf[i .. i + 4], @field(self, f.name)); + i += 4; + } + return buf; } }; @@ -42,7 +52,7 @@ pub const ExecHdr = struct { pub const Sym32 = struct { value: u32, // big endian in the file type: SymType, - name: [*:0]const u8, + name: []const u8, }; // uchar value[8]; // char type; @@ -50,7 +60,7 @@ pub const Sym32 = struct { pub const Sym64 = struct { value: u64, // big endian in the file type: SymType, - name: [*:0]const u8, + name: []const u8, }; // The type field is one of the following characters with the // high bit set: @@ -85,27 +95,27 @@ pub const SymType = enum(u8) { m = 0x80 | 'm', }; -pub const HDR_MAGIC = @import("std").meta.promoteIntLiteral(c_int, 0x00008000, .hexadecimal); +pub const HDR_MAGIC = 0x00008000; pub inline fn _MAGIC(f: anytype, b: anytype) @TypeOf(f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7))) { return f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7)); } -pub const A_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 8)); // 68020 -pub const I_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 11)); // intel 386 -pub const J_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 12)); // intel 960 (retired) -pub const K_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 13)); // sparc -pub const V_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 16)); // mips 3000 BE -pub const X_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 17)); // att dsp 3210 (retired) -pub const M_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 18)); // mips 4000 BE -pub const D_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 19)); // amd 29000 (retired) -pub const E_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 20)); // arm -pub const Q_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 21)); // powerpc -pub const N_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 22)); // mips 4000 LE -pub const L_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 23)); // dec alpha (retired) -pub const P_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 24)); // mips 3000 LE -pub const U_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 25)); // sparc64 -pub const S_MAGIC = _MAGIC(HDR_MAGIC, @as(c_int, 26)); // amd64 -pub const T_MAGIC = _MAGIC(HDR_MAGIC, @as(c_int, 27)); // powerpc64 -pub const R_MAGIC = _MAGIC(HDR_MAGIC, @as(c_int, 28)); // arm64 +pub const A_MAGIC = _MAGIC(0, 8); // 68020 +pub const I_MAGIC = _MAGIC(0, 11); // intel 386 +pub const J_MAGIC = _MAGIC(0, 12); // intel 960 (retired) +pub const K_MAGIC = _MAGIC(0, 13); // sparc +pub const V_MAGIC = _MAGIC(0, 16); // mips 3000 BE +pub const X_MAGIC = _MAGIC(0, 17); // att dsp 3210 (retired) +pub const M_MAGIC = _MAGIC(0, 18); // mips 4000 BE +pub const D_MAGIC = _MAGIC(0, 19); // amd 29000 (retired) +pub const E_MAGIC = _MAGIC(0, 20); // arm +pub const Q_MAGIC = _MAGIC(0, 21); // powerpc +pub const N_MAGIC = _MAGIC(0, 22); // mips 4000 LE +pub const L_MAGIC = _MAGIC(0, 23); // dec alpha (retired) +pub const P_MAGIC = _MAGIC(0, 24); // mips 3000 LE +pub const U_MAGIC = _MAGIC(0, 25); // sparc64 +pub const S_MAGIC = _MAGIC(HDR_MAGIC, 26); // amd64 +pub const T_MAGIC = _MAGIC(HDR_MAGIC, 27); // powerpc64 +pub const R_MAGIC = _MAGIC(HDR_MAGIC, 28); // arm64 pub fn magicFromArch(arch: std.Target.Cpu.Arch) !u32 { return switch (arch) { |
