authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-01 20:35:45+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-04 09:09:35+01:00
log21853bc310fb6029f949bcf9aca59f69c768a664
treee77aba201e50d6f86925b615450c7fda6e596b34
parent0ee2ab413fd0370a8ced8d433c71d1d951dab41c

elf: emit .rela shdrs for output sections


1 files changed, 107 insertions(+), 48 deletions(-)

src/link/Elf.zig+107-48
......@@ -99,15 +99,20 @@ plt_got: PltGotSection = .{},
9999copy_rel: CopyRelSection = .{},
100100/// .rela.plt section
101101rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
102/// .zig.got section
102/// .got.zig section
103103zig_got: ZigGotSection = .{},
104104
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.
106107zig_text_section_index: ?u16 = null,
108zig_text_rela_section_index: ?u16 = null,
107109zig_data_rel_ro_section_index: ?u16 = null,
110zig_data_rel_ro_rela_section_index: ?u16 = null,
108111zig_data_section_index: ?u16 = null,
112zig_data_rela_section_index: ?u16 = null,
109113zig_bss_section_index: ?u16 = null,
110114zig_got_section_index: ?u16 = null,
115zig_got_rela_section_index: ?u16 = null,
111116
112117debug_info_section_index: ?u16 = null,
113118debug_abbrev_section_index: ?u16 = null,
......@@ -491,6 +496,21 @@ pub fn initMetadata(self: *Elf) !void {
491496 const ptr_bit_width = self.base.options.target.ptrBitWidth();
492497 const is_linux = self.base.options.target.os.tag == .linux;
493498
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
494514 comptime assert(number_of_zig_segments == 5);
495515
496516 if (!self.isObject()) {
......@@ -569,24 +589,25 @@ pub fn initMetadata(self: *Elf) !void {
569589
570590 if (self.zig_text_section_index == null) {
571591 self.zig_text_section_index = try self.addSection(.{
572 .name = ".zig.text",
592 .name = ".text.zig",
573593 .type = elf.SHT_PROGBITS,
574594 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
575595 .addralign = 1,
576596 .offset = std.math.maxInt(u64),
577597 });
578598 const shdr = &self.shdrs.items[self.zig_text_section_index.?];
579 if (self.phdr_zig_load_re_index) |phndx| {
580 const phdr = self.phdrs.items[phndx];
581 shdr.sh_addr = phdr.p_vaddr;
582 shdr.sh_offset = phdr.p_offset;
583 shdr.sh_size = phdr.p_memsz;
584 try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_text_section_index.?, phndx);
599 fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index);
600 if (self.isObject()) {
601 self.zig_text_rela_section_index = try self.addRelaShdr(
602 ".rela.text.zig",
603 self.zig_text_section_index.?,
604 );
585605 } else {
586 const size = self.base.options.program_code_size_hint;
587 const off = self.findFreeSpace(size, 1);
588 shdr.sh_offset = off;
589 shdr.sh_size = size;
606 try self.phdr_to_shdr_table.putNoClobber(
607 gpa,
608 self.zig_text_section_index.?,
609 self.phdr_zig_load_re_index.?,
610 );
590611 }
591612 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{});
592613 }
......@@ -594,78 +615,80 @@ pub fn initMetadata(self: *Elf) !void {
594615 if (self.zig_got_section_index == null) {
595616 // TODO we don't actually need this section in a relocatable object file
596617 self.zig_got_section_index = try self.addSection(.{
597 .name = ".zig.got",
618 .name = ".got.zig",
598619 .type = elf.SHT_PROGBITS,
599620 .addralign = ptr_size,
600621 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
601622 .offset = std.math.maxInt(u64),
602623 });
603624 const shdr = &self.shdrs.items[self.zig_got_section_index.?];
604 if (self.phdr_zig_got_index) |phndx| {
605 const phdr = self.phdrs.items[phndx];
606 shdr.sh_addr = phdr.p_vaddr;
607 shdr.sh_offset = phdr.p_offset;
608 shdr.sh_size = phdr.p_memsz;
609 try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_got_section_index.?, phndx);
610 } else {
611 const size = @as(u64, ptr_size) * self.base.options.symbol_count_hint;
612 const off = self.findFreeSpace(size, ptr_size);
613 shdr.sh_offset = off;
614 shdr.sh_size = size;
625 fillSection(
626 self,
627 shdr,
628 @as(u64, ptr_size) * self.base.options.symbol_count_hint,
629 self.phdr_zig_got_index,
630 );
631 if (self.isObject()) {
632 self.zig_got_rela_section_index = try self.addRelaShdr(
633 ".rela.got.zig",
634 self.zig_got_section_index.?,
635 );
615636 }
616637 }
617638
618639 if (self.zig_data_rel_ro_section_index == null) {
619640 self.zig_data_rel_ro_section_index = try self.addSection(.{
620 .name = ".zig.data.rel.ro",
641 .name = ".data.rel.ro.zig",
621642 .type = elf.SHT_PROGBITS,
622643 .addralign = 1,
623644 .flags = elf.SHF_ALLOC | elf.SHF_WRITE, // TODO rename this section to .data.rel.ro
624645 .offset = std.math.maxInt(u64),
625646 });
626647 const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?];
627 if (self.phdr_zig_load_ro_index) |phndx| {
628 const phdr = self.phdrs.items[phndx];
629 shdr.sh_addr = phdr.p_vaddr;
630 shdr.sh_offset = phdr.p_offset;
631 shdr.sh_size = phdr.p_memsz;
632 try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, phndx);
648 fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index);
649 if (self.isObject()) {
650 self.zig_data_rel_ro_rela_section_index = try self.addRelaShdr(
651 ".rela.data.rel.ro.zig",
652 self.zig_data_rel_ro_section_index.?,
653 );
633654 } else {
634 const size: u64 = 1024;
635 const off = self.findFreeSpace(size, 1);
636 shdr.sh_offset = off;
637 shdr.sh_size = size;
655 try self.phdr_to_shdr_table.putNoClobber(
656 gpa,
657 self.zig_data_rel_ro_section_index.?,
658 self.phdr_zig_load_ro_index.?,
659 );
638660 }
639661 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{});
640662 }
641663
642664 if (self.zig_data_section_index == null) {
643665 self.zig_data_section_index = try self.addSection(.{
644 .name = ".zig.data",
666 .name = ".data.zig",
645667 .type = elf.SHT_PROGBITS,
646668 .addralign = ptr_size,
647669 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
648670 .offset = std.math.maxInt(u64),
649671 });
650672 const shdr = &self.shdrs.items[self.zig_data_section_index.?];
651 if (self.phdr_zig_load_rw_index) |phndx| {
652 const phdr = self.phdrs.items[phndx];
653 shdr.sh_addr = phdr.p_vaddr;
654 shdr.sh_offset = phdr.p_offset;
655 shdr.sh_size = phdr.p_memsz;
656 try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_data_section_index.?, phndx);
673 fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index);
674 if (self.isObject()) {
675 self.zig_data_rela_section_index = try self.addRelaShdr(
676 ".rela.data.zig",
677 self.zig_data_section_index.?,
678 );
657679 } else {
658 const size: u64 = 1024;
659 const off = self.findFreeSpace(size, ptr_size);
660 shdr.sh_offset = off;
661 shdr.sh_size = size;
680 try self.phdr_to_shdr_table.putNoClobber(
681 gpa,
682 self.zig_data_section_index.?,
683 self.phdr_zig_load_rw_index.?,
684 );
662685 }
663686 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_section_index.?, .{});
664687 }
665688
666689 if (self.zig_bss_section_index == null) {
667690 self.zig_bss_section_index = try self.addSection(.{
668 .name = ".zig.bss",
691 .name = ".bss.zig",
669692 .type = elf.SHT_NOBITS,
670693 .addralign = ptr_size,
671694 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
......@@ -3676,9 +3699,13 @@ fn sortShdrs(self: *Elf) !void {
36763699 &self.versym_section_index,
36773700 &self.verneed_section_index,
36783701 &self.zig_text_section_index,
3702 &self.zig_text_rela_section_index,
36793703 &self.zig_got_section_index,
3704 &self.zig_got_rela_section_index,
36803705 &self.zig_data_rel_ro_section_index,
3706 &self.zig_data_rel_ro_rela_section_index,
36813707 &self.zig_data_section_index,
3708 &self.zig_data_rela_section_index,
36823709 &self.zig_bss_section_index,
36833710 &self.debug_str_section_index,
36843711 &self.debug_info_section_index,
......@@ -3737,6 +3764,18 @@ fn sortShdrs(self: *Elf) !void {
37373764 shdr.sh_info = self.plt_section_index.?;
37383765 }
37393766
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
37403779 {
37413780 var phdr_to_shdr_table = try self.phdr_to_shdr_table.clone(gpa);
37423781 defer phdr_to_shdr_table.deinit(gpa);
......@@ -4955,6 +4994,26 @@ fn addPhdr(self: *Elf, opts: struct {
49554994 return index;
49564995}
49574996
4997fn 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
49585017pub const AddSectionOpts = struct {
49595018 name: [:0]const u8,
49605019 type: u32 = elf.SHT_NULL,