| ... | ... | @@ -39,11 +39,12 @@ 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 | // offset into syms |
| 43 | sym_index: ?usize, |
| 43 | 44 | pub const empty = DeclBlock{ |
| 44 | 45 | .type = .text, |
| 45 | 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 | 99 | const tracy = trace(@src()); |
| 99 | 100 | defer tracy.end(); |
| 100 | 101 | |
| 102 | defer assert(self.hdr.entry != 0x0); |
| 103 | |
| 101 | 104 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 102 | 105 | |
| 103 | 106 | self.text_buf.items.len = 0; |
| ... | ... | @@ -120,7 +123,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 120 | 123 | .type = .data, |
| 121 | 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 | 127 | try self.syms.append(self.base.allocator, .{ |
| 125 | 128 | .value = decl.link.plan9.offset, |
| 126 | 129 | .type = switch (decl.link.plan9.type) { |
| ... | ... | @@ -131,7 +134,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 131 | 134 | }); |
| 132 | 135 | decl.link.plan9.sym_index = self.syms.items.len - 1; |
| 133 | 136 | } else { |
| 134 | | self.syms.items[decl.link.plan9.sym_index] = .{ |
| 137 | self.syms.items[decl.link.plan9.sym_index.?] = .{ |
| 135 | 138 | .value = decl.link.plan9.offset, |
| 136 | 139 | .type = switch (decl.link.plan9.type) { |
| 137 | 140 | .text => .t, |
| ... | ... | @@ -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 | 187 | var sym_buf = std.ArrayList(u8).init(self.base.allocator); |
| 166 | 188 | defer sym_buf.deinit(); |
| 167 | 189 | try self.writeSyms(&sym_buf); |
| 168 | 190 | |
| 169 | 191 | // generate the header |
| 170 | | self.hdr.magic = try aout.magicFromArch(self.base.options.target.cpu.arch); |
| 171 | | self.hdr.text = @intCast(u32, self.text_buf.items.len); |
| 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; |
| 175 | | self.hdr.pcsz = 0; |
| 176 | | self.hdr.spsz = 0; |
| 192 | self.hdr = .{ |
| 193 | .magic = try aout.magicFromArch(self.base.options.target.cpu.arch), |
| 194 | .text = @intCast(u32, self.text_buf.items.len), |
| 195 | .data = @intCast(u32, self.data_buf.items.len), |
| 196 | .syms = @intCast(u32, sym_buf.items.len), |
| 197 | .bss = 0, |
| 198 | .pcsz = 0, |
| 199 | .spsz = 0, |
| 200 | .entry = self.hdr.entry, |
| 201 | }; |
| 177 | 202 | |
| 178 | 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 | 287 | const self = try createEmpty(allocator, options); |
| 263 | 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 | 293 | self.base.file = file; |
| 266 | 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 | 299 | pub fn addCallReloc(self: *Plan9, code: *std.ArrayList(u8), reloc: CallReloc) !void { |
| 270 | 300 | try self.call_relocs.append(self.base.allocator, reloc); |
| 271 | | try code.writer().writeIntBig(u64, 0xdeadbeef); |
| 272 | 301 | } |
| 273 | 302 | |
| 274 | 303 | pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 275 | 304 | const writer = buf.writer(); |
| 276 | 305 | for (self.syms.items) |sym| { |
| 277 | 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 | 308 | } else { |
| 280 | | try writer.writeIntBig(u64, sym.value); |
| 309 | try writer.writeIntBig(u64, sym.value + default_base_addr); |
| 281 | 310 | } |
| 282 | 311 | try writer.writeByte(@enumToInt(sym.type)); |
| 283 | 312 | try writer.writeAll(std.mem.span(sym.name)); |