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 = .{},...@@ -99,15 +99,20 @@ plt_got: PltGotSection = .{},
99copy_rel: CopyRelSection = .{},99copy_rel: CopyRelSection = .{},
100/// .rela.plt section100/// .rela.plt section
101rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},101rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
102/// .zig.got section102/// .got.zig section
103zig_got: ZigGotSection = .{},103zig_got: ZigGotSection = .{},
104104
105/// Tracked section headers with incremental updates to Zig object105/// Tracked section headers with incremental updates to Zig object.
106/// .rela.* sections are only used when emitting a relocatable object file.
106zig_text_section_index: ?u16 = null,107zig_text_section_index: ?u16 = null,
108zig_text_rela_section_index: ?u16 = null,
107zig_data_rel_ro_section_index: ?u16 = null,109zig_data_rel_ro_section_index: ?u16 = null,
110zig_data_rel_ro_rela_section_index: ?u16 = null,
108zig_data_section_index: ?u16 = null,111zig_data_section_index: ?u16 = null,
112zig_data_rela_section_index: ?u16 = null,
109zig_bss_section_index: ?u16 = null,113zig_bss_section_index: ?u16 = null,
110zig_got_section_index: ?u16 = null,114zig_got_section_index: ?u16 = null,
115zig_got_rela_section_index: ?u16 = null,
111116
112debug_info_section_index: ?u16 = null,117debug_info_section_index: ?u16 = null,
113debug_abbrev_section_index: ?u16 = null,118debug_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;
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
494 comptime assert(number_of_zig_segments == 5);514 comptime assert(number_of_zig_segments == 5);
495515
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 {
569589
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 file616 // 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 }
617638
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.ro644 .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 }
641663
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 }
665688
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 }
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
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}
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
4958pub const AddSectionOpts = struct {5017pub 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,