| ... | @@ -34,7 +34,7 @@ data_decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, []const u8) = .{}, | ... | @@ -34,7 +34,7 @@ data_decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, []const u8) = .{}, |
| 34 | | 34 | |
| 35 | hdr: aout.ExecHdr = undefined, | 35 | hdr: aout.ExecHdr = undefined, |
| 36 | | 36 | |
| 37 | entry_decl: ?*Module.Decl = null, | 37 | entry_val: ?u64 = null, |
| 38 | | 38 | |
| 39 | got_len: u64 = 0, | 39 | got_len: u64 = 0, |
| 40 | | 40 | |
| ... | @@ -213,6 +213,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -213,6 +213,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 213 | if (build_options.skip_non_native and builtin.object_format != .plan9) { | 213 | if (build_options.skip_non_native and builtin.object_format != .plan9) { |
| 214 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 214 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 215 | } | 215 | } |
| | 216 | |
| 216 | _ = comp; | 217 | _ = comp; |
| 217 | const tracy = trace(@src()); | 218 | const tracy = trace(@src()); |
| 218 | defer tracy.end(); | 219 | defer tracy.end(); |
| ... | @@ -221,7 +222,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -221,7 +222,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 221 | | 222 | |
| 222 | defer assert(self.hdr.entry != 0x0); | 223 | defer assert(self.hdr.entry != 0x0); |
| 223 | | 224 | |
| 224 | _ = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; | 225 | const mod = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 225 | | 226 | |
| 226 | assert(self.got_len == self.fn_decl_table.count() + self.data_decl_table.count()); | 227 | assert(self.got_len == self.fn_decl_table.count() + self.data_decl_table.count()); |
| 227 | const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; | 228 | const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; |
| ... | @@ -230,6 +231,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -230,6 +231,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 230 | | 231 | |
| 231 | // + 2 for header, got, symbols | 232 | // + 2 for header, got, symbols |
| 232 | var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.fn_decl_table.count() + self.data_decl_table.count() + 3); | 233 | var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.fn_decl_table.count() + self.data_decl_table.count() + 3); |
| | 234 | defer self.base.allocator.free(iovecs); |
| 233 | | 235 | |
| 234 | const file = self.base.file.?; | 236 | const file = self.base.file.?; |
| 235 | | 237 | |
| ... | @@ -247,11 +249,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -247,11 +249,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 247 | while (it.next()) |entry| { | 249 | while (it.next()) |entry| { |
| 248 | const decl = entry.key_ptr.*; | 250 | const decl = entry.key_ptr.*; |
| 249 | const code = entry.value_ptr.*; | 251 | const code = entry.value_ptr.*; |
| | 252 | log.debug("write text decl {*} ({s})", .{ decl, decl.name }); |
| 250 | foff += code.len; | 253 | foff += code.len; |
| 251 | text_i += code.len; | | |
| 252 | iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len }; | 254 | iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len }; |
| 253 | iovecs_i += 1; | 255 | iovecs_i += 1; |
| 254 | const off = self.getAddr(text_i, .t); | 256 | const off = self.getAddr(text_i, .t); |
| | 257 | text_i += code.len; |
| 255 | decl.link.plan9.offset = off; | 258 | decl.link.plan9.offset = off; |
| 256 | if (!self.sixtyfour_bit) { | 259 | if (!self.sixtyfour_bit) { |
| 257 | mem.writeIntNative(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off)); | 260 | mem.writeIntNative(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off)); |
| ... | @@ -260,10 +263,16 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -260,10 +263,16 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 260 | mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); | 263 | mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); |
| 261 | } | 264 | } |
| 262 | self.syms.items[decl.link.plan9.sym_index.?].value = off; | 265 | self.syms.items[decl.link.plan9.sym_index.?].value = off; |
| | 266 | if (mod.decl_exports.get(decl)) |exports| { |
| | 267 | try self.addDeclExports(mod, decl, exports); |
| | 268 | } |
| 263 | } | 269 | } |
| 264 | // etext symbol | 270 | // etext symbol |
| 265 | self.syms.items[2].value = self.getAddr(text_i, .t); | 271 | self.syms.items[2].value = self.getAddr(text_i, .t); |
| 266 | } | 272 | } |
| | 273 | // global offset table is in data |
| | 274 | iovecs[iovecs_i] = .{ .iov_base = got_table.ptr, .iov_len = got_table.len }; |
| | 275 | iovecs_i += 1; |
| 267 | // data | 276 | // data |
| 268 | var data_i: u64 = got_size; | 277 | var data_i: u64 = got_size; |
| 269 | { | 278 | { |
| ... | @@ -271,11 +280,13 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -271,11 +280,13 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 271 | while (it.next()) |entry| { | 280 | while (it.next()) |entry| { |
| 272 | const decl = entry.key_ptr.*; | 281 | const decl = entry.key_ptr.*; |
| 273 | const code = entry.value_ptr.*; | 282 | const code = entry.value_ptr.*; |
| | 283 | log.debug("write data decl {*} ({s})", .{ decl, decl.name }); |
| | 284 | |
| 274 | foff += code.len; | 285 | foff += code.len; |
| 275 | data_i += code.len; | | |
| 276 | iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len }; | 286 | iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len }; |
| 277 | iovecs_i += 1; | 287 | iovecs_i += 1; |
| 278 | const off = self.getAddr(data_i, .d); | 288 | const off = self.getAddr(data_i, .d); |
| | 289 | data_i += code.len; |
| 279 | decl.link.plan9.offset = off; | 290 | decl.link.plan9.offset = off; |
| 280 | if (!self.sixtyfour_bit) { | 291 | if (!self.sixtyfour_bit) { |
| 281 | mem.writeInt(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian()); | 292 | mem.writeInt(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian()); |
| ... | @@ -283,6 +294,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -283,6 +294,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 283 | mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); | 294 | mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); |
| 284 | } | 295 | } |
| 285 | self.syms.items[decl.link.plan9.sym_index.?].value = off; | 296 | self.syms.items[decl.link.plan9.sym_index.?].value = off; |
| | 297 | if (mod.decl_exports.get(decl)) |exports| { |
| | 298 | try self.addDeclExports(mod, decl, exports); |
| | 299 | } |
| 286 | } | 300 | } |
| 287 | // edata symbol | 301 | // edata symbol |
| 288 | self.syms.items[0].value = self.getAddr(data_i, .b); | 302 | self.syms.items[0].value = self.getAddr(data_i, .b); |
| ... | @@ -292,8 +306,6 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -292,8 +306,6 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 292 | var sym_buf = std.ArrayList(u8).init(self.base.allocator); | 306 | var sym_buf = std.ArrayList(u8).init(self.base.allocator); |
| 293 | defer sym_buf.deinit(); | 307 | defer sym_buf.deinit(); |
| 294 | try self.writeSyms(&sym_buf); | 308 | try self.writeSyms(&sym_buf); |
| 295 | iovecs[iovecs_i] = .{ .iov_base = got_table.ptr, .iov_len = got_table.len }; | | |
| 296 | iovecs_i += 1; | | |
| 297 | assert(2 + self.fn_decl_table.count() + self.data_decl_table.count() == iovecs_i); // we didn't write all the decls | 309 | assert(2 + self.fn_decl_table.count() + self.data_decl_table.count() == iovecs_i); // we didn't write all the decls |
| 298 | iovecs[iovecs_i] = .{ .iov_base = sym_buf.items.ptr, .iov_len = sym_buf.items.len }; | 310 | iovecs[iovecs_i] = .{ .iov_base = sym_buf.items.ptr, .iov_len = sym_buf.items.len }; |
| 299 | iovecs_i += 1; | 311 | iovecs_i += 1; |
| ... | @@ -306,16 +318,45 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -306,16 +318,45 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 306 | .bss = 0, | 318 | .bss = 0, |
| 307 | .pcsz = 0, | 319 | .pcsz = 0, |
| 308 | .spsz = 0, | 320 | .spsz = 0, |
| 309 | .entry = @intCast(u32, self.entry_decl.?.link.plan9.offset.?), | 321 | .entry = @intCast(u32, self.entry_val.?), |
| 310 | }; | 322 | }; |
| 311 | std.mem.copy(u8, hdr_slice, self.hdr.toU8s()[0..hdr_size]); | 323 | std.mem.copy(u8, hdr_slice, self.hdr.toU8s()[0..hdr_size]); |
| 312 | // write the fat header for 64 bit entry points | 324 | // write the fat header for 64 bit entry points |
| 313 | if (self.sixtyfour_bit) { | 325 | if (self.sixtyfour_bit) { |
| 314 | mem.writeIntSliceBig(u64, hdr_buf[32..40], self.entry_decl.?.link.plan9.offset.?); | 326 | mem.writeIntSliceBig(u64, hdr_buf[32..40], self.entry_val.?); |
| 315 | } | 327 | } |
| 316 | // write it all! | 328 | // write it all! |
| 317 | try file.pwritevAll(iovecs, 0); | 329 | try file.pwritevAll(iovecs, 0); |
| 318 | } | 330 | } |
| | 331 | fn addDeclExports( |
| | 332 | self: *Plan9, |
| | 333 | module: *Module, |
| | 334 | decl: *Module.Decl, |
| | 335 | exports: []const *Module.Export, |
| | 336 | ) !void { |
| | 337 | for (exports) |exp| { |
| | 338 | // plan9 does not support custom sections |
| | 339 | if (exp.options.section) |section_name| { |
| | 340 | if (!mem.eql(u8, section_name, ".text") or !mem.eql(u8, section_name, ".data")) { |
| | 341 | try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "plan9 does not support extra sections", .{})); |
| | 342 | break; |
| | 343 | } |
| | 344 | } |
| | 345 | const sym = .{ |
| | 346 | .value = decl.link.plan9.offset.?, |
| | 347 | .type = decl.link.plan9.type.toGlobal(), |
| | 348 | .name = exp.options.name, |
| | 349 | }; |
| | 350 | |
| | 351 | if (exp.link.plan9) |i| { |
| | 352 | self.syms.items[i] = sym; |
| | 353 | } else { |
| | 354 | try self.syms.append(self.base.allocator, sym); |
| | 355 | exp.link.plan9 = self.syms.items.len - 1; |
| | 356 | } |
| | 357 | } |
| | 358 | } |
| | 359 | |
| 319 | pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { | 360 | pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { |
| 320 | const is_fn = (decl.ty.zigTypeTag() == .Fn); | 361 | const is_fn = (decl.ty.zigTypeTag() == .Fn); |
| 321 | if (is_fn) | 362 | if (is_fn) |
| ... | @@ -394,19 +435,23 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -394,19 +435,23 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 394 | pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { | 435 | pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 395 | const writer = buf.writer(); | 436 | const writer = buf.writer(); |
| 396 | for (self.syms.items) |sym| { | 437 | for (self.syms.items) |sym| { |
| | 438 | log.debug("sym.name: {s}", .{sym.name}); |
| | 439 | log.debug("sym.value: {x}", .{sym.value}); |
| | 440 | if (mem.eql(u8, sym.name, "_start")) |
| | 441 | self.entry_val = sym.value; |
| 397 | if (!self.sixtyfour_bit) { | 442 | if (!self.sixtyfour_bit) { |
| 398 | try writer.writeIntBig(u32, @intCast(u32, sym.value)); | 443 | try writer.writeIntBig(u32, @intCast(u32, sym.value)); |
| 399 | } else { | 444 | } else { |
| 400 | try writer.writeIntBig(u64, sym.value); | 445 | try writer.writeIntBig(u64, sym.value); |
| 401 | } | 446 | } |
| 402 | try writer.writeByte(@enumToInt(sym.type)); | 447 | try writer.writeByte(@enumToInt(sym.type)); |
| 403 | try writer.writeAll(std.mem.span(sym.name)); | 448 | try writer.writeAll(sym.name); |
| 404 | try writer.writeByte(0); | 449 | try writer.writeByte(0); |
| 405 | } | 450 | } |
| 406 | } | 451 | } |
| 407 | | 452 | |
| 408 | pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void { | 453 | pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void { |
| 409 | if (decl.link.plan9.got_index != null) { | 454 | if (decl.link.plan9.got_index == null) { |
| 410 | self.got_len += 1; | 455 | self.got_len += 1; |
| 411 | decl.link.plan9.got_index = self.got_len - 1; | 456 | decl.link.plan9.got_index = self.got_len - 1; |
| 412 | } | 457 | } |