| ... | @@ -78,14 +78,9 @@ undefs: std.StringArrayHashMapUnmanaged(Symbol) = .{}, | ... | @@ -78,14 +78,9 @@ undefs: std.StringArrayHashMapUnmanaged(Symbol) = .{}, |
| 78 | externs: std.StringArrayHashMapUnmanaged(Symbol) = .{}, | 78 | externs: std.StringArrayHashMapUnmanaged(Symbol) = .{}, |
| 79 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 79 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 80 | | 80 | |
| 81 | // locals: std.StringArrayHashMapUnmanaged(std.ArrayListUnmanaged(Symbol)) = .{}, | 81 | threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{}, |
| 82 | // exports: std.StringArrayHashMapUnmanaged(macho.nlist_64) = .{}, | 82 | rebases: std.ArrayListUnmanaged(Pointer) = .{}, |
| 83 | // nonlazy_imports: std.StringArrayHashMapUnmanaged(Import) = .{}, | 83 | got_entries: std.StringArrayHashMapUnmanaged(GotEntry) = .{}, |
| 84 | // lazy_imports: std.StringArrayHashMapUnmanaged(Import) = .{}, | | |
| 85 | // tlv_bootstrap: ?Import = null, | | |
| 86 | // threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{}, | | |
| 87 | // local_rebases: std.ArrayListUnmanaged(Pointer) = .{}, | | |
| 88 | // nonlazy_pointers: std.StringArrayHashMapUnmanaged(GotEntry) = .{}, | | |
| 89 | | 84 | |
| 90 | stub_helper_stubs_start_off: ?u64 = null, | 85 | stub_helper_stubs_start_off: ?u64 = null, |
| 91 | | 86 | |
| ... | @@ -279,12 +274,12 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void { | ... | @@ -279,12 +274,12 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void { |
| 279 | try self.populateMetadata(); | 274 | try self.populateMetadata(); |
| 280 | try self.parseInputFiles(files); | 275 | try self.parseInputFiles(files); |
| 281 | try self.resolveSymbols(); | 276 | try self.resolveSymbols(); |
| 282 | self.printSymtab(); | 277 | try self.updateMetadata(); |
| 283 | // try self.sortSections(); | 278 | try self.sortSections(); |
| 284 | // try self.allocateTextSegment(); | 279 | try self.allocateTextSegment(); |
| 285 | // try self.allocateDataConstSegment(); | 280 | try self.allocateDataConstSegment(); |
| 286 | // try self.allocateDataSegment(); | 281 | try self.allocateDataSegment(); |
| 287 | // self.allocateLinkeditSegment(); | 282 | self.allocateLinkeditSegment(); |
| 288 | // try self.writeStubHelperCommon(); | 283 | // try self.writeStubHelperCommon(); |
| 289 | // try self.doRelocs(); | 284 | // try self.doRelocs(); |
| 290 | // try self.flush(); | 285 | // try self.flush(); |
| ... | @@ -403,28 +398,69 @@ fn mapAndUpdateSections( | ... | @@ -403,28 +398,69 @@ fn mapAndUpdateSections( |
| 403 | target_sect.size = offset + size; | 398 | target_sect.size = offset + size; |
| 404 | } | 399 | } |
| 405 | | 400 | |
| 406 | fn updateMetadata(self: *Zld, object_id: u16) !void { | 401 | fn updateMetadata(self: *Zld) !void { |
| 407 | const object = self.objects.items[object_id]; | 402 | for (self.objects.items) |object, id| { |
| 408 | const object_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; | 403 | const object_id = @intCast(u16, id); |
| 409 | const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 404 | const object_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| 410 | const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 405 | const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 411 | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 406 | const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 412 | | 407 | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 413 | // Create missing metadata | | |
| 414 | for (object_seg.sections.items) |source_sect, id| { | | |
| 415 | if (id == object.text_section_index.?) continue; | | |
| 416 | const segname = parseName(&source_sect.segname); | | |
| 417 | const sectname = parseName(&source_sect.sectname); | | |
| 418 | const flags = source_sect.flags; | | |
| 419 | | | |
| 420 | switch (flags) { | | |
| 421 | macho.S_REGULAR, macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { | | |
| 422 | if (mem.eql(u8, segname, "__TEXT")) { | | |
| 423 | if (self.text_const_section_index != null) continue; | | |
| 424 | | 408 | |
| 425 | self.text_const_section_index = @intCast(u16, text_seg.sections.items.len); | 409 | // Create missing metadata |
| | 410 | for (object_seg.sections.items) |source_sect, sect_id| { |
| | 411 | if (sect_id == object.text_section_index.?) continue; |
| | 412 | const segname = parseName(&source_sect.segname); |
| | 413 | const sectname = parseName(&source_sect.sectname); |
| | 414 | const flags = source_sect.flags; |
| | 415 | |
| | 416 | switch (flags) { |
| | 417 | macho.S_REGULAR, macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { |
| | 418 | if (mem.eql(u8, segname, "__TEXT")) { |
| | 419 | if (self.text_const_section_index != null) continue; |
| | 420 | |
| | 421 | self.text_const_section_index = @intCast(u16, text_seg.sections.items.len); |
| | 422 | try text_seg.addSection(self.allocator, .{ |
| | 423 | .sectname = makeStaticString("__const"), |
| | 424 | .segname = makeStaticString("__TEXT"), |
| | 425 | .addr = 0, |
| | 426 | .size = 0, |
| | 427 | .offset = 0, |
| | 428 | .@"align" = 0, |
| | 429 | .reloff = 0, |
| | 430 | .nreloc = 0, |
| | 431 | .flags = macho.S_REGULAR, |
| | 432 | .reserved1 = 0, |
| | 433 | .reserved2 = 0, |
| | 434 | .reserved3 = 0, |
| | 435 | }); |
| | 436 | } else if (mem.eql(u8, segname, "__DATA")) { |
| | 437 | if (!mem.eql(u8, sectname, "__const")) continue; |
| | 438 | if (self.data_const_section_index != null) continue; |
| | 439 | |
| | 440 | self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| | 441 | try data_const_seg.addSection(self.allocator, .{ |
| | 442 | .sectname = makeStaticString("__const"), |
| | 443 | .segname = makeStaticString("__DATA_CONST"), |
| | 444 | .addr = 0, |
| | 445 | .size = 0, |
| | 446 | .offset = 0, |
| | 447 | .@"align" = 0, |
| | 448 | .reloff = 0, |
| | 449 | .nreloc = 0, |
| | 450 | .flags = macho.S_REGULAR, |
| | 451 | .reserved1 = 0, |
| | 452 | .reserved2 = 0, |
| | 453 | .reserved3 = 0, |
| | 454 | }); |
| | 455 | } |
| | 456 | }, |
| | 457 | macho.S_CSTRING_LITERALS => { |
| | 458 | if (!mem.eql(u8, segname, "__TEXT")) continue; |
| | 459 | if (self.cstring_section_index != null) continue; |
| | 460 | |
| | 461 | self.cstring_section_index = @intCast(u16, text_seg.sections.items.len); |
| 426 | try text_seg.addSection(self.allocator, .{ | 462 | try text_seg.addSection(self.allocator, .{ |
| 427 | .sectname = makeStaticString("__const"), | 463 | .sectname = makeStaticString("__cstring"), |
| 428 | .segname = makeStaticString("__TEXT"), | 464 | .segname = makeStaticString("__TEXT"), |
| 429 | .addr = 0, | 465 | .addr = 0, |
| 430 | .size = 0, | 466 | .size = 0, |
| ... | @@ -432,18 +468,19 @@ fn updateMetadata(self: *Zld, object_id: u16) !void { | ... | @@ -432,18 +468,19 @@ fn updateMetadata(self: *Zld, object_id: u16) !void { |
| 432 | .@"align" = 0, | 468 | .@"align" = 0, |
| 433 | .reloff = 0, | 469 | .reloff = 0, |
| 434 | .nreloc = 0, | 470 | .nreloc = 0, |
| 435 | .flags = macho.S_REGULAR, | 471 | .flags = macho.S_CSTRING_LITERALS, |
| 436 | .reserved1 = 0, | 472 | .reserved1 = 0, |
| 437 | .reserved2 = 0, | 473 | .reserved2 = 0, |
| 438 | .reserved3 = 0, | 474 | .reserved3 = 0, |
| 439 | }); | 475 | }); |
| 440 | } else if (mem.eql(u8, segname, "__DATA")) { | 476 | }, |
| 441 | if (!mem.eql(u8, sectname, "__const")) continue; | 477 | macho.S_MOD_INIT_FUNC_POINTERS => { |
| 442 | if (self.data_const_section_index != null) continue; | 478 | if (!mem.eql(u8, segname, "__DATA")) continue; |
| | 479 | if (self.mod_init_func_section_index != null) continue; |
| 443 | | 480 | |
| 444 | self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len); | 481 | self.mod_init_func_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 445 | try data_const_seg.addSection(self.allocator, .{ | 482 | try data_const_seg.addSection(self.allocator, .{ |
| 446 | .sectname = makeStaticString("__const"), | 483 | .sectname = makeStaticString("__mod_init_func"), |
| 447 | .segname = makeStaticString("__DATA_CONST"), | 484 | .segname = makeStaticString("__DATA_CONST"), |
| 448 | .addr = 0, | 485 | .addr = 0, |
| 449 | .size = 0, | 486 | .size = 0, |
| ... | @@ -451,183 +488,143 @@ fn updateMetadata(self: *Zld, object_id: u16) !void { | ... | @@ -451,183 +488,143 @@ fn updateMetadata(self: *Zld, object_id: u16) !void { |
| 451 | .@"align" = 0, | 488 | .@"align" = 0, |
| 452 | .reloff = 0, | 489 | .reloff = 0, |
| 453 | .nreloc = 0, | 490 | .nreloc = 0, |
| 454 | .flags = macho.S_REGULAR, | 491 | .flags = macho.S_MOD_INIT_FUNC_POINTERS, |
| 455 | .reserved1 = 0, | 492 | .reserved1 = 0, |
| 456 | .reserved2 = 0, | 493 | .reserved2 = 0, |
| 457 | .reserved3 = 0, | 494 | .reserved3 = 0, |
| 458 | }); | 495 | }); |
| 459 | } | 496 | }, |
| 460 | }, | 497 | macho.S_MOD_TERM_FUNC_POINTERS => { |
| 461 | macho.S_CSTRING_LITERALS => { | 498 | if (!mem.eql(u8, segname, "__DATA")) continue; |
| 462 | if (!mem.eql(u8, segname, "__TEXT")) continue; | 499 | if (self.mod_term_func_section_index != null) continue; |
| 463 | if (self.cstring_section_index != null) continue; | | |
| 464 | | | |
| 465 | self.cstring_section_index = @intCast(u16, text_seg.sections.items.len); | | |
| 466 | try text_seg.addSection(self.allocator, .{ | | |
| 467 | .sectname = makeStaticString("__cstring"), | | |
| 468 | .segname = makeStaticString("__TEXT"), | | |
| 469 | .addr = 0, | | |
| 470 | .size = 0, | | |
| 471 | .offset = 0, | | |
| 472 | .@"align" = 0, | | |
| 473 | .reloff = 0, | | |
| 474 | .nreloc = 0, | | |
| 475 | .flags = macho.S_CSTRING_LITERALS, | | |
| 476 | .reserved1 = 0, | | |
| 477 | .reserved2 = 0, | | |
| 478 | .reserved3 = 0, | | |
| 479 | }); | | |
| 480 | }, | | |
| 481 | macho.S_MOD_INIT_FUNC_POINTERS => { | | |
| 482 | if (!mem.eql(u8, segname, "__DATA")) continue; | | |
| 483 | if (self.mod_init_func_section_index != null) continue; | | |
| 484 | | | |
| 485 | self.mod_init_func_section_index = @intCast(u16, data_const_seg.sections.items.len); | | |
| 486 | try data_const_seg.addSection(self.allocator, .{ | | |
| 487 | .sectname = makeStaticString("__mod_init_func"), | | |
| 488 | .segname = makeStaticString("__DATA_CONST"), | | |
| 489 | .addr = 0, | | |
| 490 | .size = 0, | | |
| 491 | .offset = 0, | | |
| 492 | .@"align" = 0, | | |
| 493 | .reloff = 0, | | |
| 494 | .nreloc = 0, | | |
| 495 | .flags = macho.S_MOD_INIT_FUNC_POINTERS, | | |
| 496 | .reserved1 = 0, | | |
| 497 | .reserved2 = 0, | | |
| 498 | .reserved3 = 0, | | |
| 499 | }); | | |
| 500 | }, | | |
| 501 | macho.S_MOD_TERM_FUNC_POINTERS => { | | |
| 502 | if (!mem.eql(u8, segname, "__DATA")) continue; | | |
| 503 | if (self.mod_term_func_section_index != null) continue; | | |
| 504 | | | |
| 505 | self.mod_term_func_section_index = @intCast(u16, data_const_seg.sections.items.len); | | |
| 506 | try data_const_seg.addSection(self.allocator, .{ | | |
| 507 | .sectname = makeStaticString("__mod_term_func"), | | |
| 508 | .segname = makeStaticString("__DATA_CONST"), | | |
| 509 | .addr = 0, | | |
| 510 | .size = 0, | | |
| 511 | .offset = 0, | | |
| 512 | .@"align" = 0, | | |
| 513 | .reloff = 0, | | |
| 514 | .nreloc = 0, | | |
| 515 | .flags = macho.S_MOD_TERM_FUNC_POINTERS, | | |
| 516 | .reserved1 = 0, | | |
| 517 | .reserved2 = 0, | | |
| 518 | .reserved3 = 0, | | |
| 519 | }); | | |
| 520 | }, | | |
| 521 | macho.S_ZEROFILL => { | | |
| 522 | if (!mem.eql(u8, segname, "__DATA")) continue; | | |
| 523 | if (self.bss_section_index != null) continue; | | |
| 524 | | | |
| 525 | self.bss_section_index = @intCast(u16, data_seg.sections.items.len); | | |
| 526 | try data_seg.addSection(self.allocator, .{ | | |
| 527 | .sectname = makeStaticString("__bss"), | | |
| 528 | .segname = makeStaticString("__DATA"), | | |
| 529 | .addr = 0, | | |
| 530 | .size = 0, | | |
| 531 | .offset = 0, | | |
| 532 | .@"align" = 0, | | |
| 533 | .reloff = 0, | | |
| 534 | .nreloc = 0, | | |
| 535 | .flags = macho.S_ZEROFILL, | | |
| 536 | .reserved1 = 0, | | |
| 537 | .reserved2 = 0, | | |
| 538 | .reserved3 = 0, | | |
| 539 | }); | | |
| 540 | }, | | |
| 541 | macho.S_THREAD_LOCAL_VARIABLES => { | | |
| 542 | if (!mem.eql(u8, segname, "__DATA")) continue; | | |
| 543 | if (self.tlv_section_index != null) continue; | | |
| 544 | | | |
| 545 | self.tlv_section_index = @intCast(u16, data_seg.sections.items.len); | | |
| 546 | try data_seg.addSection(self.allocator, .{ | | |
| 547 | .sectname = makeStaticString("__thread_vars"), | | |
| 548 | .segname = makeStaticString("__DATA"), | | |
| 549 | .addr = 0, | | |
| 550 | .size = 0, | | |
| 551 | .offset = 0, | | |
| 552 | .@"align" = 0, | | |
| 553 | .reloff = 0, | | |
| 554 | .nreloc = 0, | | |
| 555 | .flags = macho.S_THREAD_LOCAL_VARIABLES, | | |
| 556 | .reserved1 = 0, | | |
| 557 | .reserved2 = 0, | | |
| 558 | .reserved3 = 0, | | |
| 559 | }); | | |
| 560 | }, | | |
| 561 | macho.S_THREAD_LOCAL_REGULAR => { | | |
| 562 | if (!mem.eql(u8, segname, "__DATA")) continue; | | |
| 563 | if (self.tlv_data_section_index != null) continue; | | |
| 564 | | | |
| 565 | self.tlv_data_section_index = @intCast(u16, data_seg.sections.items.len); | | |
| 566 | try data_seg.addSection(self.allocator, .{ | | |
| 567 | .sectname = makeStaticString("__thread_data"), | | |
| 568 | .segname = makeStaticString("__DATA"), | | |
| 569 | .addr = 0, | | |
| 570 | .size = 0, | | |
| 571 | .offset = 0, | | |
| 572 | .@"align" = 0, | | |
| 573 | .reloff = 0, | | |
| 574 | .nreloc = 0, | | |
| 575 | .flags = macho.S_THREAD_LOCAL_REGULAR, | | |
| 576 | .reserved1 = 0, | | |
| 577 | .reserved2 = 0, | | |
| 578 | .reserved3 = 0, | | |
| 579 | }); | | |
| 580 | }, | | |
| 581 | macho.S_THREAD_LOCAL_ZEROFILL => { | | |
| 582 | if (!mem.eql(u8, segname, "__DATA")) continue; | | |
| 583 | if (self.tlv_bss_section_index != null) continue; | | |
| 584 | | | |
| 585 | self.tlv_bss_section_index = @intCast(u16, data_seg.sections.items.len); | | |
| 586 | try data_seg.addSection(self.allocator, .{ | | |
| 587 | .sectname = makeStaticString("__thread_bss"), | | |
| 588 | .segname = makeStaticString("__DATA"), | | |
| 589 | .addr = 0, | | |
| 590 | .size = 0, | | |
| 591 | .offset = 0, | | |
| 592 | .@"align" = 0, | | |
| 593 | .reloff = 0, | | |
| 594 | .nreloc = 0, | | |
| 595 | .flags = macho.S_THREAD_LOCAL_ZEROFILL, | | |
| 596 | .reserved1 = 0, | | |
| 597 | .reserved2 = 0, | | |
| 598 | .reserved3 = 0, | | |
| 599 | }); | | |
| 600 | }, | | |
| 601 | else => { | | |
| 602 | log.debug("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname }); | | |
| 603 | }, | | |
| 604 | } | | |
| 605 | } | | |
| 606 | | 500 | |
| 607 | // Find ideal section alignment. | 501 | self.mod_term_func_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 608 | for (object_seg.sections.items) |source_sect, id| { | 502 | try data_const_seg.addSection(self.allocator, .{ |
| 609 | if (self.getMatchingSection(source_sect)) |res| { | 503 | .sectname = makeStaticString("__mod_term_func"), |
| 610 | const target_seg = &self.load_commands.items[res.seg].Segment; | 504 | .segname = makeStaticString("__DATA_CONST"), |
| 611 | const target_sect = &target_seg.sections.items[res.sect]; | 505 | .addr = 0, |
| 612 | target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align"); | 506 | .size = 0, |
| | 507 | .offset = 0, |
| | 508 | .@"align" = 0, |
| | 509 | .reloff = 0, |
| | 510 | .nreloc = 0, |
| | 511 | .flags = macho.S_MOD_TERM_FUNC_POINTERS, |
| | 512 | .reserved1 = 0, |
| | 513 | .reserved2 = 0, |
| | 514 | .reserved3 = 0, |
| | 515 | }); |
| | 516 | }, |
| | 517 | macho.S_ZEROFILL => { |
| | 518 | if (!mem.eql(u8, segname, "__DATA")) continue; |
| | 519 | if (self.bss_section_index != null) continue; |
| | 520 | |
| | 521 | self.bss_section_index = @intCast(u16, data_seg.sections.items.len); |
| | 522 | try data_seg.addSection(self.allocator, .{ |
| | 523 | .sectname = makeStaticString("__bss"), |
| | 524 | .segname = makeStaticString("__DATA"), |
| | 525 | .addr = 0, |
| | 526 | .size = 0, |
| | 527 | .offset = 0, |
| | 528 | .@"align" = 0, |
| | 529 | .reloff = 0, |
| | 530 | .nreloc = 0, |
| | 531 | .flags = macho.S_ZEROFILL, |
| | 532 | .reserved1 = 0, |
| | 533 | .reserved2 = 0, |
| | 534 | .reserved3 = 0, |
| | 535 | }); |
| | 536 | }, |
| | 537 | macho.S_THREAD_LOCAL_VARIABLES => { |
| | 538 | if (!mem.eql(u8, segname, "__DATA")) continue; |
| | 539 | if (self.tlv_section_index != null) continue; |
| | 540 | |
| | 541 | self.tlv_section_index = @intCast(u16, data_seg.sections.items.len); |
| | 542 | try data_seg.addSection(self.allocator, .{ |
| | 543 | .sectname = makeStaticString("__thread_vars"), |
| | 544 | .segname = makeStaticString("__DATA"), |
| | 545 | .addr = 0, |
| | 546 | .size = 0, |
| | 547 | .offset = 0, |
| | 548 | .@"align" = 0, |
| | 549 | .reloff = 0, |
| | 550 | .nreloc = 0, |
| | 551 | .flags = macho.S_THREAD_LOCAL_VARIABLES, |
| | 552 | .reserved1 = 0, |
| | 553 | .reserved2 = 0, |
| | 554 | .reserved3 = 0, |
| | 555 | }); |
| | 556 | }, |
| | 557 | macho.S_THREAD_LOCAL_REGULAR => { |
| | 558 | if (!mem.eql(u8, segname, "__DATA")) continue; |
| | 559 | if (self.tlv_data_section_index != null) continue; |
| | 560 | |
| | 561 | self.tlv_data_section_index = @intCast(u16, data_seg.sections.items.len); |
| | 562 | try data_seg.addSection(self.allocator, .{ |
| | 563 | .sectname = makeStaticString("__thread_data"), |
| | 564 | .segname = makeStaticString("__DATA"), |
| | 565 | .addr = 0, |
| | 566 | .size = 0, |
| | 567 | .offset = 0, |
| | 568 | .@"align" = 0, |
| | 569 | .reloff = 0, |
| | 570 | .nreloc = 0, |
| | 571 | .flags = macho.S_THREAD_LOCAL_REGULAR, |
| | 572 | .reserved1 = 0, |
| | 573 | .reserved2 = 0, |
| | 574 | .reserved3 = 0, |
| | 575 | }); |
| | 576 | }, |
| | 577 | macho.S_THREAD_LOCAL_ZEROFILL => { |
| | 578 | if (!mem.eql(u8, segname, "__DATA")) continue; |
| | 579 | if (self.tlv_bss_section_index != null) continue; |
| | 580 | |
| | 581 | self.tlv_bss_section_index = @intCast(u16, data_seg.sections.items.len); |
| | 582 | try data_seg.addSection(self.allocator, .{ |
| | 583 | .sectname = makeStaticString("__thread_bss"), |
| | 584 | .segname = makeStaticString("__DATA"), |
| | 585 | .addr = 0, |
| | 586 | .size = 0, |
| | 587 | .offset = 0, |
| | 588 | .@"align" = 0, |
| | 589 | .reloff = 0, |
| | 590 | .nreloc = 0, |
| | 591 | .flags = macho.S_THREAD_LOCAL_ZEROFILL, |
| | 592 | .reserved1 = 0, |
| | 593 | .reserved2 = 0, |
| | 594 | .reserved3 = 0, |
| | 595 | }); |
| | 596 | }, |
| | 597 | else => { |
| | 598 | log.debug("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname }); |
| | 599 | }, |
| | 600 | } |
| 613 | } | 601 | } |
| 614 | } | | |
| 615 | | 602 | |
| 616 | // Update section mappings | 603 | // Find ideal section alignment. |
| 617 | for (object_seg.sections.items) |source_sect, id| { | 604 | for (object_seg.sections.items) |source_sect| { |
| 618 | const source_sect_id = @intCast(u16, id); | 605 | if (self.getMatchingSection(source_sect)) |res| { |
| 619 | if (self.getMatchingSection(source_sect)) |res| { | 606 | const target_seg = &self.load_commands.items[res.seg].Segment; |
| 620 | try self.mapAndUpdateSections(object_id, source_sect_id, res.seg, res.sect); | 607 | const target_sect = &target_seg.sections.items[res.sect]; |
| 621 | continue; | 608 | target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align"); |
| | 609 | } |
| 622 | } | 610 | } |
| 623 | | 611 | |
| 624 | const segname = parseName(&source_sect.segname); | 612 | // Update section mappings |
| 625 | const sectname = parseName(&source_sect.sectname); | 613 | for (object_seg.sections.items) |source_sect, sect_id| { |
| 626 | log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname }); | 614 | const source_sect_id = @intCast(u16, sect_id); |
| 627 | try self.unhandled_sections.putNoClobber(self.allocator, .{ | 615 | if (self.getMatchingSection(source_sect)) |res| { |
| 628 | .object_id = object_id, | 616 | try self.mapAndUpdateSections(object_id, source_sect_id, res.seg, res.sect); |
| 629 | .source_sect_id = source_sect_id, | 617 | continue; |
| 630 | }, 0); | 618 | } |
| | 619 | |
| | 620 | const segname = parseName(&source_sect.segname); |
| | 621 | const sectname = parseName(&source_sect.sectname); |
| | 622 | log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname }); |
| | 623 | try self.unhandled_sections.putNoClobber(self.allocator, .{ |
| | 624 | .object_id = object_id, |
| | 625 | .source_sect_id = source_sect_id, |
| | 626 | }, 0); |
| | 627 | } |
| 631 | } | 628 | } |
| 632 | } | 629 | } |
| 633 | | 630 | |
| ... | @@ -826,7 +823,10 @@ fn sortSections(self: *Zld) !void { | ... | @@ -826,7 +823,10 @@ fn sortSections(self: *Zld) !void { |
| 826 | | 823 | |
| 827 | fn allocateTextSegment(self: *Zld) !void { | 824 | fn allocateTextSegment(self: *Zld) !void { |
| 828 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 825 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 829 | const nexterns = @intCast(u32, self.lazy_imports.items().len); | 826 | // TODO This should be worked out by scanning the relocations in the __text sections of all combined |
| | 827 | // object files. For the time being, assume all externs are stubs (this is wasting space but should |
| | 828 | // correspond to the worst-case upper bound). |
| | 829 | const nstubs = @intCast(u32, self.externs.count()); |
| 830 | | 830 | |
| 831 | const base_vmaddr = self.load_commands.items[self.pagezero_segment_cmd_index.?].Segment.inner.vmsize; | 831 | const base_vmaddr = self.load_commands.items[self.pagezero_segment_cmd_index.?].Segment.inner.vmsize; |
| 832 | seg.inner.fileoff = 0; | 832 | seg.inner.fileoff = 0; |
| ... | @@ -835,14 +835,14 @@ fn allocateTextSegment(self: *Zld) !void { | ... | @@ -835,14 +835,14 @@ fn allocateTextSegment(self: *Zld) !void { |
| 835 | // Set stubs and stub_helper sizes | 835 | // Set stubs and stub_helper sizes |
| 836 | const stubs = &seg.sections.items[self.stubs_section_index.?]; | 836 | const stubs = &seg.sections.items[self.stubs_section_index.?]; |
| 837 | const stub_helper = &seg.sections.items[self.stub_helper_section_index.?]; | 837 | const stub_helper = &seg.sections.items[self.stub_helper_section_index.?]; |
| 838 | stubs.size += nexterns * stubs.reserved2; | 838 | stubs.size += nstubs * stubs.reserved2; |
| 839 | | 839 | |
| 840 | const stub_size: u4 = switch (self.arch.?) { | 840 | const stub_size: u4 = switch (self.arch.?) { |
| 841 | .x86_64 => 10, | 841 | .x86_64 => 10, |
| 842 | .aarch64 => 3 * @sizeOf(u32), | 842 | .aarch64 => 3 * @sizeOf(u32), |
| 843 | else => unreachable, | 843 | else => unreachable, |
| 844 | }; | 844 | }; |
| 845 | stub_helper.size += nexterns * stub_size; | 845 | stub_helper.size += nstubs * stub_size; |
| 846 | | 846 | |
| 847 | var sizeofcmds: u64 = 0; | 847 | var sizeofcmds: u64 = 0; |
| 848 | for (self.load_commands.items) |lc| { | 848 | for (self.load_commands.items) |lc| { |
| ... | @@ -877,7 +877,10 @@ fn allocateTextSegment(self: *Zld) !void { | ... | @@ -877,7 +877,10 @@ fn allocateTextSegment(self: *Zld) !void { |
| 877 | | 877 | |
| 878 | fn allocateDataConstSegment(self: *Zld) !void { | 878 | fn allocateDataConstSegment(self: *Zld) !void { |
| 879 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 879 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 880 | const nonlazy = @intCast(u32, self.nonlazy_imports.items().len); | 880 | // TODO This should be worked out by scanning the relocations in the __text sections of all |
| | 881 | // combined object files. For the time being, assume all externs are GOT entries (this is wasting space but |
| | 882 | // should correspond to the worst-case upper bound). |
| | 883 | const nexterns = @intCast(u32, self.externs.count()); |
| 881 | | 884 | |
| 882 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 885 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 883 | seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize; | 886 | seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize; |
| ... | @@ -888,14 +891,17 @@ fn allocateDataConstSegment(self: *Zld) !void { | ... | @@ -888,14 +891,17 @@ fn allocateDataConstSegment(self: *Zld) !void { |
| 888 | // TODO this will require scanning the relocations at least one to work out | 891 | // TODO this will require scanning the relocations at least one to work out |
| 889 | // the exact amount of local GOT indirections. For the time being, set some | 892 | // the exact amount of local GOT indirections. For the time being, set some |
| 890 | // default value. | 893 | // default value. |
| 891 | got.size += (max_local_got_indirections + nonlazy) * @sizeOf(u64); | 894 | got.size += (max_local_got_indirections + nexterns) * @sizeOf(u64); |
| 892 | | 895 | |
| 893 | try self.allocateSegment(self.data_const_segment_cmd_index.?, 0); | 896 | try self.allocateSegment(self.data_const_segment_cmd_index.?, 0); |
| 894 | } | 897 | } |
| 895 | | 898 | |
| 896 | fn allocateDataSegment(self: *Zld) !void { | 899 | fn allocateDataSegment(self: *Zld) !void { |
| 897 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 900 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 898 | const lazy = @intCast(u32, self.lazy_imports.items().len); | 901 | // TODO This should be worked out by scanning the relocations in the __text sections of all combined |
| | 902 | // object files. For the time being, assume all externs are stubs (this is wasting space but should |
| | 903 | // correspond to the worst-case upper bound). |
| | 904 | const nstubs = @intCast(u32, self.externs.count()); |
| 899 | | 905 | |
| 900 | const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 906 | const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 901 | seg.inner.fileoff = data_const_seg.inner.fileoff + data_const_seg.inner.filesize; | 907 | seg.inner.fileoff = data_const_seg.inner.fileoff + data_const_seg.inner.filesize; |
| ... | @@ -904,8 +910,8 @@ fn allocateDataSegment(self: *Zld) !void { | ... | @@ -904,8 +910,8 @@ fn allocateDataSegment(self: *Zld) !void { |
| 904 | // Set la_symbol_ptr and data size | 910 | // Set la_symbol_ptr and data size |
| 905 | const la_symbol_ptr = &seg.sections.items[self.la_symbol_ptr_section_index.?]; | 911 | const la_symbol_ptr = &seg.sections.items[self.la_symbol_ptr_section_index.?]; |
| 906 | const data = &seg.sections.items[self.data_section_index.?]; | 912 | const data = &seg.sections.items[self.data_section_index.?]; |
| 907 | la_symbol_ptr.size += lazy * @sizeOf(u64); | 913 | la_symbol_ptr.size += nstubs * @sizeOf(u64); |
| 908 | data.size += @sizeOf(u64); // TODO when do we need more? | 914 | data.size += @sizeOf(u64); // We need at least 8bytes for address of dyld_stub_binder |
| 909 | | 915 | |
| 910 | try self.allocateSegment(self.data_segment_cmd_index.?, 0); | 916 | try self.allocateSegment(self.data_segment_cmd_index.?, 0); |
| 911 | } | 917 | } |
| ... | @@ -1303,7 +1309,13 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1303,7 +1309,13 @@ fn resolveSymbols(self: *Zld) !void { |
| 1303 | while (self.undefs.items().len > 0) { | 1309 | while (self.undefs.items().len > 0) { |
| 1304 | const entry = self.undefs.pop(); | 1310 | const entry = self.undefs.pop(); |
| 1305 | try self.externs.putNoClobber(self.allocator, entry.key, .{ | 1311 | try self.externs.putNoClobber(self.allocator, entry.key, .{ |
| 1306 | .inner = entry.value.inner, | 1312 | .inner = .{ |
| | 1313 | .n_strx = 0, // This will be populated once we write the string table. |
| | 1314 | .n_type = macho.N_UNDF | macho.N_EXT, |
| | 1315 | .n_sect = 0, |
| | 1316 | .n_desc = macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | macho.N_SYMBOL_RESOLVER, |
| | 1317 | .n_value = 0, |
| | 1318 | }, |
| 1307 | .file = 0, | 1319 | .file = 0, |
| 1308 | }); | 1320 | }); |
| 1309 | } | 1321 | } |
| ... | @@ -1316,6 +1328,19 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1316,6 +1328,19 @@ fn resolveSymbols(self: *Zld) !void { |
| 1316 | | 1328 | |
| 1317 | return error.UndefinedSymbolReference; | 1329 | return error.UndefinedSymbolReference; |
| 1318 | } | 1330 | } |
| | 1331 | |
| | 1332 | // Finally, put in a reference to 'dyld_stub_binder'. |
| | 1333 | const name = try self.allocator.dupe(u8, "dyld_stub_binder"); |
| | 1334 | try self.externs.putNoClobber(self.allocator, name, .{ |
| | 1335 | .inner = .{ |
| | 1336 | .n_strx = 0, // This will be populated once we write the string table. |
| | 1337 | .n_type = std.macho.N_UNDF | std.macho.N_EXT, |
| | 1338 | .n_sect = 0, |
| | 1339 | .n_desc = std.macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | std.macho.N_SYMBOL_RESOLVER, |
| | 1340 | .n_value = 0, |
| | 1341 | }, |
| | 1342 | .file = 0, |
| | 1343 | }); |
| 1319 | } | 1344 | } |
| 1320 | | 1345 | |
| 1321 | fn doRelocs(self: *Zld) !void { | 1346 | fn doRelocs(self: *Zld) !void { |
| ... | @@ -1879,10 +1904,33 @@ fn doRelocs(self: *Zld) !void { | ... | @@ -1879,10 +1904,33 @@ fn doRelocs(self: *Zld) !void { |
| 1879 | fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 { | 1904 | fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 { |
| 1880 | const object = self.objects.items[object_id]; | 1905 | const object = self.objects.items[object_id]; |
| 1881 | const seg = object.load_commands.items[object.segment_cmd_index.?].Segment; | 1906 | const seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| | 1907 | |
| | 1908 | const is_got: bool = is_got: { |
| | 1909 | switch (self.arch.?) { |
| | 1910 | .x86_64 => { |
| | 1911 | const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type); |
| | 1912 | break :is_got = switch (rel_type) { |
| | 1913 | .X86_64_RELOC_GOT, .X86_64_RELOC_GOT_LOAD => true, |
| | 1914 | else => false, |
| | 1915 | }; |
| | 1916 | }, |
| | 1917 | .aarch64 => { |
| | 1918 | const rel_type = @intToEnum(macho.reloc_type_aarch64, rel.r_type); |
| | 1919 | break :is_got = switch (rel_type) { |
| | 1920 | .ARM64_RELOC_GOT_LOAD_PAGE21, |
| | 1921 | .ARM64_RELOC_GOT_LOAD_PAGEOFF12, |
| | 1922 | .ARM64_RELOC_POINTER_TO_GOT, |
| | 1923 | => true, |
| | 1924 | else => false, |
| | 1925 | }; |
| | 1926 | }, |
| | 1927 | } |
| | 1928 | }; |
| | 1929 | |
| 1882 | const target_addr = blk: { | 1930 | const target_addr = blk: { |
| 1883 | if (rel.r_extern == 1) { | 1931 | if (rel.r_extern == 1) { |
| 1884 | const sym = object.symtab.items[rel.r_symbolnum]; | 1932 | const sym = object.symtab.items[rel.r_symbolnum]; |
| 1885 | if (isLocal(&sym) or isExport(&sym)) { | 1933 | if (sym.isSect()) { |
| 1886 | // Relocate using section offsets only. | 1934 | // Relocate using section offsets only. |
| 1887 | const target_mapping = self.mappings.get(.{ | 1935 | const target_mapping = self.mappings.get(.{ |
| 1888 | .object_id = object_id, | 1936 | .object_id = object_id, |
| ... | @@ -1894,30 +1942,13 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 | ... | @@ -1894,30 +1942,13 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 |
| 1894 | const target_sect_addr = target_sect.addr + target_mapping.offset; | 1942 | const target_sect_addr = target_sect.addr + target_mapping.offset; |
| 1895 | log.debug(" | symbol local to object", .{}); | 1943 | log.debug(" | symbol local to object", .{}); |
| 1896 | break :blk target_sect_addr + sym.n_value - source_sect.addr; | 1944 | break :blk target_sect_addr + sym.n_value - source_sect.addr; |
| 1897 | } else if (isImport(&sym)) { | 1945 | } else if (sym.isUndf()) { |
| 1898 | // Relocate to either the artifact's local symbol, or an import from | 1946 | // Relocate to either the global symbol, or an import from |
| 1899 | // shared library. | 1947 | // shared library. |
| 1900 | const sym_name = object.getString(sym.n_strx); | 1948 | const sym_name = object.getString(sym.n_strx); |
| 1901 | if (self.locals.get(sym_name)) |locs| { | 1949 | if (self.globals.get(sym_name)) |glob| { |
| 1902 | var n_value: ?u64 = null; | 1950 | break :blk glob.inner.n_value; |
| 1903 | for (locs.items) |loc| { | 1951 | } else if (self.externs.getEntry(sym_name)) |ext| { |
| 1904 | switch (loc.tt) { | | |
| 1905 | .Global => { | | |
| 1906 | n_value = loc.inner.n_value; | | |
| 1907 | break; | | |
| 1908 | }, | | |
| 1909 | .WeakGlobal => { | | |
| 1910 | n_value = loc.inner.n_value; | | |
| 1911 | }, | | |
| 1912 | .Local => {}, | | |
| 1913 | } | | |
| 1914 | } | | |
| 1915 | if (n_value) |v| { | | |
| 1916 | break :blk v; | | |
| 1917 | } | | |
| 1918 | log.err("local symbol export '{s}' not found", .{sym_name}); | | |
| 1919 | return error.LocalSymbolExportNotFound; | | |
| 1920 | } else if (self.lazy_imports.get(sym_name)) |ext| { | | |
| 1921 | const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 1952 | const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 1922 | const stubs = segment.sections.items[self.stubs_section_index.?]; | 1953 | const stubs = segment.sections.items[self.stubs_section_index.?]; |
| 1923 | break :blk stubs.addr + ext.index * stubs.reserved2; | 1954 | break :blk stubs.addr + ext.index * stubs.reserved2; |
| ... | @@ -1928,7 +1959,7 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 | ... | @@ -1928,7 +1959,7 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 |
| 1928 | } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) { | 1959 | } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) { |
| 1929 | const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 1960 | const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 1930 | const tlv = segment.sections.items[self.tlv_section_index.?]; | 1961 | const tlv = segment.sections.items[self.tlv_section_index.?]; |
| 1931 | break :blk tlv.addr + self.tlv_bootstrap.?.index * @sizeOf(u64); | 1962 | break :blk tlv.addr; |
| 1932 | } else { | 1963 | } else { |
| 1933 | log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name}); | 1964 | log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name}); |
| 1934 | return error.FailedToResolveRelocationTarget; | 1965 | return error.FailedToResolveRelocationTarget; |
| ... | @@ -1951,6 +1982,7 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 | ... | @@ -1951,6 +1982,7 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 |
| 1951 | break :blk target_sect.addr + target_mapping.offset; | 1982 | break :blk target_sect.addr + target_mapping.offset; |
| 1952 | } | 1983 | } |
| 1953 | }; | 1984 | }; |
| | 1985 | |
| 1954 | return target_addr; | 1986 | return target_addr; |
| 1955 | } | 1987 | } |
| 1956 | | 1988 | |