| ... | @@ -39,11 +39,12 @@ pub const DeclBlock = struct { | ... | @@ -39,11 +39,12 @@ pub const DeclBlock = struct { |
| 39 | type: enum { text, data }, | 39 | type: enum { text, data }, |
| 40 | // offset in the text or data sects | 40 | // offset in the text or data sects |
| 41 | offset: u32, | 41 | offset: u32, |
| 42 | sym_index: usize, | 42 | // offset into syms |
| | 43 | sym_index: ?usize, |
| 43 | pub const empty = DeclBlock{ | 44 | pub const empty = DeclBlock{ |
| 44 | .type = .text, | 45 | .type = .text, |
| 45 | .offset = 0, | 46 | .offset = 0, |
| 46 | .sym_index = 0, | 47 | .sym_index = null, |
| 47 | }; | 48 | }; |
| 48 | }; | 49 | }; |
| 49 | | 50 | |
| ... | @@ -98,6 +99,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -98,6 +99,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 98 | const tracy = trace(@src()); | 99 | const tracy = trace(@src()); |
| 99 | defer tracy.end(); | 100 | defer tracy.end(); |
| 100 | | 101 | |
| | 102 | defer assert(self.hdr.entry != 0x0); |
| | 103 | |
| 101 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; | 104 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 102 | | 105 | |
| 103 | self.text_buf.items.len = 0; | 106 | self.text_buf.items.len = 0; |
| ... | @@ -120,7 +123,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -120,7 +123,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 120 | .type = .data, | 123 | .type = .data, |
| 121 | .sym_index = decl.link.plan9.sym_index, | 124 | .sym_index = decl.link.plan9.sym_index, |
| 122 | }; | 125 | }; |
| 123 | if (decl.link.plan9.sym_index == 0) { | 126 | if (decl.link.plan9.sym_index == null) { |
| 124 | try self.syms.append(self.base.allocator, .{ | 127 | try self.syms.append(self.base.allocator, .{ |
| 125 | .value = decl.link.plan9.offset, | 128 | .value = decl.link.plan9.offset, |
| 126 | .type = switch (decl.link.plan9.type) { | 129 | .type = switch (decl.link.plan9.type) { |
| ... | @@ -131,7 +134,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -131,7 +134,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 131 | }); | 134 | }); |
| 132 | decl.link.plan9.sym_index = self.syms.items.len - 1; | 135 | decl.link.plan9.sym_index = self.syms.items.len - 1; |
| 133 | } else { | 136 | } else { |
| 134 | self.syms.items[decl.link.plan9.sym_index] = .{ | 137 | self.syms.items[decl.link.plan9.sym_index.?] = .{ |
| 135 | .value = decl.link.plan9.offset, | 138 | .value = decl.link.plan9.offset, |
| 136 | .type = switch (decl.link.plan9.type) { | 139 | .type = switch (decl.link.plan9.type) { |
| 137 | .text => .t, | 140 | .text => .t, |
| ... | @@ -162,18 +165,40 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -162,18 +165,40 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 162 | } | 165 | } |
| 163 | } | 166 | } |
| 164 | | 167 | |
| | 168 | // Do relocations. |
| | 169 | { |
| | 170 | for (self.call_relocs.items) |reloc| { |
| | 171 | const l: DeclBlock = reloc.caller.link.plan9; |
| | 172 | assert(l.sym_index != null); // we didn't process it already |
| | 173 | const endian = self.base.options.target.cpu.arch.endian(); |
| | 174 | if (self.ptr_width == .p32) { |
| | 175 | const callee_offset = @truncate(u32, reloc.callee.link.plan9.offset + default_base_addr); // TODO this is different if its data |
| | 176 | const off = reloc.offset_in_caller + l.offset; |
| | 177 | std.mem.writeInt(u32, self.text_buf.items[off - 4 ..][0..4], callee_offset, endian); |
| | 178 | } else { |
| | 179 | // what we are writing |
| | 180 | const callee_offset = reloc.callee.link.plan9.offset + default_base_addr; // TODO this is different if its data |
| | 181 | const off = reloc.offset_in_caller + l.offset; |
| | 182 | std.mem.writeInt(u64, self.text_buf.items[off - 8 ..][0..8], callee_offset, endian); |
| | 183 | } |
| | 184 | } |
| | 185 | } |
| | 186 | |
| 165 | var sym_buf = std.ArrayList(u8).init(self.base.allocator); | 187 | var sym_buf = std.ArrayList(u8).init(self.base.allocator); |
| 166 | defer sym_buf.deinit(); | 188 | defer sym_buf.deinit(); |
| 167 | try self.writeSyms(&sym_buf); | 189 | try self.writeSyms(&sym_buf); |
| 168 | | 190 | |
| 169 | // generate the header | 191 | // generate the header |
| 170 | self.hdr.magic = try aout.magicFromArch(self.base.options.target.cpu.arch); | 192 | self.hdr = .{ |
| 171 | self.hdr.text = @intCast(u32, self.text_buf.items.len); | 193 | .magic = try aout.magicFromArch(self.base.options.target.cpu.arch), |
| 172 | self.hdr.data = @intCast(u32, self.data_buf.items.len); | 194 | .text = @intCast(u32, self.text_buf.items.len), |
| 173 | self.hdr.syms = @intCast(u32, sym_buf.items.len); | 195 | .data = @intCast(u32, self.data_buf.items.len), |
| 174 | self.hdr.bss = 0; | 196 | .syms = @intCast(u32, sym_buf.items.len), |
| 175 | self.hdr.pcsz = 0; | 197 | .bss = 0, |
| 176 | self.hdr.spsz = 0; | 198 | .pcsz = 0, |
| | 199 | .spsz = 0, |
| | 200 | .entry = self.hdr.entry, |
| | 201 | }; |
| 177 | | 202 | |
| 178 | const file = self.base.file.?; | 203 | const file = self.base.file.?; |
| 179 | | 204 | |
| ... | @@ -262,22 +287,26 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -262,22 +287,26 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 262 | const self = try createEmpty(allocator, options); | 287 | const self = try createEmpty(allocator, options); |
| 263 | errdefer self.base.destroy(); | 288 | errdefer self.base.destroy(); |
| 264 | | 289 | |
| | 290 | if (std.builtin.mode == .Debug or std.builtin.mode == .ReleaseSafe) |
| | 291 | self.hdr.entry = 0x0; |
| | 292 | |
| 265 | self.base.file = file; | 293 | self.base.file = file; |
| 266 | return self; | 294 | return self; |
| 267 | } | 295 | } |
| 268 | | 296 | |
| | 297 | // tells its future self to write the addr of the callee decl into offset_in_caller. |
| | 298 | // writes it to the {4, 8} bytes before offset_in_caller |
| 269 | pub fn addCallReloc(self: *Plan9, code: *std.ArrayList(u8), reloc: CallReloc) !void { | 299 | pub fn addCallReloc(self: *Plan9, code: *std.ArrayList(u8), reloc: CallReloc) !void { |
| 270 | try self.call_relocs.append(self.base.allocator, reloc); | 300 | try self.call_relocs.append(self.base.allocator, reloc); |
| 271 | try code.writer().writeIntBig(u64, 0xdeadbeef); | | |
| 272 | } | 301 | } |
| 273 | | 302 | |
| 274 | pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { | 303 | pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 275 | const writer = buf.writer(); | 304 | const writer = buf.writer(); |
| 276 | for (self.syms.items) |sym| { | 305 | for (self.syms.items) |sym| { |
| 277 | if (self.ptr_width == .p32) { | 306 | if (self.ptr_width == .p32) { |
| 278 | try writer.writeIntBig(u32, @intCast(u32, sym.value)); | 307 | try writer.writeIntBig(u32, @intCast(u32, sym.value) + default_base_addr); |
| 279 | } else { | 308 | } else { |
| 280 | try writer.writeIntBig(u64, sym.value); | 309 | try writer.writeIntBig(u64, sym.value + default_base_addr); |
| 281 | } | 310 | } |
| 282 | try writer.writeByte(@enumToInt(sym.type)); | 311 | try writer.writeByte(@enumToInt(sym.type)); |
| 283 | try writer.writeAll(std.mem.span(sym.name)); | 312 | try writer.writeAll(std.mem.span(sym.name)); |