| ... | ... | @@ -34,7 +34,7 @@ data_decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, []const u8) = .{}, |
| 34 | 34 | |
| 35 | 35 | hdr: aout.ExecHdr = undefined, |
| 36 | 36 | |
| 37 | | entry_decl: ?*Module.Decl = null, |
| 37 | entry_val: ?u64 = null, |
| 38 | 38 | |
| 39 | 39 | got_len: u64 = 0, |
| 40 | 40 | |
| ... | ... | @@ -213,6 +213,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 213 | 213 | if (build_options.skip_non_native and builtin.object_format != .plan9) { |
| 214 | 214 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 215 | 215 | } |
| 216 | |
| 216 | 217 | _ = comp; |
| 217 | 218 | const tracy = trace(@src()); |
| 218 | 219 | defer tracy.end(); |
| ... | ... | @@ -221,7 +222,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 221 | 222 | |
| 222 | 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 | 227 | assert(self.got_len == self.fn_decl_table.count() + self.data_decl_table.count()); |
| 227 | 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 | 231 | |
| 231 | 232 | // + 2 for header, got, symbols |
| 232 | 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 | 236 | const file = self.base.file.?; |
| 235 | 237 | |
| ... | ... | @@ -247,11 +249,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 247 | 249 | while (it.next()) |entry| { |
| 248 | 250 | const decl = entry.key_ptr.*; |
| 249 | 251 | const code = entry.value_ptr.*; |
| 252 | log.debug("write text decl {*} ({s})", .{ decl, decl.name }); |
| 250 | 253 | foff += code.len; |
| 251 | | text_i += code.len; |
| 252 | 254 | iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len }; |
| 253 | 255 | iovecs_i += 1; |
| 254 | 256 | const off = self.getAddr(text_i, .t); |
| 257 | text_i += code.len; |
| 255 | 258 | decl.link.plan9.offset = off; |
| 256 | 259 | if (!self.sixtyfour_bit) { |
| 257 | 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 | 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 | 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 | 270 | // etext symbol |
| 265 | 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 | 276 | // data |
| 268 | 277 | var data_i: u64 = got_size; |
| 269 | 278 | { |
| ... | ... | @@ -271,11 +280,13 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 271 | 280 | while (it.next()) |entry| { |
| 272 | 281 | const decl = entry.key_ptr.*; |
| 273 | 282 | const code = entry.value_ptr.*; |
| 283 | log.debug("write data decl {*} ({s})", .{ decl, decl.name }); |
| 284 | |
| 274 | 285 | foff += code.len; |
| 275 | | data_i += code.len; |
| 276 | 286 | iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len }; |
| 277 | 287 | iovecs_i += 1; |
| 278 | 288 | const off = self.getAddr(data_i, .d); |
| 289 | data_i += code.len; |
| 279 | 290 | decl.link.plan9.offset = off; |
| 280 | 291 | if (!self.sixtyfour_bit) { |
| 281 | 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 | 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 | 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 | 301 | // edata symbol |
| 288 | 302 | self.syms.items[0].value = self.getAddr(data_i, .b); |
| ... | ... | @@ -292,8 +306,6 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 292 | 306 | var sym_buf = std.ArrayList(u8).init(self.base.allocator); |
| 293 | 307 | defer sym_buf.deinit(); |
| 294 | 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 | 309 | assert(2 + self.fn_decl_table.count() + self.data_decl_table.count() == iovecs_i); // we didn't write all the decls |
| 298 | 310 | iovecs[iovecs_i] = .{ .iov_base = sym_buf.items.ptr, .iov_len = sym_buf.items.len }; |
| 299 | 311 | iovecs_i += 1; |
| ... | ... | @@ -306,16 +318,45 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 306 | 318 | .bss = 0, |
| 307 | 319 | .pcsz = 0, |
| 308 | 320 | .spsz = 0, |
| 309 | | .entry = @intCast(u32, self.entry_decl.?.link.plan9.offset.?), |
| 321 | .entry = @intCast(u32, self.entry_val.?), |
| 310 | 322 | }; |
| 311 | 323 | std.mem.copy(u8, hdr_slice, self.hdr.toU8s()[0..hdr_size]); |
| 312 | 324 | // write the fat header for 64 bit entry points |
| 313 | 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 | 328 | // write it all! |
| 317 | 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 | 360 | pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { |
| 320 | 361 | const is_fn = (decl.ty.zigTypeTag() == .Fn); |
| 321 | 362 | if (is_fn) |
| ... | ... | @@ -394,19 +435,23 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 394 | 435 | pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 395 | 436 | const writer = buf.writer(); |
| 396 | 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 | 442 | if (!self.sixtyfour_bit) { |
| 398 | 443 | try writer.writeIntBig(u32, @intCast(u32, sym.value)); |
| 399 | 444 | } else { |
| 400 | 445 | try writer.writeIntBig(u64, sym.value); |
| 401 | 446 | } |
| 402 | 447 | try writer.writeByte(@enumToInt(sym.type)); |
| 403 | | try writer.writeAll(std.mem.span(sym.name)); |
| 448 | try writer.writeAll(sym.name); |
| 404 | 449 | try writer.writeByte(0); |
| 405 | 450 | } |
| 406 | 451 | } |
| 407 | 452 | |
| 408 | 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 | 455 | self.got_len += 1; |
| 411 | 456 | decl.link.plan9.got_index = self.got_len - 1; |
| 412 | 457 | } |