| ... | @@ -99,15 +99,20 @@ plt_got: PltGotSection = .{}, | ... | @@ -99,15 +99,20 @@ plt_got: PltGotSection = .{}, |
| 99 | copy_rel: CopyRelSection = .{}, | 99 | copy_rel: CopyRelSection = .{}, |
| 100 | /// .rela.plt section | 100 | /// .rela.plt section |
| 101 | rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, | 101 | rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, |
| 102 | /// .zig.got section | 102 | /// .got.zig section |
| 103 | zig_got: ZigGotSection = .{}, | 103 | zig_got: ZigGotSection = .{}, |
| 104 | | 104 | |
| 105 | /// Tracked section headers with incremental updates to Zig object | 105 | /// Tracked section headers with incremental updates to Zig object. |
| | 106 | /// .rela.* sections are only used when emitting a relocatable object file. |
| 106 | zig_text_section_index: ?u16 = null, | 107 | zig_text_section_index: ?u16 = null, |
| | 108 | zig_text_rela_section_index: ?u16 = null, |
| 107 | zig_data_rel_ro_section_index: ?u16 = null, | 109 | zig_data_rel_ro_section_index: ?u16 = null, |
| | 110 | zig_data_rel_ro_rela_section_index: ?u16 = null, |
| 108 | zig_data_section_index: ?u16 = null, | 111 | zig_data_section_index: ?u16 = null, |
| | 112 | zig_data_rela_section_index: ?u16 = null, |
| 109 | zig_bss_section_index: ?u16 = null, | 113 | zig_bss_section_index: ?u16 = null, |
| 110 | zig_got_section_index: ?u16 = null, | 114 | zig_got_section_index: ?u16 = null, |
| | 115 | zig_got_rela_section_index: ?u16 = null, |
| 111 | | 116 | |
| 112 | debug_info_section_index: ?u16 = null, | 117 | debug_info_section_index: ?u16 = null, |
| 113 | debug_abbrev_section_index: ?u16 = null, | 118 | debug_abbrev_section_index: ?u16 = null, |
| ... | @@ -491,6 +496,21 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -491,6 +496,21 @@ pub fn initMetadata(self: *Elf) !void { |
| 491 | const ptr_bit_width = self.base.options.target.ptrBitWidth(); | 496 | const ptr_bit_width = self.base.options.target.ptrBitWidth(); |
| 492 | const is_linux = self.base.options.target.os.tag == .linux; | 497 | const is_linux = self.base.options.target.os.tag == .linux; |
| 493 | | 498 | |
| | 499 | const fillSection = struct { |
| | 500 | fn fillSection(elf_file: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) void { |
| | 501 | if (elf_file.isObject()) { |
| | 502 | const off = elf_file.findFreeSpace(size, shdr.sh_addralign); |
| | 503 | shdr.sh_offset = off; |
| | 504 | shdr.sh_size = size; |
| | 505 | } else { |
| | 506 | const phdr = elf_file.phdrs.items[phndx.?]; |
| | 507 | shdr.sh_addr = phdr.p_vaddr; |
| | 508 | shdr.sh_offset = phdr.p_offset; |
| | 509 | shdr.sh_size = phdr.p_memsz; |
| | 510 | } |
| | 511 | } |
| | 512 | }.fillSection; |
| | 513 | |
| 494 | comptime assert(number_of_zig_segments == 5); | 514 | comptime assert(number_of_zig_segments == 5); |
| 495 | | 515 | |
| 496 | if (!self.isObject()) { | 516 | if (!self.isObject()) { |
| ... | @@ -569,24 +589,25 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -569,24 +589,25 @@ pub fn initMetadata(self: *Elf) !void { |
| 569 | | 589 | |
| 570 | if (self.zig_text_section_index == null) { | 590 | if (self.zig_text_section_index == null) { |
| 571 | self.zig_text_section_index = try self.addSection(.{ | 591 | self.zig_text_section_index = try self.addSection(.{ |
| 572 | .name = ".zig.text", | 592 | .name = ".text.zig", |
| 573 | .type = elf.SHT_PROGBITS, | 593 | .type = elf.SHT_PROGBITS, |
| 574 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | 594 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, |
| 575 | .addralign = 1, | 595 | .addralign = 1, |
| 576 | .offset = std.math.maxInt(u64), | 596 | .offset = std.math.maxInt(u64), |
| 577 | }); | 597 | }); |
| 578 | const shdr = &self.shdrs.items[self.zig_text_section_index.?]; | 598 | const shdr = &self.shdrs.items[self.zig_text_section_index.?]; |
| 579 | if (self.phdr_zig_load_re_index) |phndx| { | 599 | fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index); |
| 580 | const phdr = self.phdrs.items[phndx]; | 600 | if (self.isObject()) { |
| 581 | shdr.sh_addr = phdr.p_vaddr; | 601 | self.zig_text_rela_section_index = try self.addRelaShdr( |
| 582 | shdr.sh_offset = phdr.p_offset; | 602 | ".rela.text.zig", |
| 583 | shdr.sh_size = phdr.p_memsz; | 603 | self.zig_text_section_index.?, |
| 584 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_text_section_index.?, phndx); | 604 | ); |
| 585 | } else { | 605 | } else { |
| 586 | const size = self.base.options.program_code_size_hint; | 606 | try self.phdr_to_shdr_table.putNoClobber( |
| 587 | const off = self.findFreeSpace(size, 1); | 607 | gpa, |
| 588 | shdr.sh_offset = off; | 608 | self.zig_text_section_index.?, |
| 589 | shdr.sh_size = size; | 609 | self.phdr_zig_load_re_index.?, |
| | 610 | ); |
| 590 | } | 611 | } |
| 591 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{}); | 612 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{}); |
| 592 | } | 613 | } |
| ... | @@ -594,78 +615,80 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -594,78 +615,80 @@ pub fn initMetadata(self: *Elf) !void { |
| 594 | if (self.zig_got_section_index == null) { | 615 | if (self.zig_got_section_index == null) { |
| 595 | // TODO we don't actually need this section in a relocatable object file | 616 | // TODO we don't actually need this section in a relocatable object file |
| 596 | self.zig_got_section_index = try self.addSection(.{ | 617 | self.zig_got_section_index = try self.addSection(.{ |
| 597 | .name = ".zig.got", | 618 | .name = ".got.zig", |
| 598 | .type = elf.SHT_PROGBITS, | 619 | .type = elf.SHT_PROGBITS, |
| 599 | .addralign = ptr_size, | 620 | .addralign = ptr_size, |
| 600 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | 621 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 601 | .offset = std.math.maxInt(u64), | 622 | .offset = std.math.maxInt(u64), |
| 602 | }); | 623 | }); |
| 603 | const shdr = &self.shdrs.items[self.zig_got_section_index.?]; | 624 | const shdr = &self.shdrs.items[self.zig_got_section_index.?]; |
| 604 | if (self.phdr_zig_got_index) |phndx| { | 625 | fillSection( |
| 605 | const phdr = self.phdrs.items[phndx]; | 626 | self, |
| 606 | shdr.sh_addr = phdr.p_vaddr; | 627 | shdr, |
| 607 | shdr.sh_offset = phdr.p_offset; | 628 | @as(u64, ptr_size) * self.base.options.symbol_count_hint, |
| 608 | shdr.sh_size = phdr.p_memsz; | 629 | self.phdr_zig_got_index, |
| 609 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_got_section_index.?, phndx); | 630 | ); |
| 610 | } else { | 631 | if (self.isObject()) { |
| 611 | const size = @as(u64, ptr_size) * self.base.options.symbol_count_hint; | 632 | self.zig_got_rela_section_index = try self.addRelaShdr( |
| 612 | const off = self.findFreeSpace(size, ptr_size); | 633 | ".rela.got.zig", |
| 613 | shdr.sh_offset = off; | 634 | self.zig_got_section_index.?, |
| 614 | shdr.sh_size = size; | 635 | ); |
| 615 | } | 636 | } |
| 616 | } | 637 | } |
| 617 | | 638 | |
| 618 | if (self.zig_data_rel_ro_section_index == null) { | 639 | if (self.zig_data_rel_ro_section_index == null) { |
| 619 | self.zig_data_rel_ro_section_index = try self.addSection(.{ | 640 | self.zig_data_rel_ro_section_index = try self.addSection(.{ |
| 620 | .name = ".zig.data.rel.ro", | 641 | .name = ".data.rel.ro.zig", |
| 621 | .type = elf.SHT_PROGBITS, | 642 | .type = elf.SHT_PROGBITS, |
| 622 | .addralign = 1, | 643 | .addralign = 1, |
| 623 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, // TODO rename this section to .data.rel.ro | 644 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, // TODO rename this section to .data.rel.ro |
| 624 | .offset = std.math.maxInt(u64), | 645 | .offset = std.math.maxInt(u64), |
| 625 | }); | 646 | }); |
| 626 | const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?]; | 647 | const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?]; |
| 627 | if (self.phdr_zig_load_ro_index) |phndx| { | 648 | fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index); |
| 628 | const phdr = self.phdrs.items[phndx]; | 649 | if (self.isObject()) { |
| 629 | shdr.sh_addr = phdr.p_vaddr; | 650 | self.zig_data_rel_ro_rela_section_index = try self.addRelaShdr( |
| 630 | shdr.sh_offset = phdr.p_offset; | 651 | ".rela.data.rel.ro.zig", |
| 631 | shdr.sh_size = phdr.p_memsz; | 652 | self.zig_data_rel_ro_section_index.?, |
| 632 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, phndx); | 653 | ); |
| 633 | } else { | 654 | } else { |
| 634 | const size: u64 = 1024; | 655 | try self.phdr_to_shdr_table.putNoClobber( |
| 635 | const off = self.findFreeSpace(size, 1); | 656 | gpa, |
| 636 | shdr.sh_offset = off; | 657 | self.zig_data_rel_ro_section_index.?, |
| 637 | shdr.sh_size = size; | 658 | self.phdr_zig_load_ro_index.?, |
| | 659 | ); |
| 638 | } | 660 | } |
| 639 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{}); | 661 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{}); |
| 640 | } | 662 | } |
| 641 | | 663 | |
| 642 | if (self.zig_data_section_index == null) { | 664 | if (self.zig_data_section_index == null) { |
| 643 | self.zig_data_section_index = try self.addSection(.{ | 665 | self.zig_data_section_index = try self.addSection(.{ |
| 644 | .name = ".zig.data", | 666 | .name = ".data.zig", |
| 645 | .type = elf.SHT_PROGBITS, | 667 | .type = elf.SHT_PROGBITS, |
| 646 | .addralign = ptr_size, | 668 | .addralign = ptr_size, |
| 647 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | 669 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 648 | .offset = std.math.maxInt(u64), | 670 | .offset = std.math.maxInt(u64), |
| 649 | }); | 671 | }); |
| 650 | const shdr = &self.shdrs.items[self.zig_data_section_index.?]; | 672 | const shdr = &self.shdrs.items[self.zig_data_section_index.?]; |
| 651 | if (self.phdr_zig_load_rw_index) |phndx| { | 673 | fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index); |
| 652 | const phdr = self.phdrs.items[phndx]; | 674 | if (self.isObject()) { |
| 653 | shdr.sh_addr = phdr.p_vaddr; | 675 | self.zig_data_rela_section_index = try self.addRelaShdr( |
| 654 | shdr.sh_offset = phdr.p_offset; | 676 | ".rela.data.zig", |
| 655 | shdr.sh_size = phdr.p_memsz; | 677 | self.zig_data_section_index.?, |
| 656 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_data_section_index.?, phndx); | 678 | ); |
| 657 | } else { | 679 | } else { |
| 658 | const size: u64 = 1024; | 680 | try self.phdr_to_shdr_table.putNoClobber( |
| 659 | const off = self.findFreeSpace(size, ptr_size); | 681 | gpa, |
| 660 | shdr.sh_offset = off; | 682 | self.zig_data_section_index.?, |
| 661 | shdr.sh_size = size; | 683 | self.phdr_zig_load_rw_index.?, |
| | 684 | ); |
| 662 | } | 685 | } |
| 663 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_section_index.?, .{}); | 686 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_section_index.?, .{}); |
| 664 | } | 687 | } |
| 665 | | 688 | |
| 666 | if (self.zig_bss_section_index == null) { | 689 | if (self.zig_bss_section_index == null) { |
| 667 | self.zig_bss_section_index = try self.addSection(.{ | 690 | self.zig_bss_section_index = try self.addSection(.{ |
| 668 | .name = ".zig.bss", | 691 | .name = ".bss.zig", |
| 669 | .type = elf.SHT_NOBITS, | 692 | .type = elf.SHT_NOBITS, |
| 670 | .addralign = ptr_size, | 693 | .addralign = ptr_size, |
| 671 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | 694 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| ... | @@ -3676,9 +3699,13 @@ fn sortShdrs(self: *Elf) !void { | ... | @@ -3676,9 +3699,13 @@ fn sortShdrs(self: *Elf) !void { |
| 3676 | &self.versym_section_index, | 3699 | &self.versym_section_index, |
| 3677 | &self.verneed_section_index, | 3700 | &self.verneed_section_index, |
| 3678 | &self.zig_text_section_index, | 3701 | &self.zig_text_section_index, |
| | 3702 | &self.zig_text_rela_section_index, |
| 3679 | &self.zig_got_section_index, | 3703 | &self.zig_got_section_index, |
| | 3704 | &self.zig_got_rela_section_index, |
| 3680 | &self.zig_data_rel_ro_section_index, | 3705 | &self.zig_data_rel_ro_section_index, |
| | 3706 | &self.zig_data_rel_ro_rela_section_index, |
| 3681 | &self.zig_data_section_index, | 3707 | &self.zig_data_section_index, |
| | 3708 | &self.zig_data_rela_section_index, |
| 3682 | &self.zig_bss_section_index, | 3709 | &self.zig_bss_section_index, |
| 3683 | &self.debug_str_section_index, | 3710 | &self.debug_str_section_index, |
| 3684 | &self.debug_info_section_index, | 3711 | &self.debug_info_section_index, |
| ... | @@ -3737,6 +3764,18 @@ fn sortShdrs(self: *Elf) !void { | ... | @@ -3737,6 +3764,18 @@ fn sortShdrs(self: *Elf) !void { |
| 3737 | shdr.sh_info = self.plt_section_index.?; | 3764 | shdr.sh_info = self.plt_section_index.?; |
| 3738 | } | 3765 | } |
| 3739 | | 3766 | |
| | 3767 | for (&[_]?u16{ |
| | 3768 | self.zig_text_rela_section_index, |
| | 3769 | self.zig_got_rela_section_index, |
| | 3770 | self.zig_data_rel_ro_rela_section_index, |
| | 3771 | self.zig_data_rela_section_index, |
| | 3772 | }) |maybe_index| { |
| | 3773 | const index = maybe_index orelse continue; |
| | 3774 | const shdr = &self.shdrs.items[index]; |
| | 3775 | shdr.sh_link = self.symtab_section_index.?; |
| | 3776 | shdr.sh_info = backlinks[shdr.sh_info]; |
| | 3777 | } |
| | 3778 | |
| 3740 | { | 3779 | { |
| 3741 | var phdr_to_shdr_table = try self.phdr_to_shdr_table.clone(gpa); | 3780 | var phdr_to_shdr_table = try self.phdr_to_shdr_table.clone(gpa); |
| 3742 | defer phdr_to_shdr_table.deinit(gpa); | 3781 | defer phdr_to_shdr_table.deinit(gpa); |
| ... | @@ -4955,6 +4994,26 @@ fn addPhdr(self: *Elf, opts: struct { | ... | @@ -4955,6 +4994,26 @@ fn addPhdr(self: *Elf, opts: struct { |
| 4955 | return index; | 4994 | return index; |
| 4956 | } | 4995 | } |
| 4957 | | 4996 | |
| | 4997 | fn addRelaShdr(self: *Elf, name: [:0]const u8, shndx: u16) !u16 { |
| | 4998 | const entsize: u64 = switch (self.ptr_width) { |
| | 4999 | .p32 => @sizeOf(elf.Elf32_Rela), |
| | 5000 | .p64 => @sizeOf(elf.Elf64_Rela), |
| | 5001 | }; |
| | 5002 | const addralign: u64 = switch (self.ptr_width) { |
| | 5003 | .p32 => @alignOf(elf.Elf32_Rela), |
| | 5004 | .p64 => @alignOf(elf.Elf64_Rela), |
| | 5005 | }; |
| | 5006 | return self.addSection(.{ |
| | 5007 | .name = name, |
| | 5008 | .type = elf.SHT_RELA, |
| | 5009 | .flags = elf.SHF_INFO_LINK, |
| | 5010 | .entsize = entsize, |
| | 5011 | .info = shndx, |
| | 5012 | .addralign = addralign, |
| | 5013 | .offset = std.math.maxInt(u64), |
| | 5014 | }); |
| | 5015 | } |
| | 5016 | |
| 4958 | pub const AddSectionOpts = struct { | 5017 | pub const AddSectionOpts = struct { |
| 4959 | name: [:0]const u8, | 5018 | name: [:0]const u8, |
| 4960 | type: u32 = elf.SHT_NULL, | 5019 | type: u32 = elf.SHT_NULL, |