authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2021-06-06 10:27:12-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-08 14:10:49-07:00
logc114474190fd6fe48b8c74becfb39ed82287d059
tree75b3493445f2bc409a1bc4a6a57af850afa32750
parent798162e5095aff130395ee542c0c0948f95180c9

plan9 linker: write symbol table

Also switch to iovecs because gotta go fast.

2 files changed, 109 insertions(+), 41 deletions(-)

src/link/Plan9.zig+76-18
......@@ -32,16 +32,18 @@ hdr: aout.ExecHdr = undefined,
3232
3333fn headerSize(self: Plan9) u32 {
3434 // 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;
3737}
3838pub const DeclBlock = struct {
3939 type: enum { text, data },
4040 // offset in the text or data sects
4141 offset: u32,
42 sym_index: usize,
4243 pub const empty = DeclBlock{
4344 .type = .text,
4445 .offset = 0,
46 .sym_index = 0,
4547 };
4648};
4749
......@@ -62,7 +64,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Plan9 {
6264 const ptr_width: PtrWidth = switch (options.target.cpu.arch.ptrBitWidth()) {
6365 0...32 => .p32,
6466 33...64 => .p64,
65 else => return error.UnsupportedELFArchitecture,
67 else => return error.UnsupportedP9Architecture,
6668 };
6769 const self = try gpa.create(Plan9);
6870 self.* = .{
......@@ -93,13 +95,14 @@ pub fn flush(self: *Plan9, comp: *Compilation) !void {
9395 return self.flushModule(comp);
9496}
9597pub 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();
97100
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;
102102
103 self.text_buf.items.len = 0;
104 self.data_buf.items.len = 0;
105 self.call_relocs.items.len = 0;
103106 // temporary buffer
104107 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
105108 defer code_buffer.deinit();
......@@ -111,10 +114,32 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void {
111114 decl.link.plan9 = if (is_fn) .{
112115 .offset = @intCast(u32, self.text_buf.items.len),
113116 .type = .text,
117 .sym_index = decl.link.plan9.sym_index,
114118 } else .{
115119 .offset = @intCast(u32, self.data_buf.items.len),
116120 .type = .data,
121 .sym_index = decl.link.plan9.sym_index,
117122 };
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 }
118143 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
119144 .ty = decl.ty,
120145 .val = decl.val,
......@@ -136,16 +161,35 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void {
136161 code_buffer.items.len = 0;
137162 }
138163 }
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);
142171 self.hdr.text = @intCast(u32, self.text_buf.items.len);
143172 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;
144175 self.hdr.pcsz = 0;
145176 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);
149193}
150194pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void {
151195 assert(self.decl_table.swapRemove(decl));
......@@ -173,14 +217,13 @@ pub fn updateDeclExports(
173217 self.hdr.entry = Plan9.default_base_addr + self.headerSize() + decl.link.plan9.offset;
174218 }
175219 if (exp.link.plan9) |i| {
176 const sym = &self.syms.items[i];
177 sym.* = .{
220 self.syms.items[i] = .{
178221 .value = decl.link.plan9.offset,
179222 .type = switch (decl.link.plan9.type) {
180223 .text => .T,
181224 .data => .D,
182225 },
183 .name = decl.name,
226 .name = exp.options.name,
184227 };
185228 } else {
186229 try self.syms.append(self.base.allocator, .{
......@@ -189,8 +232,9 @@ pub fn updateDeclExports(
189232 .text => .T,
190233 .data => .D,
191234 },
192 .name = decl.name,
235 .name = exp.options.name,
193236 });
237 exp.link.plan9 = self.syms.items.len - 1;
194238 }
195239 }
196240}
......@@ -226,3 +270,17 @@ pub fn addCallReloc(self: *Plan9, code: *std.ArrayList(u8), reloc: CallReloc) !v
226270 try self.call_relocs.append(self.base.allocator, reloc);
227271 try code.writer().writeIntBig(u64, 0xdeadbeef);
228272}
273
274pub 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}
src/link/plan9/a.out.zig+33-23
......@@ -22,7 +22,7 @@
2222// Idomatic translation of 9front a.out.h
2323const std = @import("std");
2424// all integers are in big-endian format (needs a byteswap)
25pub const ExecHdr = struct {
25pub const ExecHdr = extern struct {
2626 magic: u32,
2727 text: u32,
2828 data: u32,
......@@ -31,8 +31,18 @@ pub const ExecHdr = struct {
3131 entry: u32,
3232 spsz: u32,
3333 pcsz: u32,
34 pub fn size() u8 {
35 return 32;
34 comptime {
35 std.debug.assert(@sizeOf(@This()) == 32);
36 }
37 /// it is up to the caller to disgard the last 8 bytes if the header is not fat
38 pub fn toU8s(self: *@This()) [40]u8 {
39 var buf: [40]u8 = undefined;
40 var i: u8 = 0;
41 inline for (std.meta.fields(@This())) |f| {
42 std.mem.writeIntSliceBig(u32, buf[i .. i + 4], @field(self, f.name));
43 i += 4;
44 }
45 return buf;
3646 }
3747};
3848
......@@ -42,7 +52,7 @@ pub const ExecHdr = struct {
4252pub const Sym32 = struct {
4353 value: u32, // big endian in the file
4454 type: SymType,
45 name: [*:0]const u8,
55 name: []const u8,
4656};
4757// uchar value[8];
4858// char type;
......@@ -50,7 +60,7 @@ pub const Sym32 = struct {
5060pub const Sym64 = struct {
5161 value: u64, // big endian in the file
5262 type: SymType,
53 name: [*:0]const u8,
63 name: []const u8,
5464};
5565// The type field is one of the following characters with the
5666// high bit set:
......@@ -85,27 +95,27 @@ pub const SymType = enum(u8) {
8595 m = 0x80 | 'm',
8696};
8797
88pub const HDR_MAGIC = @import("std").meta.promoteIntLiteral(c_int, 0x00008000, .hexadecimal);
98pub const HDR_MAGIC = 0x00008000;
8999pub inline fn _MAGIC(f: anytype, b: anytype) @TypeOf(f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7))) {
90100 return f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7));
91101}
92pub const A_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 8)); // 68020
93pub const I_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 11)); // intel 386
94pub const J_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 12)); // intel 960 (retired)
95pub const K_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 13)); // sparc
96pub const V_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 16)); // mips 3000 BE
97pub const X_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 17)); // att dsp 3210 (retired)
98pub const M_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 18)); // mips 4000 BE
99pub const D_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 19)); // amd 29000 (retired)
100pub const E_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 20)); // arm
101pub const Q_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 21)); // powerpc
102pub const N_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 22)); // mips 4000 LE
103pub const L_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 23)); // dec alpha (retired)
104pub const P_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 24)); // mips 3000 LE
105pub const U_MAGIC = _MAGIC(@as(c_int, 0), @as(c_int, 25)); // sparc64
106pub const S_MAGIC = _MAGIC(HDR_MAGIC, @as(c_int, 26)); // amd64
107pub const T_MAGIC = _MAGIC(HDR_MAGIC, @as(c_int, 27)); // powerpc64
108pub const R_MAGIC = _MAGIC(HDR_MAGIC, @as(c_int, 28)); // arm64
102pub const A_MAGIC = _MAGIC(0, 8); // 68020
103pub const I_MAGIC = _MAGIC(0, 11); // intel 386
104pub const J_MAGIC = _MAGIC(0, 12); // intel 960 (retired)
105pub const K_MAGIC = _MAGIC(0, 13); // sparc
106pub const V_MAGIC = _MAGIC(0, 16); // mips 3000 BE
107pub const X_MAGIC = _MAGIC(0, 17); // att dsp 3210 (retired)
108pub const M_MAGIC = _MAGIC(0, 18); // mips 4000 BE
109pub const D_MAGIC = _MAGIC(0, 19); // amd 29000 (retired)
110pub const E_MAGIC = _MAGIC(0, 20); // arm
111pub const Q_MAGIC = _MAGIC(0, 21); // powerpc
112pub const N_MAGIC = _MAGIC(0, 22); // mips 4000 LE
113pub const L_MAGIC = _MAGIC(0, 23); // dec alpha (retired)
114pub const P_MAGIC = _MAGIC(0, 24); // mips 3000 LE
115pub const U_MAGIC = _MAGIC(0, 25); // sparc64
116pub const S_MAGIC = _MAGIC(HDR_MAGIC, 26); // amd64
117pub const T_MAGIC = _MAGIC(HDR_MAGIC, 27); // powerpc64
118pub const R_MAGIC = _MAGIC(HDR_MAGIC, 28); // arm64
109119
110120pub fn magicFromArch(arch: std.Target.Cpu.Arch) !u32 {
111121 return switch (arch) {