authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-08-26 19:25:23-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-08-26 19:25:23-07:00
logd9147b91a601ad2442aaa43f4dba2d01b25d803d
tree26f06816d827f4fd82772816dd4a33e2f7a465b6
parent492cc2ef8d1d21d96e25541c22ab885a31c62770
parent1254509d78d8dd3d6eb7922bbb924084eae826fd
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21212 from ziglang/elf-incr

elf: cleanups, cleanups, cleanups

12 files changed, 738 insertions(+), 854 deletions(-)

src/link/Dwarf.zig+4-4
......@@ -317,7 +317,7 @@ pub const Section = struct {
317317 fn resize(sec: *Section, dwarf: *Dwarf, len: u64) UpdateError!void {
318318 if (dwarf.bin_file.cast(.elf)) |elf_file| {
319319 try elf_file.growNonAllocSection(sec.index, len, @intCast(sec.alignment.toByteUnits().?), true);
320 const shdr = &elf_file.shdrs.items[sec.index];
320 const shdr = &elf_file.sections.items(.shdr)[sec.index];
321321 sec.off = shdr.sh_offset;
322322 sec.len = shdr.sh_size;
323323 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
......@@ -340,7 +340,7 @@ pub const Section = struct {
340340 sec.off += len;
341341 sec.len -= len;
342342 if (dwarf.bin_file.cast(.elf)) |elf_file| {
343 const shdr = &elf_file.shdrs.items[sec.index];
343 const shdr = &elf_file.sections.items(.shdr)[sec.index];
344344 shdr.sh_offset = sec.off;
345345 shdr.sh_size = sec.len;
346346 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
......@@ -771,7 +771,7 @@ const Entry = struct {
771771 log.err("missing {} from {s}", .{
772772 @as(Entry.Index, @enumFromInt(entry - unit.entries.items.ptr)),
773773 std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file|
774 elf_file.shstrtab.items[elf_file.shdrs.items[sec.index].sh_name..]
774 elf_file.shstrtab.items[elf_file.sections.items(.shdr)[sec.index].sh_name..]
775775 else if (dwarf.bin_file.cast(.macho)) |macho_file|
776776 if (macho_file.d_sym) |*d_sym|
777777 &d_sym.sections.items[sec.index].segname
......@@ -1529,7 +1529,7 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void {
15291529 elf_file.debug_rnglists_section_index.?,
15301530 elf_file.debug_str_section_index.?,
15311531 }) |sec, section_index| {
1532 const shdr = &elf_file.shdrs.items[section_index];
1532 const shdr = &elf_file.sections.items(.shdr)[section_index];
15331533 sec.index = section_index;
15341534 sec.off = shdr.sh_offset;
15351535 sec.len = shdr.sh_size;
src/link/Elf.zig+213-623
......@@ -45,17 +45,10 @@ linker_defined_index: ?File.Index = null,
4545objects: std.ArrayListUnmanaged(File.Index) = .{},
4646shared_objects: std.ArrayListUnmanaged(File.Index) = .{},
4747
48/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
49/// Same order as in the file.
50shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{},
51/// Given index to a section, pulls index of containing phdr if any.
52phdr_to_shdr_table: std.AutoHashMapUnmanaged(u32, u32) = .{},
48/// List of all output sections and their associated metadata.
49sections: std.MultiArrayList(Section) = .{},
5350/// File offset into the shdr table.
5451shdr_table_offset: ?u64 = null,
55/// Table of lists of atoms per output section.
56/// This table is not used to track incrementally generated atoms.
57output_sections: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(Ref)) = .{},
58output_rela_sections: std.AutoArrayHashMapUnmanaged(u32, RelaSection) = .{},
5952
6053/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
6154/// Same order as in the file.
......@@ -181,9 +174,6 @@ thunks: std.ArrayListUnmanaged(Thunk) = .{},
181174/// List of output merge sections with deduped contents.
182175merge_sections: std.ArrayListUnmanaged(MergeSection) = .{},
183176
184/// Table of last atom index in a section and matching atom free list if any.
185last_atom_and_free_list_table: LastAtomAndFreeListTable = .{},
186
187177first_eflags: ?elf.Elf64_Word = null,
188178
189179/// When allocating, the ideal_capacity is calculated by
......@@ -387,8 +377,7 @@ pub fn createEmpty(
387377 )}),
388378 } });
389379 self.zig_object_index = index;
390 try self.zigObjectPtr().?.init(self);
391 try self.initMetadata(.{
380 try self.zigObjectPtr().?.init(self, .{
392381 .symbol_count_hint = options.symbol_count_hint,
393382 .program_code_size_hint = options.program_code_size_hint,
394383 });
......@@ -430,17 +419,12 @@ pub fn deinit(self: *Elf) void {
430419 self.objects.deinit(gpa);
431420 self.shared_objects.deinit(gpa);
432421
433 self.shdrs.deinit(gpa);
434 self.phdr_to_shdr_table.deinit(gpa);
435 self.phdrs.deinit(gpa);
436 for (self.output_sections.values()) |*list| {
437 list.deinit(gpa);
422 for (self.sections.items(.atom_list), self.sections.items(.free_list)) |*atoms, *free_list| {
423 atoms.deinit(gpa);
424 free_list.deinit(gpa);
438425 }
439 self.output_sections.deinit(gpa);
440 for (self.output_rela_sections.values()) |*sec| {
441 sec.atom_list.deinit(gpa);
442 }
443 self.output_rela_sections.deinit(gpa);
426 self.sections.deinit(gpa);
427 self.phdrs.deinit(gpa);
444428 self.shstrtab.deinit(gpa);
445429 self.symtab.deinit(gpa);
446430 self.strtab.deinit(gpa);
......@@ -454,10 +438,6 @@ pub fn deinit(self: *Elf) void {
454438 sect.deinit(gpa);
455439 }
456440 self.merge_sections.deinit(gpa);
457 for (self.last_atom_and_free_list_table.values()) |*value| {
458 value.free_list.deinit(gpa);
459 }
460 self.last_atom_and_free_list_table.deinit(gpa);
461441
462442 self.got.deinit(gpa);
463443 self.plt.deinit(gpa);
......@@ -506,7 +486,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {
506486
507487 if (self.shdr_table_offset) |off| {
508488 const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr);
509 const tight_size = self.shdrs.items.len * shdr_size;
489 const tight_size = self.sections.items(.shdr).len * shdr_size;
510490 const increased_size = padToIdeal(tight_size);
511491 const test_end = off +| increased_size;
512492 if (start < test_end) {
......@@ -515,7 +495,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {
515495 }
516496 }
517497
518 for (self.shdrs.items) |shdr| {
498 for (self.sections.items(.shdr)) |shdr| {
519499 if (shdr.sh_type == elf.SHT_NOBITS) continue;
520500 const increased_size = padToIdeal(shdr.sh_size);
521501 const test_end = shdr.sh_offset +| increased_size;
......@@ -545,7 +525,7 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {
545525 if (self.shdr_table_offset) |off| {
546526 if (off > start and off < min_pos) min_pos = off;
547527 }
548 for (self.shdrs.items) |section| {
528 for (self.sections.items(.shdr)) |section| {
549529 if (section.sh_offset <= start) continue;
550530 if (section.sh_offset < min_pos) min_pos = section.sh_offset;
551531 }
......@@ -574,318 +554,13 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {
574554 return start;
575555}
576556
577pub const InitMetadataOptions = struct {
578 symbol_count_hint: u64,
579 program_code_size_hint: u64,
580};
581
582/// TODO move to ZigObject
583pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
584 const gpa = self.base.comp.gpa;
585 const ptr_size = self.ptrWidthBytes();
586 const target = self.base.comp.root_mod.resolved_target.result;
587 const ptr_bit_width = target.ptrBitWidth();
588 const zo = self.zigObjectPtr().?;
589
590 const fillSection = struct {
591 fn fillSection(elf_file: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) !void {
592 if (elf_file.base.isRelocatable()) {
593 const off = try elf_file.findFreeSpace(size, shdr.sh_addralign);
594 shdr.sh_offset = off;
595 shdr.sh_size = size;
596 } else {
597 const phdr = elf_file.phdrs.items[phndx.?];
598 shdr.sh_addr = phdr.p_vaddr;
599 shdr.sh_offset = phdr.p_offset;
600 shdr.sh_size = phdr.p_memsz;
601 }
602 }
603 }.fillSection;
604
605 comptime assert(number_of_zig_segments == 5);
606
607 if (!self.base.isRelocatable()) {
608 if (self.phdr_zig_load_re_index == null) {
609 const filesz = options.program_code_size_hint;
610 const off = try self.findFreeSpace(filesz, self.page_size);
611 self.phdr_zig_load_re_index = try self.addPhdr(.{
612 .type = elf.PT_LOAD,
613 .offset = off,
614 .filesz = filesz,
615 .addr = if (ptr_bit_width >= 32) 0x4000000 else 0x4000,
616 .memsz = filesz,
617 .@"align" = self.page_size,
618 .flags = elf.PF_X | elf.PF_R | elf.PF_W,
619 });
620 }
621
622 if (self.phdr_zig_load_ro_index == null) {
623 const alignment = self.page_size;
624 const filesz: u64 = 1024;
625 const off = try self.findFreeSpace(filesz, alignment);
626 self.phdr_zig_load_ro_index = try self.addPhdr(.{
627 .type = elf.PT_LOAD,
628 .offset = off,
629 .filesz = filesz,
630 .addr = if (ptr_bit_width >= 32) 0xc000000 else 0xa000,
631 .memsz = filesz,
632 .@"align" = alignment,
633 .flags = elf.PF_R | elf.PF_W,
634 });
635 }
636
637 if (self.phdr_zig_load_rw_index == null) {
638 const alignment = self.page_size;
639 const filesz: u64 = 1024;
640 const off = try self.findFreeSpace(filesz, alignment);
641 self.phdr_zig_load_rw_index = try self.addPhdr(.{
642 .type = elf.PT_LOAD,
643 .offset = off,
644 .filesz = filesz,
645 .addr = if (ptr_bit_width >= 32) 0x10000000 else 0xc000,
646 .memsz = filesz,
647 .@"align" = alignment,
648 .flags = elf.PF_R | elf.PF_W,
649 });
650 }
651
652 if (self.phdr_zig_load_zerofill_index == null) {
653 const alignment = self.page_size;
654 self.phdr_zig_load_zerofill_index = try self.addPhdr(.{
655 .type = elf.PT_LOAD,
656 .addr = if (ptr_bit_width >= 32) 0x14000000 else 0xf000,
657 .memsz = 1024,
658 .@"align" = alignment,
659 .flags = elf.PF_R | elf.PF_W,
660 });
661 }
662 }
663
664 if (self.zig_text_section_index == null) {
665 self.zig_text_section_index = try self.addSection(.{
666 .name = try self.insertShString(".text.zig"),
667 .type = elf.SHT_PROGBITS,
668 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
669 .addralign = 1,
670 .offset = std.math.maxInt(u64),
671 });
672 const shdr = &self.shdrs.items[self.zig_text_section_index.?];
673 try fillSection(self, shdr, options.program_code_size_hint, self.phdr_zig_load_re_index);
674 if (self.base.isRelocatable()) {
675 const rela_shndx = try self.addRelaShdr(try self.insertShString(".rela.text.zig"), self.zig_text_section_index.?);
676 try self.output_rela_sections.putNoClobber(gpa, self.zig_text_section_index.?, .{
677 .shndx = rela_shndx,
678 });
679 } else {
680 try self.phdr_to_shdr_table.putNoClobber(
681 gpa,
682 self.zig_text_section_index.?,
683 self.phdr_zig_load_re_index.?,
684 );
685 }
686 try self.output_sections.putNoClobber(gpa, self.zig_text_section_index.?, .{});
687 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{});
688 }
689
690 if (self.zig_data_rel_ro_section_index == null) {
691 self.zig_data_rel_ro_section_index = try self.addSection(.{
692 .name = try self.insertShString(".data.rel.ro.zig"),
693 .type = elf.SHT_PROGBITS,
694 .addralign = 1,
695 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
696 .offset = std.math.maxInt(u64),
697 });
698 const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?];
699 try fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index);
700 if (self.base.isRelocatable()) {
701 const rela_shndx = try self.addRelaShdr(
702 try self.insertShString(".rela.data.rel.ro.zig"),
703 self.zig_data_rel_ro_section_index.?,
704 );
705 try self.output_rela_sections.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{
706 .shndx = rela_shndx,
707 });
708 } else {
709 try self.phdr_to_shdr_table.putNoClobber(
710 gpa,
711 self.zig_data_rel_ro_section_index.?,
712 self.phdr_zig_load_ro_index.?,
713 );
714 }
715 try self.output_sections.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{});
716 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{});
717 }
718
719 if (self.zig_data_section_index == null) {
720 self.zig_data_section_index = try self.addSection(.{
721 .name = try self.insertShString(".data.zig"),
722 .type = elf.SHT_PROGBITS,
723 .addralign = ptr_size,
724 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
725 .offset = std.math.maxInt(u64),
726 });
727 const shdr = &self.shdrs.items[self.zig_data_section_index.?];
728 try fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index);
729 if (self.base.isRelocatable()) {
730 const rela_shndx = try self.addRelaShdr(
731 try self.insertShString(".rela.data.zig"),
732 self.zig_data_section_index.?,
733 );
734 try self.output_rela_sections.putNoClobber(gpa, self.zig_data_section_index.?, .{
735 .shndx = rela_shndx,
736 });
737 } else {
738 try self.phdr_to_shdr_table.putNoClobber(
739 gpa,
740 self.zig_data_section_index.?,
741 self.phdr_zig_load_rw_index.?,
742 );
743 }
744 try self.output_sections.putNoClobber(gpa, self.zig_data_section_index.?, .{});
745 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_section_index.?, .{});
746 }
747
748 if (self.zig_bss_section_index == null) {
749 self.zig_bss_section_index = try self.addSection(.{
750 .name = try self.insertShString(".bss.zig"),
751 .type = elf.SHT_NOBITS,
752 .addralign = ptr_size,
753 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
754 .offset = 0,
755 });
756 const shdr = &self.shdrs.items[self.zig_bss_section_index.?];
757 if (self.phdr_zig_load_zerofill_index) |phndx| {
758 const phdr = self.phdrs.items[phndx];
759 shdr.sh_addr = phdr.p_vaddr;
760 shdr.sh_size = phdr.p_memsz;
761 try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_bss_section_index.?, phndx);
762 } else {
763 shdr.sh_size = 1024;
764 }
765 try self.output_sections.putNoClobber(gpa, self.zig_bss_section_index.?, .{});
766 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{});
767 }
768
769 if (zo.dwarf) |*dwarf| {
770 const addSectionSymbol = struct {
771 fn addSectionSymbol(
772 zig_object: *ZigObject,
773 alloc: Allocator,
774 name: [:0]const u8,
775 alignment: Atom.Alignment,
776 shndx: u32,
777 ) !Symbol.Index {
778 const name_off = try zig_object.addString(alloc, name);
779 const index = try zig_object.newSymbolWithAtom(alloc, name_off);
780 const sym = zig_object.symbol(index);
781 const esym = &zig_object.symtab.items(.elf_sym)[sym.esym_index];
782 esym.st_info |= elf.STT_SECTION;
783 const atom_ptr = zig_object.atom(sym.ref.index).?;
784 atom_ptr.alignment = alignment;
785 atom_ptr.output_section_index = shndx;
786 return index;
787 }
788 }.addSectionSymbol;
789
790 if (self.debug_str_section_index == null) {
791 self.debug_str_section_index = try self.addSection(.{
792 .name = try self.insertShString(".debug_str"),
793 .flags = elf.SHF_MERGE | elf.SHF_STRINGS,
794 .entsize = 1,
795 .type = elf.SHT_PROGBITS,
796 .addralign = 1,
797 });
798 zo.debug_str_section_dirty = true;
799 zo.debug_str_index = try addSectionSymbol(zo, gpa, ".debug_str", .@"1", self.debug_str_section_index.?);
800 try self.output_sections.putNoClobber(gpa, self.debug_str_section_index.?, .{});
801 }
802
803 if (self.debug_info_section_index == null) {
804 self.debug_info_section_index = try self.addSection(.{
805 .name = try self.insertShString(".debug_info"),
806 .type = elf.SHT_PROGBITS,
807 .addralign = 1,
808 });
809 zo.debug_info_section_dirty = true;
810 zo.debug_info_index = try addSectionSymbol(zo, gpa, ".debug_info", .@"1", self.debug_info_section_index.?);
811 try self.output_sections.putNoClobber(gpa, self.debug_info_section_index.?, .{});
812 }
813
814 if (self.debug_abbrev_section_index == null) {
815 self.debug_abbrev_section_index = try self.addSection(.{
816 .name = try self.insertShString(".debug_abbrev"),
817 .type = elf.SHT_PROGBITS,
818 .addralign = 1,
819 });
820 zo.debug_abbrev_section_dirty = true;
821 zo.debug_abbrev_index = try addSectionSymbol(zo, gpa, ".debug_abbrev", .@"1", self.debug_abbrev_section_index.?);
822 try self.output_sections.putNoClobber(gpa, self.debug_abbrev_section_index.?, .{});
823 }
824
825 if (self.debug_aranges_section_index == null) {
826 self.debug_aranges_section_index = try self.addSection(.{
827 .name = try self.insertShString(".debug_aranges"),
828 .type = elf.SHT_PROGBITS,
829 .addralign = 16,
830 });
831 zo.debug_aranges_section_dirty = true;
832 zo.debug_aranges_index = try addSectionSymbol(zo, gpa, ".debug_aranges", .@"16", self.debug_aranges_section_index.?);
833 try self.output_sections.putNoClobber(gpa, self.debug_aranges_section_index.?, .{});
834 }
835
836 if (self.debug_line_section_index == null) {
837 self.debug_line_section_index = try self.addSection(.{
838 .name = try self.insertShString(".debug_line"),
839 .type = elf.SHT_PROGBITS,
840 .addralign = 1,
841 });
842 zo.debug_line_section_dirty = true;
843 zo.debug_line_index = try addSectionSymbol(zo, gpa, ".debug_line", .@"1", self.debug_line_section_index.?);
844 try self.output_sections.putNoClobber(gpa, self.debug_line_section_index.?, .{});
845 }
846
847 if (self.debug_line_str_section_index == null) {
848 self.debug_line_str_section_index = try self.addSection(.{
849 .name = try self.insertShString(".debug_line_str"),
850 .flags = elf.SHF_MERGE | elf.SHF_STRINGS,
851 .entsize = 1,
852 .type = elf.SHT_PROGBITS,
853 .addralign = 1,
854 });
855 zo.debug_line_str_section_dirty = true;
856 zo.debug_line_str_index = try addSectionSymbol(zo, gpa, ".debug_line_str", .@"1", self.debug_line_str_section_index.?);
857 try self.output_sections.putNoClobber(gpa, self.debug_line_str_section_index.?, .{});
858 }
859
860 if (self.debug_loclists_section_index == null) {
861 self.debug_loclists_section_index = try self.addSection(.{
862 .name = try self.insertShString(".debug_loclists"),
863 .type = elf.SHT_PROGBITS,
864 .addralign = 1,
865 });
866 zo.debug_loclists_section_dirty = true;
867 zo.debug_loclists_index = try addSectionSymbol(zo, gpa, ".debug_loclists", .@"1", self.debug_loclists_section_index.?);
868 try self.output_sections.putNoClobber(gpa, self.debug_loclists_section_index.?, .{});
869 }
870
871 if (self.debug_rnglists_section_index == null) {
872 self.debug_rnglists_section_index = try self.addSection(.{
873 .name = try self.insertShString(".debug_rnglists"),
874 .type = elf.SHT_PROGBITS,
875 .addralign = 1,
876 });
877 zo.debug_rnglists_section_dirty = true;
878 zo.debug_rnglists_index = try addSectionSymbol(zo, gpa, ".debug_rnglists", .@"1", self.debug_rnglists_section_index.?);
879 try self.output_sections.putNoClobber(gpa, self.debug_rnglists_section_index.?, .{});
880 }
881
882 try dwarf.initMetadata();
883 }
884}
885
886557pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void {
887 const shdr = &self.shdrs.items[shdr_index];
888 const maybe_phdr = if (self.phdr_to_shdr_table.get(shdr_index)) |phndx| &self.phdrs.items[phndx] else null;
558 const slice = self.sections.slice();
559 const shdr = &slice.items(.shdr)[shdr_index];
560 assert(shdr.sh_flags & elf.SHF_ALLOC != 0);
561 const phndx = slice.items(.phndx)[shdr_index];
562 const maybe_phdr = if (phndx) |ndx| &self.phdrs.items[ndx] else null;
563
889564 log.debug("allocated size {x} of {s}, needed size {x}", .{
890565 self.allocatedSize(shdr.sh_offset),
891566 self.getShString(shdr.sh_name),
......@@ -924,9 +599,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void {
924599 const mem_capacity = self.allocatedVirtualSize(phdr.p_vaddr);
925600 if (needed_size > mem_capacity) {
926601 var err = try self.base.addErrorWithNotes(2);
927 try err.addMsg("fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{
928 self.phdr_to_shdr_table.get(shdr_index).?,
929 });
602 try err.addMsg("fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{phndx.?});
930603 try err.addNote("TODO: emit relocations to memory locations in self-hosted backends", .{});
931604 try err.addNote("as a workaround, try increasing pre-allocated virtual memory of each segment", .{});
932605 }
......@@ -944,7 +617,8 @@ pub fn growNonAllocSection(
944617 min_alignment: u32,
945618 requires_file_copy: bool,
946619) !void {
947 const shdr = &self.shdrs.items[shdr_index];
620 const shdr = &self.sections.items(.shdr)[shdr_index];
621 assert(shdr.sh_flags & elf.SHF_ALLOC == 0);
948622
949623 const allocated_size = self.allocatedSize(shdr.sh_offset);
950624 if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {
......@@ -1328,7 +1002,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
13281002 const atom_ptr = zo.atom(atom_index) orelse continue;
13291003 if (!atom_ptr.alive) continue;
13301004 const out_shndx = atom_ptr.output_section_index;
1331 const shdr = &self.shdrs.items[out_shndx];
1005 const shdr = &self.sections.items(.shdr)[out_shndx];
13321006 if (shdr.sh_type == elf.SHT_NOBITS) continue;
13331007 const code = try zo.codeAlloc(self, atom_index);
13341008 defer gpa.free(code);
......@@ -2692,7 +2366,7 @@ pub fn writeShdrTable(self: *Elf) !void {
26922366 };
26932367
26942368 const shoff = self.shdr_table_offset orelse 0;
2695 const needed_size = self.shdrs.items.len * shsize;
2369 const needed_size = self.sections.items(.shdr).len * shsize;
26962370
26972371 if (needed_size > self.allocatedSize(shoff)) {
26982372 self.shdr_table_offset = null;
......@@ -2706,12 +2380,12 @@ pub fn writeShdrTable(self: *Elf) !void {
27062380
27072381 switch (self.ptr_width) {
27082382 .p32 => {
2709 const buf = try gpa.alloc(elf.Elf32_Shdr, self.shdrs.items.len);
2383 const buf = try gpa.alloc(elf.Elf32_Shdr, self.sections.items(.shdr).len);
27102384 defer gpa.free(buf);
27112385
27122386 for (buf, 0..) |*shdr, i| {
2713 assert(self.shdrs.items[i].sh_offset != math.maxInt(u64));
2714 shdr.* = shdrTo32(self.shdrs.items[i]);
2387 assert(self.sections.items(.shdr)[i].sh_offset != math.maxInt(u64));
2388 shdr.* = shdrTo32(self.sections.items(.shdr)[i]);
27152389 if (foreign_endian) {
27162390 mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);
27172391 }
......@@ -2719,12 +2393,12 @@ pub fn writeShdrTable(self: *Elf) !void {
27192393 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
27202394 },
27212395 .p64 => {
2722 const buf = try gpa.alloc(elf.Elf64_Shdr, self.shdrs.items.len);
2396 const buf = try gpa.alloc(elf.Elf64_Shdr, self.sections.items(.shdr).len);
27232397 defer gpa.free(buf);
27242398
27252399 for (buf, 0..) |*shdr, i| {
2726 assert(self.shdrs.items[i].sh_offset != math.maxInt(u64));
2727 shdr.* = self.shdrs.items[i];
2400 assert(self.sections.items(.shdr)[i].sh_offset != math.maxInt(u64));
2401 shdr.* = self.sections.items(.shdr)[i];
27282402 if (foreign_endian) {
27292403 mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);
27302404 }
......@@ -2892,7 +2566,7 @@ pub fn writeElfHeader(self: *Elf) !void {
28922566 mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian);
28932567 index += 2;
28942568
2895 const e_shnum = @as(u16, @intCast(self.shdrs.items.len));
2569 const e_shnum = @as(u16, @intCast(self.sections.items(.shdr).len));
28962570 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);
28972571 index += 2;
28982572
......@@ -3051,7 +2725,7 @@ pub fn updateMergeSectionSizes(self: *Elf) !void {
30512725 msec.updateSize();
30522726 }
30532727 for (self.merge_sections.items) |*msec| {
3054 const shdr = &self.shdrs.items[msec.output_section_index];
2728 const shdr = &self.sections.items(.shdr)[msec.output_section_index];
30552729 const offset = msec.alignment.forward(shdr.sh_size);
30562730 const padding = offset - shdr.sh_size;
30572731 msec.value = @intCast(offset);
......@@ -3067,7 +2741,7 @@ pub fn writeMergeSections(self: *Elf) !void {
30672741 defer buffer.deinit();
30682742
30692743 for (self.merge_sections.items) |*msec| {
3070 const shdr = self.shdrs.items[msec.output_section_index];
2744 const shdr = self.sections.items(.shdr)[msec.output_section_index];
30712745 const fileoff = math.cast(usize, msec.value + shdr.sh_offset) orelse return error.Overflow;
30722746 const size = math.cast(usize, msec.size) orelse return error.Overflow;
30732747 try buffer.ensureTotalCapacity(size);
......@@ -3355,7 +3029,7 @@ fn initSpecialPhdrs(self: *Elf) !void {
33553029 .@"align" = 1,
33563030 });
33573031
3358 const has_tls = for (self.shdrs.items) |shdr| {
3032 const has_tls = for (self.sections.items(.shdr)) |shdr| {
33593033 if (shdr.sh_flags & elf.SHF_TLS != 0) break true;
33603034 } else false;
33613035 if (has_tls) {
......@@ -3384,6 +3058,7 @@ fn initSpecialPhdrs(self: *Elf) !void {
33843058/// we are about to sort.
33853059fn sortInitFini(self: *Elf) !void {
33863060 const gpa = self.base.comp.gpa;
3061 const slice = self.sections.slice();
33873062
33883063 const Entry = struct {
33893064 priority: i32,
......@@ -3397,7 +3072,7 @@ fn sortInitFini(self: *Elf) !void {
33973072 }
33983073 };
33993074
3400 for (self.shdrs.items, 0..) |shdr, shndx| {
3075 for (slice.items(.shdr), slice.items(.atom_list)) |shdr, *atom_list| {
34013076 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
34023077
34033078 var is_init_fini = false;
......@@ -3414,8 +3089,6 @@ fn sortInitFini(self: *Elf) !void {
34143089 }
34153090
34163091 if (!is_init_fini and !is_ctor_dtor) continue;
3417
3418 const atom_list = self.output_sections.getPtr(@intCast(shndx)).?;
34193092 if (atom_list.items.len == 0) continue;
34203093
34213094 var entries = std.ArrayList(Entry).init(gpa);
......@@ -3483,7 +3156,7 @@ fn setVersionSymtab(self: *Elf) !void {
34833156
34843157 if (self.verneed_section_index) |shndx| {
34853158 try self.verneed.generate(self);
3486 const shdr = &self.shdrs.items[shndx];
3159 const shdr = &self.sections.items(.shdr)[shndx];
34873160 shdr.sh_info = @as(u32, @intCast(self.verneed.verneed.items.len));
34883161 }
34893162}
......@@ -3563,16 +3236,15 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
35633236 }
35643237 }
35653238
3566 {
3567 var it = self.phdr_to_shdr_table.iterator();
3568 while (it.next()) |entry| {
3569 entry.value_ptr.* = backlinks[entry.value_ptr.*];
3239 for (self.sections.items(.phndx)) |*maybe_phndx| {
3240 if (maybe_phndx.*) |*index| {
3241 index.* = backlinks[index.*];
35703242 }
35713243 }
35723244}
35733245
35743246fn shdrRank(self: *Elf, shndx: u32) u8 {
3575 const shdr = self.shdrs.items[shndx];
3247 const shdr = self.sections.items(.shdr)[shndx];
35763248 const name = self.getShString(shdr.sh_name);
35773249 const flags = shdr.sh_flags;
35783250
......@@ -3629,9 +3301,9 @@ pub fn sortShdrs(self: *Elf) !void {
36293301 };
36303302
36313303 const gpa = self.base.comp.gpa;
3632 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.shdrs.items.len);
3304 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.sections.items(.shdr).len);
36333305 defer entries.deinit();
3634 for (0..self.shdrs.items.len) |shndx| {
3306 for (0..self.sections.items(.shdr).len) |shndx| {
36353307 entries.appendAssumeCapacity(.{ .shndx = @intCast(shndx) });
36363308 }
36373309
......@@ -3643,20 +3315,18 @@ pub fn sortShdrs(self: *Elf) !void {
36433315 backlinks[entry.shndx] = @intCast(i);
36443316 }
36453317
3646 const slice = try self.shdrs.toOwnedSlice(gpa);
3647 defer gpa.free(slice);
3318 var slice = self.sections.toOwnedSlice();
3319 defer slice.deinit(gpa);
36483320
3649 try self.shdrs.ensureTotalCapacityPrecise(gpa, slice.len);
3321 try self.sections.ensureTotalCapacity(gpa, slice.len);
36503322 for (entries.items) |sorted| {
3651 self.shdrs.appendAssumeCapacity(slice[sorted.shndx]);
3323 self.sections.appendAssumeCapacity(slice.get(sorted.shndx));
36523324 }
36533325
3654 try self.resetShdrIndexes(backlinks);
3326 self.resetShdrIndexes(backlinks);
36553327}
36563328
3657fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void {
3658 const gpa = self.base.comp.gpa;
3659
3329fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
36603330 for (&[_]*?u32{
36613331 &self.eh_frame_section_index,
36623332 &self.eh_frame_rela_section_index,
......@@ -3697,142 +3367,88 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void {
36973367 }
36983368 }
36993369
3370 for (self.merge_sections.items) |*msec| {
3371 msec.output_section_index = backlinks[msec.output_section_index];
3372 }
3373
3374 for (self.sections.items(.shdr)) |*shdr| {
3375 if (shdr.sh_type != elf.SHT_RELA) continue;
3376 // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections
3377 // to point at symtab
3378 // shdr.sh_link = backlinks[shdr.sh_link];
3379 shdr.sh_link = self.symtab_section_index.?;
3380 shdr.sh_info = backlinks[shdr.sh_info];
3381 }
3382
3383 if (self.zigObjectPtr()) |zo| {
3384 for (zo.atoms_indexes.items) |atom_index| {
3385 const atom_ptr = zo.atom(atom_index) orelse continue;
3386 atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];
3387 }
3388 if (zo.dwarf) |*dwarf| dwarf.reloadSectionMetadata();
3389 }
3390
3391 for (self.comdat_group_sections.items) |*cg| {
3392 cg.shndx = backlinks[cg.shndx];
3393 }
3394
37003395 if (self.symtab_section_index) |index| {
3701 const shdr = &self.shdrs.items[index];
3396 const shdr = &self.sections.items(.shdr)[index];
37023397 shdr.sh_link = self.strtab_section_index.?;
37033398 }
37043399
37053400 if (self.dynamic_section_index) |index| {
3706 const shdr = &self.shdrs.items[index];
3401 const shdr = &self.sections.items(.shdr)[index];
37073402 shdr.sh_link = self.dynstrtab_section_index.?;
37083403 }
37093404
37103405 if (self.dynsymtab_section_index) |index| {
3711 const shdr = &self.shdrs.items[index];
3406 const shdr = &self.sections.items(.shdr)[index];
37123407 shdr.sh_link = self.dynstrtab_section_index.?;
37133408 }
37143409
37153410 if (self.hash_section_index) |index| {
3716 const shdr = &self.shdrs.items[index];
3411 const shdr = &self.sections.items(.shdr)[index];
37173412 shdr.sh_link = self.dynsymtab_section_index.?;
37183413 }
37193414
37203415 if (self.gnu_hash_section_index) |index| {
3721 const shdr = &self.shdrs.items[index];
3416 const shdr = &self.sections.items(.shdr)[index];
37223417 shdr.sh_link = self.dynsymtab_section_index.?;
37233418 }
37243419
37253420 if (self.versym_section_index) |index| {
3726 const shdr = &self.shdrs.items[index];
3421 const shdr = &self.sections.items(.shdr)[index];
37273422 shdr.sh_link = self.dynsymtab_section_index.?;
37283423 }
37293424
37303425 if (self.verneed_section_index) |index| {
3731 const shdr = &self.shdrs.items[index];
3426 const shdr = &self.sections.items(.shdr)[index];
37323427 shdr.sh_link = self.dynstrtab_section_index.?;
37333428 }
37343429
37353430 if (self.rela_dyn_section_index) |index| {
3736 const shdr = &self.shdrs.items[index];
3431 const shdr = &self.sections.items(.shdr)[index];
37373432 shdr.sh_link = self.dynsymtab_section_index orelse 0;
37383433 }
37393434
37403435 if (self.rela_plt_section_index) |index| {
3741 const shdr = &self.shdrs.items[index];
3436 const shdr = &self.sections.items(.shdr)[index];
37423437 shdr.sh_link = self.dynsymtab_section_index.?;
37433438 shdr.sh_info = self.plt_section_index.?;
37443439 }
37453440
37463441 if (self.eh_frame_rela_section_index) |index| {
3747 const shdr = &self.shdrs.items[index];
3442 const shdr = &self.sections.items(.shdr)[index];
37483443 shdr.sh_link = self.symtab_section_index.?;
37493444 shdr.sh_info = self.eh_frame_section_index.?;
37503445 }
3751
3752 {
3753 var output_sections = try self.output_sections.clone(gpa);
3754 defer output_sections.deinit(gpa);
3755
3756 self.output_sections.clearRetainingCapacity();
3757
3758 var it = output_sections.iterator();
3759 while (it.next()) |entry| {
3760 const shndx = entry.key_ptr.*;
3761 const meta = entry.value_ptr.*;
3762 self.output_sections.putAssumeCapacityNoClobber(backlinks[shndx], meta);
3763 }
3764 }
3765
3766 for (self.merge_sections.items) |*msec| {
3767 msec.output_section_index = backlinks[msec.output_section_index];
3768 }
3769
3770 {
3771 var output_rela_sections = try self.output_rela_sections.clone(gpa);
3772 defer output_rela_sections.deinit(gpa);
3773
3774 self.output_rela_sections.clearRetainingCapacity();
3775
3776 var it = output_rela_sections.iterator();
3777 while (it.next()) |entry| {
3778 const shndx = entry.key_ptr.*;
3779 var meta = entry.value_ptr.*;
3780 meta.shndx = backlinks[meta.shndx];
3781 self.output_rela_sections.putAssumeCapacityNoClobber(backlinks[shndx], meta);
3782 }
3783 }
3784
3785 {
3786 var last_atom_and_free_list_table = try self.last_atom_and_free_list_table.clone(gpa);
3787 defer last_atom_and_free_list_table.deinit(gpa);
3788
3789 self.last_atom_and_free_list_table.clearRetainingCapacity();
3790
3791 var it = last_atom_and_free_list_table.iterator();
3792 while (it.next()) |entry| {
3793 const shndx = entry.key_ptr.*;
3794 const meta = entry.value_ptr.*;
3795 self.last_atom_and_free_list_table.putAssumeCapacityNoClobber(backlinks[shndx], meta);
3796 }
3797 }
3798
3799 {
3800 var phdr_to_shdr_table = try self.phdr_to_shdr_table.clone(gpa);
3801 defer phdr_to_shdr_table.deinit(gpa);
3802
3803 self.phdr_to_shdr_table.clearRetainingCapacity();
3804
3805 var it = phdr_to_shdr_table.iterator();
3806 while (it.next()) |entry| {
3807 const shndx = entry.key_ptr.*;
3808 const phndx = entry.value_ptr.*;
3809 self.phdr_to_shdr_table.putAssumeCapacityNoClobber(backlinks[shndx], phndx);
3810 }
3811 }
3812
3813 if (self.zigObjectPtr()) |zo| {
3814 for (zo.atoms_indexes.items) |atom_index| {
3815 const atom_ptr = zo.atom(atom_index) orelse continue;
3816 atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];
3817 }
3818 if (zo.dwarf) |*dwarf| dwarf.reloadSectionMetadata();
3819 }
3820
3821 for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, sec| {
3822 const shdr = &self.shdrs.items[sec.shndx];
3823 shdr.sh_link = self.symtab_section_index.?;
3824 shdr.sh_info = shndx;
3825 }
3826
3827 for (self.comdat_group_sections.items) |*cg| {
3828 cg.shndx = backlinks[cg.shndx];
3829 }
38303446}
38313447
38323448fn updateSectionSizes(self: *Elf) !void {
38333449 const target = self.base.comp.root_mod.resolved_target.result;
3834 for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {
3835 const shdr = &self.shdrs.items[shndx];
3450 const slice = self.sections.slice();
3451 for (slice.items(.shdr), slice.items(.atom_list)) |*shdr, atom_list| {
38363452 if (atom_list.items.len == 0) continue;
38373453 if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;
38383454 for (atom_list.items) |ref| {
......@@ -3847,38 +3463,38 @@ fn updateSectionSizes(self: *Elf) !void {
38473463 }
38483464
38493465 if (self.requiresThunks()) {
3850 for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {
3851 const shdr = self.shdrs.items[shndx];
3466 for (slice.items(.shdr), slice.items(.atom_list), 0..) |*shdr, atom_list, shndx| {
38523467 if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue;
38533468 if (atom_list.items.len == 0) continue;
38543469
38553470 // Create jump/branch range extenders if needed.
3856 try thunks.createThunks(shndx, self);
3471 try thunks.createThunks(shdr, @intCast(shndx), self);
38573472 }
38583473 }
38593474
3475 const shdrs = slice.items(.shdr);
38603476 if (self.eh_frame_section_index) |index| {
3861 self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self);
3477 shdrs[index].sh_size = try eh_frame.calcEhFrameSize(self);
38623478 }
38633479
38643480 if (self.eh_frame_hdr_section_index) |index| {
3865 self.shdrs.items[index].sh_size = eh_frame.calcEhFrameHdrSize(self);
3481 shdrs[index].sh_size = eh_frame.calcEhFrameHdrSize(self);
38663482 }
38673483
38683484 if (self.got_section_index) |index| {
3869 self.shdrs.items[index].sh_size = self.got.size(self);
3485 shdrs[index].sh_size = self.got.size(self);
38703486 }
38713487
38723488 if (self.plt_section_index) |index| {
3873 self.shdrs.items[index].sh_size = self.plt.size(self);
3489 shdrs[index].sh_size = self.plt.size(self);
38743490 }
38753491
38763492 if (self.got_plt_section_index) |index| {
3877 self.shdrs.items[index].sh_size = self.got_plt.size(self);
3493 shdrs[index].sh_size = self.got_plt.size(self);
38783494 }
38793495
38803496 if (self.plt_got_section_index) |index| {
3881 self.shdrs.items[index].sh_size = self.plt_got.size(self);
3497 shdrs[index].sh_size = self.plt_got.size(self);
38823498 }
38833499
38843500 if (self.rela_dyn_section_index) |shndx| {
......@@ -3889,11 +3505,11 @@ fn updateSectionSizes(self: *Elf) !void {
38893505 for (self.objects.items) |index| {
38903506 num += self.file(index).?.object.num_dynrelocs;
38913507 }
3892 self.shdrs.items[shndx].sh_size = num * @sizeOf(elf.Elf64_Rela);
3508 shdrs[shndx].sh_size = num * @sizeOf(elf.Elf64_Rela);
38933509 }
38943510
38953511 if (self.rela_plt_section_index) |index| {
3896 self.shdrs.items[index].sh_size = self.plt.numRela() * @sizeOf(elf.Elf64_Rela);
3512 shdrs[index].sh_size = self.plt.numRela() * @sizeOf(elf.Elf64_Rela);
38973513 }
38983514
38993515 if (self.copy_rel_section_index) |index| {
......@@ -3901,44 +3517,45 @@ fn updateSectionSizes(self: *Elf) !void {
39013517 }
39023518
39033519 if (self.interp_section_index) |index| {
3904 self.shdrs.items[index].sh_size = target.dynamic_linker.get().?.len + 1;
3520 shdrs[index].sh_size = target.dynamic_linker.get().?.len + 1;
39053521 }
39063522
39073523 if (self.hash_section_index) |index| {
3908 self.shdrs.items[index].sh_size = self.hash.size();
3524 shdrs[index].sh_size = self.hash.size();
39093525 }
39103526
39113527 if (self.gnu_hash_section_index) |index| {
3912 self.shdrs.items[index].sh_size = self.gnu_hash.size();
3528 shdrs[index].sh_size = self.gnu_hash.size();
39133529 }
39143530
39153531 if (self.dynamic_section_index) |index| {
3916 self.shdrs.items[index].sh_size = self.dynamic.size(self);
3532 shdrs[index].sh_size = self.dynamic.size(self);
39173533 }
39183534
39193535 if (self.dynsymtab_section_index) |index| {
3920 self.shdrs.items[index].sh_size = self.dynsym.size();
3536 shdrs[index].sh_size = self.dynsym.size();
39213537 }
39223538
39233539 if (self.dynstrtab_section_index) |index| {
3924 self.shdrs.items[index].sh_size = self.dynstrtab.items.len;
3540 shdrs[index].sh_size = self.dynstrtab.items.len;
39253541 }
39263542
39273543 if (self.versym_section_index) |index| {
3928 self.shdrs.items[index].sh_size = self.versym.items.len * @sizeOf(elf.Elf64_Versym);
3544 shdrs[index].sh_size = self.versym.items.len * @sizeOf(elf.Elf64_Versym);
39293545 }
39303546
39313547 if (self.verneed_section_index) |index| {
3932 self.shdrs.items[index].sh_size = self.verneed.size();
3548 shdrs[index].sh_size = self.verneed.size();
39333549 }
39343550
39353551 try self.updateSymtabSize();
39363552 self.updateShStrtabSize();
39373553}
39383554
3555// FIXME:JK this is very much obsolete, remove!
39393556pub fn updateShStrtabSize(self: *Elf) void {
39403557 if (self.shstrtab_section_index) |index| {
3941 self.shdrs.items[index].sh_size = self.shstrtab.items.len;
3558 self.sections.items(.shdr)[index].sh_size = self.shstrtab.items.len;
39423559 }
39433560}
39443561
......@@ -3971,7 +3588,7 @@ fn getMaxNumberOfPhdrs() u64 {
39713588/// We permit a maximum of 3**2 number of segments.
39723589fn calcNumberOfSegments(self: *Elf) usize {
39733590 var covers: [9]bool = [_]bool{false} ** 9;
3974 for (self.shdrs.items, 0..) |shdr, shndx| {
3591 for (self.sections.items(.shdr), 0..) |shdr, shndx| {
39753592 if (shdr.sh_type == elf.SHT_NULL) continue;
39763593 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
39773594 if (self.isZigSection(@intCast(shndx))) continue;
......@@ -4042,8 +3659,9 @@ pub fn allocateAllocSections(self: *Elf) !void {
40423659 }
40433660 };
40443661
3662 const slice = self.sections.slice();
40453663 var alignment = Align{};
4046 for (self.shdrs.items, 0..) |shdr, i| {
3664 for (slice.items(.shdr), 0..) |shdr, i| {
40473665 if (shdr.sh_type == elf.SHT_NULL) continue;
40483666 if (shdr.sh_flags & elf.SHF_TLS == 0) continue;
40493667 if (alignment.first_tls_index == null) alignment.first_tls_index = i;
......@@ -4068,7 +3686,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
40683686 cover.deinit();
40693687 };
40703688
4071 for (self.shdrs.items, 0..) |shdr, shndx| {
3689 for (slice.items(.shdr), 0..) |shdr, shndx| {
40723690 if (shdr.sh_type == elf.SHT_NULL) continue;
40733691 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
40743692 if (self.isZigSection(@intCast(shndx))) continue;
......@@ -4089,7 +3707,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
40893707
40903708 var @"align": u64 = self.page_size;
40913709 for (cover.items) |shndx| {
4092 const shdr = self.shdrs.items[shndx];
3710 const shdr = slice.items(.shdr)[shndx];
40933711 if (shdr.sh_type == elf.SHT_NOBITS and shdr.sh_flags & elf.SHF_TLS != 0) continue;
40943712 @"align" = @max(@"align", shdr.sh_addralign);
40953713 }
......@@ -4101,7 +3719,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
41013719 var i: usize = 0;
41023720 while (i < cover.items.len) : (i += 1) {
41033721 const shndx = cover.items[i];
4104 const shdr = &self.shdrs.items[shndx];
3722 const shdr = &slice.items(.shdr)[shndx];
41053723 if (shdr.sh_type == elf.SHT_NOBITS and shdr.sh_flags & elf.SHF_TLS != 0) {
41063724 // .tbss is a little special as it's used only by the loader meaning it doesn't
41073725 // need to be actually mmap'ed at runtime. We still need to correctly increment
......@@ -4117,11 +3735,11 @@ pub fn allocateAllocSections(self: *Elf) !void {
41173735 // ...
41183736 var tbss_addr = addr;
41193737 while (i < cover.items.len and
4120 self.shdrs.items[cover.items[i]].sh_type == elf.SHT_NOBITS and
4121 self.shdrs.items[cover.items[i]].sh_flags & elf.SHF_TLS != 0) : (i += 1)
3738 slice.items(.shdr)[cover.items[i]].sh_type == elf.SHT_NOBITS and
3739 slice.items(.shdr)[cover.items[i]].sh_flags & elf.SHF_TLS != 0) : (i += 1)
41223740 {
41233741 const tbss_shndx = cover.items[i];
4124 const tbss_shdr = &self.shdrs.items[tbss_shndx];
3742 const tbss_shdr = &slice.items(.shdr)[tbss_shndx];
41253743 tbss_addr = alignment.@"align"(tbss_shndx, tbss_shdr.sh_addralign, tbss_addr);
41263744 tbss_shdr.sh_addr = tbss_addr;
41273745 tbss_addr += tbss_shdr.sh_size;
......@@ -4140,7 +3758,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
41403758 addr += shdr.sh_size;
41413759 }
41423760
4143 const first = self.shdrs.items[cover.items[0]];
3761 const first = slice.items(.shdr)[cover.items[0]];
41443762 var off = try self.findFreeSpace(filesz, @"align");
41453763 const phndx = try self.addPhdr(.{
41463764 .type = elf.PT_LOAD,
......@@ -4153,7 +3771,8 @@ pub fn allocateAllocSections(self: *Elf) !void {
41533771 });
41543772
41553773 for (cover.items) |shndx| {
4156 const shdr = &self.shdrs.items[shndx];
3774 const shdr = &slice.items(.shdr)[shndx];
3775 slice.items(.phndx)[shndx] = phndx;
41573776 if (shdr.sh_type == elf.SHT_NOBITS) {
41583777 shdr.sh_offset = 0;
41593778 continue;
......@@ -4161,7 +3780,6 @@ pub fn allocateAllocSections(self: *Elf) !void {
41613780 off = alignment.@"align"(shndx, shdr.sh_addralign, off);
41623781 shdr.sh_offset = off;
41633782 off += shdr.sh_size;
4164 try self.phdr_to_shdr_table.putNoClobber(gpa, shndx, phndx);
41653783 }
41663784
41673785 addr = mem.alignForward(u64, addr, self.page_size);
......@@ -4170,7 +3788,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
41703788
41713789/// Allocates non-alloc sections (debug info, symtabs, etc.).
41723790pub fn allocateNonAllocSections(self: *Elf) !void {
4173 for (self.shdrs.items, 0..) |*shdr, shndx| {
3791 for (self.sections.items(.shdr), 0..) |*shdr, shndx| {
41743792 if (shdr.sh_type == elf.SHT_NULL) continue;
41753793 if (shdr.sh_flags & elf.SHF_ALLOC != 0) continue;
41763794 const needed_size = shdr.sh_size;
......@@ -4215,13 +3833,15 @@ pub fn allocateNonAllocSections(self: *Elf) !void {
42153833}
42163834
42173835fn allocateSpecialPhdrs(self: *Elf) void {
3836 const slice = self.sections.slice();
3837
42183838 for (&[_]struct { ?u16, ?u32 }{
42193839 .{ self.phdr_interp_index, self.interp_section_index },
42203840 .{ self.phdr_dynamic_index, self.dynamic_section_index },
42213841 .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index },
42223842 }) |pair| {
42233843 if (pair[0]) |index| {
4224 const shdr = self.shdrs.items[pair[1].?];
3844 const shdr = slice.items(.shdr)[pair[1].?];
42253845 const phdr = &self.phdrs.items[index];
42263846 phdr.p_align = shdr.sh_addralign;
42273847 phdr.p_offset = shdr.sh_offset;
......@@ -4236,11 +3856,11 @@ fn allocateSpecialPhdrs(self: *Elf) void {
42363856 // We assume TLS sections are laid out contiguously and that there is
42373857 // a single TLS segment.
42383858 if (self.phdr_tls_index) |index| {
4239 const slice = self.shdrs.items;
3859 const shdrs = slice.items(.shdr);
42403860 const phdr = &self.phdrs.items[index];
42413861 var shndx: u32 = 0;
4242 while (shndx < slice.len) {
4243 const shdr = slice[shndx];
3862 while (shndx < shdrs.len) {
3863 const shdr = shdrs[shndx];
42443864 if (shdr.sh_flags & elf.SHF_TLS == 0) {
42453865 shndx += 1;
42463866 continue;
......@@ -4256,8 +3876,8 @@ fn allocateSpecialPhdrs(self: *Elf) void {
42563876 }
42573877 phdr.p_memsz = shdr.sh_addr + shdr.sh_size - phdr.p_vaddr;
42583878
4259 while (shndx < slice.len) : (shndx += 1) {
4260 const next = slice[shndx];
3879 while (shndx < shdrs.len) : (shndx += 1) {
3880 const next = shdrs[shndx];
42613881 if (next.sh_flags & elf.SHF_TLS == 0) break;
42623882 phdr.p_align = @max(phdr.p_align, next.sh_addralign);
42633883 if (next.sh_type != elf.SHT_NOBITS) {
......@@ -4281,13 +3901,10 @@ fn writeAtoms(self: *Elf) !void {
42813901 }
42823902
42833903 var has_reloc_errors = false;
4284
4285 // TODO iterate over `output_sections` directly
4286 for (self.shdrs.items, 0..) |shdr, shndx| {
3904 const slice = self.sections.slice();
3905 for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| {
42873906 if (shdr.sh_type == elf.SHT_NULL) continue;
42883907 if (shdr.sh_type == elf.SHT_NOBITS) continue;
4289
4290 const atom_list = self.output_sections.get(@intCast(shndx)) orelse continue;
42913908 if (atom_list.items.len == 0) continue;
42923909
42933910 log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)});
......@@ -4366,7 +3983,7 @@ fn writeAtoms(self: *Elf) !void {
43663983 for (self.thunks.items) |th| {
43673984 const thunk_size = th.size(self);
43683985 try buffer.ensureUnusedCapacity(thunk_size);
4369 const shdr = self.shdrs.items[th.output_section_index];
3986 const shdr = slice.items(.shdr)[th.output_section_index];
43703987 const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset;
43713988 try th.write(self, buffer.writer());
43723989 assert(buffer.items.len == thunk_size);
......@@ -4396,15 +4013,10 @@ pub fn updateSymtabSize(self: *Elf) !void {
43964013 if (self.linker_defined_index) |index| files.appendAssumeCapacity(index);
43974014
43984015 // Section symbols
4399 for (self.output_sections.keys()) |_| {
4400 nlocals += 1;
4401 }
4402 if (self.eh_frame_section_index) |_| {
4403 nlocals += 1;
4404 }
4016 nlocals += @intCast(self.sections.slice().len);
44054017
44064018 if (self.requiresThunks()) for (self.thunks.items) |*th| {
4407 th.output_symtab_ctx.ilocal = nlocals + 1;
4019 th.output_symtab_ctx.ilocal = nlocals;
44084020 th.calcSymtabSize(self);
44094021 nlocals += th.output_symtab_ctx.nlocals;
44104022 strsize += th.output_symtab_ctx.strsize;
......@@ -4415,8 +4027,8 @@ pub fn updateSymtabSize(self: *Elf) !void {
44154027 const ctx = switch (file_ptr) {
44164028 inline else => |x| &x.output_symtab_ctx,
44174029 };
4418 ctx.ilocal = nlocals + 1;
4419 ctx.iglobal = nglobals + 1;
4030 ctx.ilocal = nlocals;
4031 ctx.iglobal = nglobals;
44204032 try file_ptr.updateSymtabSize(self);
44214033 nlocals += ctx.nlocals;
44224034 nglobals += ctx.nglobals;
......@@ -4424,21 +4036,21 @@ pub fn updateSymtabSize(self: *Elf) !void {
44244036 }
44254037
44264038 if (self.got_section_index) |_| {
4427 self.got.output_symtab_ctx.ilocal = nlocals + 1;
4039 self.got.output_symtab_ctx.ilocal = nlocals;
44284040 self.got.updateSymtabSize(self);
44294041 nlocals += self.got.output_symtab_ctx.nlocals;
44304042 strsize += self.got.output_symtab_ctx.strsize;
44314043 }
44324044
44334045 if (self.plt_section_index) |_| {
4434 self.plt.output_symtab_ctx.ilocal = nlocals + 1;
4046 self.plt.output_symtab_ctx.ilocal = nlocals;
44354047 self.plt.updateSymtabSize(self);
44364048 nlocals += self.plt.output_symtab_ctx.nlocals;
44374049 strsize += self.plt.output_symtab_ctx.strsize;
44384050 }
44394051
44404052 if (self.plt_got_section_index) |_| {
4441 self.plt_got.output_symtab_ctx.ilocal = nlocals + 1;
4053 self.plt_got.output_symtab_ctx.ilocal = nlocals;
44424054 self.plt_got.updateSymtabSize(self);
44434055 nlocals += self.plt_got.output_symtab_ctx.nlocals;
44444056 strsize += self.plt_got.output_symtab_ctx.strsize;
......@@ -4452,24 +4064,26 @@ pub fn updateSymtabSize(self: *Elf) !void {
44524064 ctx.iglobal += nlocals;
44534065 }
44544066
4455 const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?];
4456 symtab_shdr.sh_info = nlocals + 1;
4067 const slice = self.sections.slice();
4068 const symtab_shdr = &slice.items(.shdr)[self.symtab_section_index.?];
4069 symtab_shdr.sh_info = nlocals;
44574070 symtab_shdr.sh_link = self.strtab_section_index.?;
44584071
44594072 const sym_size: u64 = switch (self.ptr_width) {
44604073 .p32 => @sizeOf(elf.Elf32_Sym),
44614074 .p64 => @sizeOf(elf.Elf64_Sym),
44624075 };
4463 const needed_size = (nlocals + nglobals + 1) * sym_size;
4076 const needed_size = (nlocals + nglobals) * sym_size;
44644077 symtab_shdr.sh_size = needed_size;
44654078
4466 const strtab = &self.shdrs.items[self.strtab_section_index.?];
4079 const strtab = &slice.items(.shdr)[self.strtab_section_index.?];
44674080 strtab.sh_size = strsize + 1;
44684081}
44694082
44704083fn writeSyntheticSections(self: *Elf) !void {
4471 const target = self.base.comp.root_mod.resolved_target.result;
44724084 const gpa = self.base.comp.gpa;
4085 const target = self.getTarget();
4086 const slice = self.sections.slice();
44734087
44744088 if (self.interp_section_index) |shndx| {
44754089 var buffer: [256]u8 = undefined;
......@@ -4477,18 +4091,18 @@ fn writeSyntheticSections(self: *Elf) !void {
44774091 @memcpy(buffer[0..interp.len], interp);
44784092 buffer[interp.len] = 0;
44794093 const contents = buffer[0 .. interp.len + 1];
4480 const shdr = self.shdrs.items[shndx];
4094 const shdr = slice.items(.shdr)[shndx];
44814095 assert(shdr.sh_size == contents.len);
44824096 try self.base.file.?.pwriteAll(contents, shdr.sh_offset);
44834097 }
44844098
44854099 if (self.hash_section_index) |shndx| {
4486 const shdr = self.shdrs.items[shndx];
4100 const shdr = slice.items(.shdr)[shndx];
44874101 try self.base.file.?.pwriteAll(self.hash.buffer.items, shdr.sh_offset);
44884102 }
44894103
44904104 if (self.gnu_hash_section_index) |shndx| {
4491 const shdr = self.shdrs.items[shndx];
4105 const shdr = slice.items(.shdr)[shndx];
44924106 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.gnu_hash.size());
44934107 defer buffer.deinit();
44944108 try self.gnu_hash.write(self, buffer.writer());
......@@ -4496,12 +4110,12 @@ fn writeSyntheticSections(self: *Elf) !void {
44964110 }
44974111
44984112 if (self.versym_section_index) |shndx| {
4499 const shdr = self.shdrs.items[shndx];
4113 const shdr = slice.items(.shdr)[shndx];
45004114 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.versym.items), shdr.sh_offset);
45014115 }
45024116
45034117 if (self.verneed_section_index) |shndx| {
4504 const shdr = self.shdrs.items[shndx];
4118 const shdr = slice.items(.shdr)[shndx];
45054119 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.verneed.size());
45064120 defer buffer.deinit();
45074121 try self.verneed.write(buffer.writer());
......@@ -4509,7 +4123,7 @@ fn writeSyntheticSections(self: *Elf) !void {
45094123 }
45104124
45114125 if (self.dynamic_section_index) |shndx| {
4512 const shdr = self.shdrs.items[shndx];
4126 const shdr = slice.items(.shdr)[shndx];
45134127 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynamic.size(self));
45144128 defer buffer.deinit();
45154129 try self.dynamic.write(self, buffer.writer());
......@@ -4517,7 +4131,7 @@ fn writeSyntheticSections(self: *Elf) !void {
45174131 }
45184132
45194133 if (self.dynsymtab_section_index) |shndx| {
4520 const shdr = self.shdrs.items[shndx];
4134 const shdr = slice.items(.shdr)[shndx];
45214135 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynsym.size());
45224136 defer buffer.deinit();
45234137 try self.dynsym.write(self, buffer.writer());
......@@ -4525,12 +4139,12 @@ fn writeSyntheticSections(self: *Elf) !void {
45254139 }
45264140
45274141 if (self.dynstrtab_section_index) |shndx| {
4528 const shdr = self.shdrs.items[shndx];
4142 const shdr = slice.items(.shdr)[shndx];
45294143 try self.base.file.?.pwriteAll(self.dynstrtab.items, shdr.sh_offset);
45304144 }
45314145
45324146 if (self.eh_frame_section_index) |shndx| {
4533 const shdr = self.shdrs.items[shndx];
4147 const shdr = slice.items(.shdr)[shndx];
45344148 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
45354149 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
45364150 defer buffer.deinit();
......@@ -4539,7 +4153,7 @@ fn writeSyntheticSections(self: *Elf) !void {
45394153 }
45404154
45414155 if (self.eh_frame_hdr_section_index) |shndx| {
4542 const shdr = self.shdrs.items[shndx];
4156 const shdr = slice.items(.shdr)[shndx];
45434157 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
45444158 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
45454159 defer buffer.deinit();
......@@ -4548,7 +4162,7 @@ fn writeSyntheticSections(self: *Elf) !void {
45484162 }
45494163
45504164 if (self.got_section_index) |index| {
4551 const shdr = self.shdrs.items[index];
4165 const shdr = slice.items(.shdr)[index];
45524166 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got.size(self));
45534167 defer buffer.deinit();
45544168 try self.got.write(self, buffer.writer());
......@@ -4556,7 +4170,7 @@ fn writeSyntheticSections(self: *Elf) !void {
45564170 }
45574171
45584172 if (self.rela_dyn_section_index) |shndx| {
4559 const shdr = self.shdrs.items[shndx];
4173 const shdr = slice.items(.shdr)[shndx];
45604174 try self.got.addRela(self);
45614175 try self.copy_rel.addRela(self);
45624176 self.sortRelaDyn();
......@@ -4564,7 +4178,7 @@ fn writeSyntheticSections(self: *Elf) !void {
45644178 }
45654179
45664180 if (self.plt_section_index) |shndx| {
4567 const shdr = self.shdrs.items[shndx];
4181 const shdr = slice.items(.shdr)[shndx];
45684182 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt.size(self));
45694183 defer buffer.deinit();
45704184 try self.plt.write(self, buffer.writer());
......@@ -4572,7 +4186,7 @@ fn writeSyntheticSections(self: *Elf) !void {
45724186 }
45734187
45744188 if (self.got_plt_section_index) |shndx| {
4575 const shdr = self.shdrs.items[shndx];
4189 const shdr = slice.items(.shdr)[shndx];
45764190 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got_plt.size(self));
45774191 defer buffer.deinit();
45784192 try self.got_plt.write(self, buffer.writer());
......@@ -4580,7 +4194,7 @@ fn writeSyntheticSections(self: *Elf) !void {
45804194 }
45814195
45824196 if (self.plt_got_section_index) |shndx| {
4583 const shdr = self.shdrs.items[shndx];
4197 const shdr = slice.items(.shdr)[shndx];
45844198 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size(self));
45854199 defer buffer.deinit();
45864200 try self.plt_got.write(self, buffer.writer());
......@@ -4588,7 +4202,7 @@ fn writeSyntheticSections(self: *Elf) !void {
45884202 }
45894203
45904204 if (self.rela_plt_section_index) |shndx| {
4591 const shdr = self.shdrs.items[shndx];
4205 const shdr = slice.items(.shdr)[shndx];
45924206 try self.plt.addRela(self);
45934207 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_plt.items), shdr.sh_offset);
45944208 }
......@@ -4597,19 +4211,21 @@ fn writeSyntheticSections(self: *Elf) !void {
45974211 try self.writeShStrtab();
45984212}
45994213
4214// FIXME:JK again, why is this needed?
46004215pub fn writeShStrtab(self: *Elf) !void {
46014216 if (self.shstrtab_section_index) |index| {
4602 const shdr = self.shdrs.items[index];
4217 const shdr = self.sections.items(.shdr)[index];
46034218 log.debug("writing .shstrtab from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size });
46044219 try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset);
46054220 }
46064221}
46074222
46084223pub fn writeSymtab(self: *Elf) !void {
4609 const target = self.base.comp.root_mod.resolved_target.result;
46104224 const gpa = self.base.comp.gpa;
4611 const symtab_shdr = self.shdrs.items[self.symtab_section_index.?];
4612 const strtab_shdr = self.shdrs.items[self.strtab_section_index.?];
4225 const target = self.getTarget();
4226 const slice = self.sections.slice();
4227 const symtab_shdr = slice.items(.shdr)[self.symtab_section_index.?];
4228 const strtab_shdr = slice.items(.shdr)[self.strtab_section_index.?];
46134229 const sym_size: u64 = switch (self.ptr_width) {
46144230 .p32 => @sizeOf(elf.Elf32_Sym),
46154231 .p64 => @sizeOf(elf.Elf64_Sym),
......@@ -4630,7 +4246,17 @@ pub fn writeSymtab(self: *Elf) !void {
46304246 const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;
46314247 try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size);
46324248
4633 self.writeSectionSymbols();
4249 for (slice.items(.shdr), 0..) |shdr, shndx| {
4250 const out_sym = &self.symtab.items[shndx];
4251 out_sym.* = .{
4252 .st_name = 0,
4253 .st_value = shdr.sh_addr,
4254 .st_info = if (shdr.sh_type == elf.SHT_NULL) elf.STT_NOTYPE else elf.STT_SECTION,
4255 .st_shndx = @intCast(shndx),
4256 .st_size = 0,
4257 .st_other = 0,
4258 };
4259 }
46344260
46354261 if (self.requiresThunks()) for (self.thunks.items) |th| {
46364262 th.writeSymtab(self);
......@@ -4696,44 +4322,6 @@ pub fn writeSymtab(self: *Elf) !void {
46964322 try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);
46974323}
46984324
4699fn writeSectionSymbols(self: *Elf) void {
4700 var ilocal: u32 = 1;
4701 for (self.output_sections.keys()) |shndx| {
4702 const shdr = self.shdrs.items[shndx];
4703 const out_sym = &self.symtab.items[ilocal];
4704 out_sym.* = .{
4705 .st_name = 0,
4706 .st_value = shdr.sh_addr,
4707 .st_info = elf.STT_SECTION,
4708 .st_shndx = @intCast(shndx),
4709 .st_size = 0,
4710 .st_other = 0,
4711 };
4712 ilocal += 1;
4713 }
4714
4715 if (self.eh_frame_section_index) |shndx| {
4716 const shdr = self.shdrs.items[shndx];
4717 const out_sym = &self.symtab.items[ilocal];
4718 out_sym.* = .{
4719 .st_name = 0,
4720 .st_value = shdr.sh_addr,
4721 .st_info = elf.STT_SECTION,
4722 .st_shndx = @intCast(shndx),
4723 .st_size = 0,
4724 .st_other = 0,
4725 };
4726 ilocal += 1;
4727 }
4728}
4729
4730pub fn sectionSymbolOutputSymtabIndex(self: Elf, shndx: u32) u32 {
4731 if (self.eh_frame_section_index) |index| {
4732 if (index == shndx) return @intCast(self.output_sections.keys().len + 1);
4733 }
4734 return @intCast(self.output_sections.getIndex(shndx).? + 1);
4735}
4736
47374325/// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF.
47384326pub fn ptrWidthBytes(self: Elf) u8 {
47394327 return switch (self.ptr_width) {
......@@ -4745,8 +4333,7 @@ pub fn ptrWidthBytes(self: Elf) u8 {
47454333/// Does not necessarily match `ptrWidthBytes` for example can be 2 bytes
47464334/// in a 32-bit ELF file.
47474335pub fn archPtrWidthBytes(self: Elf) u8 {
4748 const target = self.base.comp.root_mod.resolved_target.result;
4749 return @intCast(@divExact(target.ptrBitWidth(), 8));
4336 return @intCast(@divExact(self.getTarget().ptrBitWidth(), 8));
47504337}
47514338
47524339fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr {
......@@ -5069,7 +4656,7 @@ pub fn isDebugSection(self: Elf, shndx: u32) bool {
50694656 return false;
50704657}
50714658
5072fn addPhdr(self: *Elf, opts: struct {
4659pub fn addPhdr(self: *Elf, opts: struct {
50734660 type: u32 = 0,
50744661 flags: u32 = 0,
50754662 @"align": u64 = 0,
......@@ -5126,25 +4713,26 @@ pub const AddSectionOpts = struct {
51264713
51274714pub fn addSection(self: *Elf, opts: AddSectionOpts) !u32 {
51284715 const gpa = self.base.comp.gpa;
5129 const index: u32 = @intCast(self.shdrs.items.len);
5130 const shdr = try self.shdrs.addOne(gpa);
5131 shdr.* = .{
5132 .sh_name = opts.name,
5133 .sh_type = opts.type,
5134 .sh_flags = opts.flags,
5135 .sh_addr = 0,
5136 .sh_offset = opts.offset,
5137 .sh_size = 0,
5138 .sh_link = opts.link,
5139 .sh_info = opts.info,
5140 .sh_addralign = opts.addralign,
5141 .sh_entsize = opts.entsize,
5142 };
4716 const index: u32 = @intCast(try self.sections.addOne(gpa));
4717 self.sections.set(index, .{
4718 .shdr = .{
4719 .sh_name = opts.name,
4720 .sh_type = opts.type,
4721 .sh_flags = opts.flags,
4722 .sh_addr = 0,
4723 .sh_offset = opts.offset,
4724 .sh_size = 0,
4725 .sh_link = opts.link,
4726 .sh_info = opts.info,
4727 .sh_addralign = opts.addralign,
4728 .sh_entsize = opts.entsize,
4729 },
4730 });
51434731 return index;
51444732}
51454733
51464734pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u32 {
5147 for (self.shdrs.items, 0..) |*shdr, i| {
4735 for (self.sections.items(.shdr), 0..) |*shdr, i| {
51484736 const this_name = self.getShString(shdr.sh_name);
51494737 if (mem.eql(u8, this_name, name)) return @intCast(i);
51504738 } else return null;
......@@ -5322,7 +4910,7 @@ pub fn gotAddress(self: *Elf) i64 {
53224910 break :blk self.got_plt_section_index.?;
53234911 break :blk if (self.got_section_index) |shndx| shndx else null;
53244912 };
5325 return if (shndx) |index| @intCast(self.shdrs.items[index].sh_addr) else 0;
4913 return if (shndx) |index| @intCast(self.sections.items(.shdr)[index].sh_addr) else 0;
53264914}
53274915
53284916pub fn tpAddress(self: *Elf) i64 {
......@@ -5676,16 +5264,16 @@ fn fmtDumpState(
56765264 }
56775265
56785266 try writer.writeAll("\nOutput shdrs\n");
5679 for (self.shdrs.items, 0..) |shdr, shndx| {
5267 for (self.sections.items(.shdr), self.sections.items(.phndx), 0..) |shdr, phndx, shndx| {
56805268 try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{
56815269 shndx,
5682 self.phdr_to_shdr_table.get(@intCast(shndx)),
5270 phndx,
56835271 self.fmtShdr(shdr),
56845272 });
56855273 }
56865274 try writer.writeAll("\nOutput phdrs\n");
56875275 for (self.phdrs.items, 0..) |phdr, phndx| {
5688 try writer.print(" phdr{d} : {}\n", .{ phndx, self.fmtPhdr(phdr) });
5276 try writer.print(" phdr({d}) : {}\n", .{ phndx, self.fmtPhdr(phdr) });
56895277 }
56905278}
56915279
......@@ -5746,7 +5334,7 @@ fn requiresThunks(self: Elf) bool {
57465334/// so that we reserve enough space for the program header table up-front.
57475335/// Bump these numbers when adding or deleting a Zig specific pre-allocated segment, or adding
57485336/// more special-purpose program headers.
5749const number_of_zig_segments = 5;
5337pub const number_of_zig_segments = 4;
57505338const max_number_of_object_segments = 9;
57515339const max_number_of_special_phdrs = 5;
57525340
......@@ -5814,8 +5402,8 @@ pub const SystemLib = struct {
58145402};
58155403
58165404pub const Ref = struct {
5817 index: u32,
5818 file: u32,
5405 index: u32 = 0,
5406 file: u32 = 0,
58195407
58205408 pub fn eql(ref: Ref, other: Ref) bool {
58215409 return ref.index == other.index and ref.file == other.file;
......@@ -5923,9 +5511,18 @@ pub const SymbolResolver = struct {
59235511 pub const Index = u32;
59245512};
59255513
5926const LastAtomAndFreeList = struct {
5514const Section = struct {
5515 /// Section header.
5516 shdr: elf.Elf64_Shdr,
5517
5518 /// Assigned program header index if any.
5519 phndx: ?u32 = null,
5520
5521 /// List of atoms contributing to this section.
5522 atom_list: std.ArrayListUnmanaged(Ref) = .{},
5523
59275524 /// Index of the last allocated atom in this section.
5928 last_atom_index: Atom.Index = 0,
5525 last_atom: Ref = .{ .index = 0, .file = 0 },
59295526
59305527 /// A list of atoms that have surplus capacity. This list can have false
59315528 /// positives, as functions grow and shrink over time, only sometimes being added
......@@ -5942,15 +5539,8 @@ const LastAtomAndFreeList = struct {
59425539 /// overcapacity can be negative. A simple way to have negative overcapacity is to
59435540 /// allocate a fresh text block, which will have ideal capacity, and then grow it
59445541 /// by 1 byte. It will then have -1 overcapacity.
5945 free_list: std.ArrayListUnmanaged(Atom.Index) = .{},
5946};
5947const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u32, LastAtomAndFreeList);
5948
5949const RelaSection = struct {
5950 shndx: u32,
5951 atom_list: std.ArrayListUnmanaged(Ref) = .{},
5542 free_list: std.ArrayListUnmanaged(Ref) = .{},
59525543};
5953const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection);
59545544
59555545fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {
59565546 return switch (cpu_arch) {
src/link/Elf/Atom.zig+94-81
......@@ -25,10 +25,9 @@ relocs_section_index: u32 = 0,
2525/// Index of this atom in the linker's atoms table.
2626atom_index: Index = 0,
2727
28/// Points to the previous and next neighbors, based on the `text_offset`.
29/// This can be used to find, for example, the capacity of this `TextBlock`.
30prev_index: Index = 0,
31next_index: Index = 0,
28/// Points to the previous and next neighbors.
29prev_atom_ref: Elf.Ref = .{},
30next_atom_ref: Elf.Ref = .{},
3231
3332/// Specifies whether this atom is alive or has been garbage collected.
3433alive: bool = true,
......@@ -48,10 +47,22 @@ pub fn name(self: Atom, elf_file: *Elf) [:0]const u8 {
4847}
4948
5049pub fn address(self: Atom, elf_file: *Elf) i64 {
51 const shdr = elf_file.shdrs.items[self.output_section_index];
50 const shdr = elf_file.sections.items(.shdr)[self.output_section_index];
5251 return @as(i64, @intCast(shdr.sh_addr)) + self.value;
5352}
5453
54pub fn ref(self: Atom) Elf.Ref {
55 return .{ .index = self.atom_index, .file = self.file_index };
56}
57
58pub fn prevAtom(self: Atom, elf_file: *Elf) ?*Atom {
59 return elf_file.atom(self.prev_atom_ref);
60}
61
62pub fn nextAtom(self: Atom, elf_file: *Elf) ?*Atom {
63 return elf_file.atom(self.next_atom_ref);
64}
65
5566pub fn debugTombstoneValue(self: Atom, target: Symbol, elf_file: *Elf) ?u64 {
5667 if (target.mergeSubsection(elf_file)) |msub| {
5768 if (msub.alive) return null;
......@@ -95,18 +106,16 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 {
95106/// File offset relocation happens transparently, so it is not included in
96107/// this calculation.
97108pub fn capacity(self: Atom, elf_file: *Elf) u64 {
98 const zo = elf_file.zigObjectPtr().?;
99 const next_addr = if (zo.atom(self.next_index)) |next|
100 next.address(elf_file)
109 const next_addr = if (self.nextAtom(elf_file)) |next_atom|
110 next_atom.address(elf_file)
101111 else
102112 std.math.maxInt(u32);
103113 return @intCast(next_addr - self.address(elf_file));
104114}
105115
106116pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
107 const zo = elf_file.zigObjectPtr().?;
108117 // No need to keep a free list node for the last block.
109 const next = zo.atom(self.next_index) orelse return false;
118 const next = self.nextAtom(elf_file) orelse return false;
110119 const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file));
111120 const ideal_cap = Elf.padToIdeal(self.size);
112121 if (cap <= ideal_cap) return false;
......@@ -115,11 +124,10 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
115124}
116125
117126pub fn allocate(self: *Atom, elf_file: *Elf) !void {
118 const zo = elf_file.zigObjectPtr().?;
119 const shdr = &elf_file.shdrs.items[self.output_section_index];
120 const meta = elf_file.last_atom_and_free_list_table.getPtr(self.output_section_index).?;
121 const free_list = &meta.free_list;
122 const last_atom_index = &meta.last_atom_index;
127 const slice = elf_file.sections.slice();
128 const shdr = &slice.items(.shdr)[self.output_section_index];
129 const free_list = &slice.items(.free_list)[self.output_section_index];
130 const last_atom_ref = &slice.items(.last_atom)[self.output_section_index];
123131 const new_atom_ideal_capacity = Elf.padToIdeal(self.size);
124132
125133 // We use these to indicate our intention to update metadata, placing the new atom,
......@@ -127,7 +135,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
127135 // It would be simpler to do it inside the for loop below, but that would cause a
128136 // problem if an error was returned later in the function. So this action
129137 // is actually carried out at the end of the function, when errors are no longer possible.
130 var atom_placement: ?Atom.Index = null;
138 var atom_placement: ?Elf.Ref = null;
131139 var free_list_removal: ?usize = null;
132140
133141 // First we look for an appropriately sized free list node.
......@@ -135,8 +143,8 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
135143 self.value = blk: {
136144 var i: usize = if (elf_file.base.child_pid == null) 0 else free_list.items.len;
137145 while (i < free_list.items.len) {
138 const big_atom_index = free_list.items[i];
139 const big_atom = zo.atom(big_atom_index).?;
146 const big_atom_ref = free_list.items[i];
147 const big_atom = elf_file.atom(big_atom_ref).?;
140148 // We now have a pointer to a live atom that has too much capacity.
141149 // Is it enough that we could fit this new atom?
142150 const cap = big_atom.capacity(elf_file);
......@@ -163,50 +171,52 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
163171 const keep_free_list_node = remaining_capacity >= Elf.min_text_capacity;
164172
165173 // Set up the metadata to be updated, after errors are no longer possible.
166 atom_placement = big_atom_index;
174 atom_placement = big_atom_ref;
167175 if (!keep_free_list_node) {
168176 free_list_removal = i;
169177 }
170178 break :blk @intCast(new_start_vaddr);
171 } else if (zo.atom(last_atom_index.*)) |last| {
172 const ideal_capacity = Elf.padToIdeal(last.size);
173 const ideal_capacity_end_vaddr = @as(u64, @intCast(last.value)) + ideal_capacity;
179 } else if (elf_file.atom(last_atom_ref.*)) |last_atom| {
180 const ideal_capacity = Elf.padToIdeal(last_atom.size);
181 const ideal_capacity_end_vaddr = @as(u64, @intCast(last_atom.value)) + ideal_capacity;
174182 const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr);
175183 // Set up the metadata to be updated, after errors are no longer possible.
176 atom_placement = last.atom_index;
184 atom_placement = last_atom.ref();
177185 break :blk @intCast(new_start_vaddr);
178186 } else {
179187 break :blk 0;
180188 }
181189 };
182190
183 log.debug("allocated atom({d}) : '{s}' at 0x{x} to 0x{x}", .{
184 self.atom_index,
191 log.debug("allocated atom({}) : '{s}' at 0x{x} to 0x{x}", .{
192 self.ref(),
185193 self.name(elf_file),
186194 self.address(elf_file),
187195 self.address(elf_file) + @as(i64, @intCast(self.size)),
188196 });
189197
190 const expand_section = if (atom_placement) |placement_index|
191 zo.atom(placement_index).?.next_index == 0
198 const expand_section = if (atom_placement) |placement_ref|
199 elf_file.atom(placement_ref).?.nextAtom(elf_file) == null
192200 else
193201 true;
194202 if (expand_section) {
195203 const needed_size: u64 = @intCast(self.value + @as(i64, @intCast(self.size)));
196204 try elf_file.growAllocSection(self.output_section_index, needed_size);
197 last_atom_index.* = self.atom_index;
198
199 const zig_object = elf_file.zigObjectPtr().?;
200 if (zig_object.dwarf) |_| {
201 // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address
202 // range of the compilation unit. When we expand the text section, this range changes,
203 // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty.
204 zig_object.debug_info_section_dirty = true;
205 // This becomes dirty for the same reason. We could potentially make this more
206 // fine-grained with the addition of support for more compilation units. It is planned to
207 // model each package as a different compilation unit.
208 zig_object.debug_aranges_section_dirty = true;
209 zig_object.debug_rnglists_section_dirty = true;
205 last_atom_ref.* = self.ref();
206
207 switch (self.file(elf_file).?) {
208 .zig_object => |zo| if (zo.dwarf) |_| {
209 // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address
210 // range of the compilation unit. When we expand the text section, this range changes,
211 // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty.
212 zo.debug_info_section_dirty = true;
213 // This becomes dirty for the same reason. We could potentially make this more
214 // fine-grained with the addition of support for more compilation units. It is planned to
215 // model each package as a different compilation unit.
216 zo.debug_aranges_section_dirty = true;
217 zo.debug_rnglists_section_dirty = true;
218 },
219 else => {},
210220 }
211221 }
212222 shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnits().?);
......@@ -214,21 +224,21 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
214224 // This function can also reallocate an atom.
215225 // In this case we need to "unplug" it from its previous location before
216226 // plugging it in to its new location.
217 if (zo.atom(self.prev_index)) |prev| {
218 prev.next_index = self.next_index;
227 if (self.prevAtom(elf_file)) |prev| {
228 prev.next_atom_ref = self.next_atom_ref;
219229 }
220 if (zo.atom(self.next_index)) |next| {
221 next.prev_index = self.prev_index;
230 if (self.nextAtom(elf_file)) |next| {
231 next.prev_atom_ref = self.prev_atom_ref;
222232 }
223233
224 if (atom_placement) |big_atom_index| {
225 const big_atom = zo.atom(big_atom_index).?;
226 self.prev_index = big_atom_index;
227 self.next_index = big_atom.next_index;
228 big_atom.next_index = self.atom_index;
234 if (atom_placement) |big_atom_ref| {
235 const big_atom = elf_file.atom(big_atom_ref).?;
236 self.prev_atom_ref = big_atom_ref;
237 self.next_atom_ref = big_atom.next_atom_ref;
238 big_atom.next_atom_ref = self.ref();
229239 } else {
230 self.prev_index = 0;
231 self.next_index = 0;
240 self.prev_atom_ref = .{ .index = 0, .file = 0 };
241 self.next_atom_ref = .{ .index = 0, .file = 0 };
232242 }
233243 if (free_list_removal) |i| {
234244 _ = free_list.swapRemove(i);
......@@ -248,64 +258,70 @@ pub fn grow(self: *Atom, elf_file: *Elf) !void {
248258}
249259
250260pub fn free(self: *Atom, elf_file: *Elf) void {
251 log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.name(elf_file) });
261 log.debug("freeAtom atom({}) ({s})", .{ self.ref(), self.name(elf_file) });
252262
253 const zo = elf_file.zigObjectPtr().?;
254263 const comp = elf_file.base.comp;
255264 const gpa = comp.gpa;
256265 const shndx = self.output_section_index;
257 const meta = elf_file.last_atom_and_free_list_table.getPtr(shndx).?;
258 const free_list = &meta.free_list;
259 const last_atom_index = &meta.last_atom_index;
266 const slice = elf_file.sections.slice();
267 const free_list = &slice.items(.free_list)[shndx];
268 const last_atom_ref = &slice.items(.last_atom)[shndx];
260269 var already_have_free_list_node = false;
261270 {
262271 var i: usize = 0;
263272 // TODO turn free_list into a hash map
264273 while (i < free_list.items.len) {
265 if (free_list.items[i] == self.atom_index) {
274 if (free_list.items[i].eql(self.ref())) {
266275 _ = free_list.swapRemove(i);
267276 continue;
268277 }
269 if (free_list.items[i] == self.prev_index) {
270 already_have_free_list_node = true;
278 if (self.prevAtom(elf_file)) |prev_atom| {
279 if (free_list.items[i].eql(prev_atom.ref())) {
280 already_have_free_list_node = true;
281 }
271282 }
272283 i += 1;
273284 }
274285 }
275286
276 if (zo.atom(last_atom_index.*)) |last_atom| {
277 if (last_atom.atom_index == self.atom_index) {
278 if (zo.atom(self.prev_index)) |_| {
287 if (elf_file.atom(last_atom_ref.*)) |last_atom| {
288 if (last_atom.ref().eql(self.ref())) {
289 if (self.prevAtom(elf_file)) |prev_atom| {
279290 // TODO shrink the section size here
280 last_atom_index.* = self.prev_index;
291 last_atom_ref.* = prev_atom.ref();
281292 } else {
282 last_atom_index.* = 0;
293 last_atom_ref.* = .{};
283294 }
284295 }
285296 }
286297
287 if (zo.atom(self.prev_index)) |prev| {
288 prev.next_index = self.next_index;
289 if (!already_have_free_list_node and prev.*.freeListEligible(elf_file)) {
298 if (self.prevAtom(elf_file)) |prev_atom| {
299 prev_atom.next_atom_ref = self.next_atom_ref;
300 if (!already_have_free_list_node and prev_atom.*.freeListEligible(elf_file)) {
290301 // The free list is heuristics, it doesn't have to be perfect, so we can
291302 // ignore the OOM here.
292 free_list.append(gpa, prev.atom_index) catch {};
303 free_list.append(gpa, prev_atom.ref()) catch {};
293304 }
294305 } else {
295 self.prev_index = 0;
306 self.prev_atom_ref = .{};
296307 }
297308
298 if (zo.atom(self.next_index)) |next| {
299 next.prev_index = self.prev_index;
309 if (self.nextAtom(elf_file)) |next_atom| {
310 next_atom.prev_atom_ref = self.prev_atom_ref;
300311 } else {
301 self.next_index = 0;
312 self.next_atom_ref = .{};
302313 }
303314
304 // TODO create relocs free list
305 self.freeRelocs(zo);
306 // TODO figure out how to free input section mappind in ZigModule
307 // const zig_object = elf_file.zigObjectPtr().?
308 // assert(zig_object.atoms.swapRemove(self.atom_index));
315 switch (self.file(elf_file).?) {
316 .zig_object => |zo| {
317 // TODO create relocs free list
318 self.freeRelocs(zo);
319 // TODO figure out how to free input section mappind in ZigModule
320 // const zig_object = elf_file.zigObjectPtr().?
321 // assert(zig_object.atoms.swapRemove(self.atom_index));
322 },
323 else => {},
324 }
309325 self.* = .{};
310326}
311327
......@@ -336,10 +352,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
336352 switch (target.type(elf_file)) {
337353 elf.STT_SECTION => {
338354 r_addend += @intCast(target.address(.{}, elf_file));
339 r_sym = if (target.outputShndx(elf_file)) |osec|
340 elf_file.sectionSymbolOutputSymtabIndex(osec)
341 else
342 0;
355 r_sym = target.outputShndx(elf_file) orelse 0;
343356 },
344357 else => {
345358 r_sym = target.outputSymtabIndex(elf_file) orelse 0;
src/link/Elf/LinkerDefined.zig+17-15
......@@ -129,9 +129,10 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
129129
130130pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
131131 const gpa = elf_file.base.comp.gpa;
132 const slice = elf_file.sections.slice();
132133
133134 var nsyms: usize = 0;
134 for (elf_file.shdrs.items) |shdr| {
135 for (slice.items(.shdr)) |shdr| {
135136 if (elf_file.getStartStopBasename(shdr)) |_| {
136137 nsyms += 2; // __start_, __stop_
137138 }
......@@ -143,7 +144,7 @@ pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
143144 try self.symbols_extra.ensureUnusedCapacity(gpa, nsyms * @sizeOf(Symbol.Extra));
144145 try self.symbols_resolver.ensureUnusedCapacity(gpa, nsyms);
145146
146 for (elf_file.shdrs.items) |shdr| {
147 for (slice.items(.shdr)) |shdr| {
147148 if (elf_file.getStartStopBasename(shdr)) |name| {
148149 const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
149150 defer gpa.free(start_name);
......@@ -193,6 +194,7 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
193194pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
194195 const comp = elf_file.base.comp;
195196 const link_mode = comp.config.link_mode;
197 const shdrs = elf_file.sections.items(.shdr);
196198
197199 const allocSymbol = struct {
198200 fn allocSymbol(ld: *LinkerDefined, index: Symbol.Index, value: u64, osec: u32, ef: *Elf) void {
......@@ -204,7 +206,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
204206
205207 // _DYNAMIC
206208 if (elf_file.dynamic_section_index) |shndx| {
207 const shdr = &elf_file.shdrs.items[shndx];
209 const shdr = shdrs[shndx];
208210 allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file);
209211 }
210212
......@@ -213,21 +215,21 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
213215
214216 // __init_array_start, __init_array_end
215217 if (elf_file.sectionByName(".init_array")) |shndx| {
216 const shdr = &elf_file.shdrs.items[shndx];
218 const shdr = shdrs[shndx];
217219 allocSymbol(self, self.init_array_start_index.?, shdr.sh_addr, shndx, elf_file);
218220 allocSymbol(self, self.init_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
219221 }
220222
221223 // __fini_array_start, __fini_array_end
222224 if (elf_file.sectionByName(".fini_array")) |shndx| {
223 const shdr = &elf_file.shdrs.items[shndx];
225 const shdr = shdrs[shndx];
224226 allocSymbol(self, self.fini_array_start_index.?, shdr.sh_addr, shndx, elf_file);
225227 allocSymbol(self, self.fini_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
226228 }
227229
228230 // __preinit_array_start, __preinit_array_end
229231 if (elf_file.sectionByName(".preinit_array")) |shndx| {
230 const shdr = &elf_file.shdrs.items[shndx];
232 const shdr = shdrs[shndx];
231233 allocSymbol(self, self.preinit_array_start_index.?, shdr.sh_addr, shndx, elf_file);
232234 allocSymbol(self, self.preinit_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
233235 }
......@@ -235,38 +237,38 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
235237 // _GLOBAL_OFFSET_TABLE_
236238 if (elf_file.getTarget().cpu.arch == .x86_64) {
237239 if (elf_file.got_plt_section_index) |shndx| {
238 const shdr = elf_file.shdrs.items[shndx];
240 const shdr = shdrs[shndx];
239241 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
240242 }
241243 } else {
242244 if (elf_file.got_section_index) |shndx| {
243 const shdr = elf_file.shdrs.items[shndx];
245 const shdr = shdrs[shndx];
244246 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
245247 }
246248 }
247249
248250 // _PROCEDURE_LINKAGE_TABLE_
249251 if (elf_file.plt_section_index) |shndx| {
250 const shdr = &elf_file.shdrs.items[shndx];
252 const shdr = shdrs[shndx];
251253 allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file);
252254 }
253255
254256 // __dso_handle
255257 if (self.dso_handle_index) |index| {
256 const shdr = &elf_file.shdrs.items[1];
258 const shdr = shdrs[1];
257259 allocSymbol(self, index, shdr.sh_addr, 0, elf_file);
258260 }
259261
260262 // __GNU_EH_FRAME_HDR
261263 if (elf_file.eh_frame_hdr_section_index) |shndx| {
262 const shdr = &elf_file.shdrs.items[shndx];
264 const shdr = shdrs[shndx];
263265 allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file);
264266 }
265267
266268 // __rela_iplt_start, __rela_iplt_end
267269 if (elf_file.rela_dyn_section_index) |shndx| blk: {
268270 if (link_mode != .static or comp.config.pie) break :blk;
269 const shdr = &elf_file.shdrs.items[shndx];
271 const shdr = shdrs[shndx];
270272 const end_addr = shdr.sh_addr + shdr.sh_size;
271273 const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);
272274 allocSymbol(self, self.rela_iplt_start_index.?, start_addr, shndx, elf_file);
......@@ -277,7 +279,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
277279 {
278280 var value: u64 = 0;
279281 var osec: u32 = 0;
280 for (elf_file.shdrs.items, 0..) |shdr, shndx| {
282 for (shdrs, 0..) |shdr, shndx| {
281283 if (shdr.sh_flags & elf.SHF_ALLOC != 0) {
282284 value = shdr.sh_addr + shdr.sh_size;
283285 osec = @intCast(shndx);
......@@ -289,7 +291,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
289291 // __global_pointer$
290292 if (self.global_pointer_index) |index| {
291293 const value, const osec = if (elf_file.sectionByName(".sdata")) |shndx| .{
292 elf_file.shdrs.items[shndx].sh_addr + 0x800,
294 shdrs[shndx].sh_addr + 0x800,
293295 shndx,
294296 } else .{ 0, 0 };
295297 allocSymbol(self, index, value, osec, elf_file);
......@@ -305,7 +307,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
305307 const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1], elf_file);
306308 const stop = elf_file.symbol(stop_ref).?;
307309 const shndx = elf_file.sectionByName(name["__start_".len..]).?;
308 const shdr = &elf_file.shdrs.items[shndx];
310 const shdr = shdrs[shndx];
309311 start.value = @intCast(shdr.sh_addr);
310312 start.output_section_index = shndx;
311313 stop.value = @intCast(shdr.sh_addr + shdr.sh_size);
src/link/Elf/Object.zig+9-11
......@@ -998,9 +998,8 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
998998
999999 const comp = elf_file.base.comp;
10001000 const gpa = comp.gpa;
1001 const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index);
1002 if (!gop.found_existing) gop.value_ptr.* = .{};
1003 try gop.value_ptr.append(gpa, .{ .index = atom_index, .file = self.index });
1001 const atom_list = &elf_file.sections.items(.atom_list)[atom_ptr.output_section_index];
1002 try atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
10041003 }
10051004}
10061005
......@@ -1011,7 +1010,8 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void {
10111010 const shndx = atom_ptr.relocsShndx() orelse continue;
10121011 const shdr = self.shdrs.items[shndx];
10131012 const out_shndx = try self.initOutputSection(elf_file, shdr);
1014 const out_shdr = &elf_file.shdrs.items[out_shndx];
1013 const out_shdr = &elf_file.sections.items(.shdr)[out_shndx];
1014 out_shdr.sh_type = elf.SHT_RELA;
10151015 out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela);
10161016 out_shdr.sh_entsize = @sizeOf(elf.Elf64_Rela);
10171017 out_shdr.sh_flags |= elf.SHF_INFO_LINK;
......@@ -1027,15 +1027,13 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
10271027 const shdr = self.shdrs.items[shndx];
10281028 break :blk self.initOutputSection(elf_file, shdr) catch unreachable;
10291029 };
1030 const shdr = &elf_file.shdrs.items[shndx];
1030 const slice = elf_file.sections.slice();
1031 const shdr = &slice.items(.shdr)[shndx];
10311032 shdr.sh_info = atom_ptr.output_section_index;
10321033 shdr.sh_link = elf_file.symtab_section_index.?;
1033
1034 const comp = elf_file.base.comp;
1035 const gpa = comp.gpa;
1036 const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom_ptr.output_section_index);
1037 if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = shndx };
1038 try gop.value_ptr.atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
1034 const gpa = elf_file.base.comp.gpa;
1035 const atom_list = &elf_file.sections.items(.atom_list)[shndx];
1036 try atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
10391037 }
10401038}
10411039
src/link/Elf/Symbol.zig+7-7
......@@ -11,7 +11,7 @@ file_index: File.Index = 0,
1111
1212/// Reference to Atom or merge subsection containing this symbol if any.
1313/// Use `atom` or `mergeSubsection` to get the pointer to the atom.
14ref: Elf.Ref = .{ .index = 0, .file = 0 },
14ref: Elf.Ref = .{},
1515
1616/// Assigned output section index for this symbol.
1717output_section_index: u32 = 0,
......@@ -126,7 +126,7 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool
126126 const sym_name = symbol.name(elf_file);
127127 const sh_addr, const sh_size = blk: {
128128 const shndx = elf_file.eh_frame_section_index orelse break :blk .{ 0, 0 };
129 const shdr = elf_file.shdrs.items[shndx];
129 const shdr = elf_file.sections.items(.shdr)[shndx];
130130 break :blk .{ shdr.sh_addr, shdr.sh_size };
131131 };
132132 if (mem.startsWith(u8, sym_name, "__EH_FRAME_BEGIN__") or
......@@ -173,7 +173,7 @@ pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 {
173173pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
174174 if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0;
175175 const extras = symbol.extra(elf_file);
176 const shdr = elf_file.shdrs.items[elf_file.plt_got_section_index.?];
176 const shdr = elf_file.sections.items(.shdr)[elf_file.plt_got_section_index.?];
177177 const cpu_arch = elf_file.getTarget().cpu.arch;
178178 return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch));
179179}
......@@ -181,7 +181,7 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
181181pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {
182182 if (!symbol.flags.has_plt) return 0;
183183 const extras = symbol.extra(elf_file);
184 const shdr = elf_file.shdrs.items[elf_file.plt_section_index.?];
184 const shdr = elf_file.sections.items(.shdr)[elf_file.plt_section_index.?];
185185 const cpu_arch = elf_file.getTarget().cpu.arch;
186186 return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch));
187187}
......@@ -189,13 +189,13 @@ pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {
189189pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 {
190190 if (!symbol.flags.has_plt) return 0;
191191 const extras = symbol.extra(elf_file);
192 const shdr = elf_file.shdrs.items[elf_file.got_plt_section_index.?];
192 const shdr = elf_file.sections.items(.shdr)[elf_file.got_plt_section_index.?];
193193 return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size);
194194}
195195
196196pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 {
197197 if (!symbol.flags.has_copy_rel) return 0;
198 const shdr = elf_file.shdrs.items[elf_file.copy_rel_section_index.?];
198 const shdr = elf_file.sections.items(.shdr)[elf_file.copy_rel_section_index.?];
199199 return @as(i64, @intCast(shdr.sh_addr)) + symbol.value;
200200}
201201
......@@ -300,7 +300,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
300300 break :blk 0;
301301 }
302302 if (st_shndx == elf.SHN_ABS or st_shndx == elf.SHN_COMMON) break :blk symbol.address(.{ .plt = false }, elf_file);
303 const shdr = elf_file.shdrs.items[st_shndx];
303 const shdr = elf_file.sections.items(.shdr)[st_shndx];
304304 if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined)
305305 break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress();
306306 break :blk symbol.address(.{ .plt = false, .trampoline = false }, elf_file);
src/link/Elf/ZigObject.zig+310-38
......@@ -63,24 +63,300 @@ pub const global_symbol_bit: u32 = 0x80000000;
6363pub const symbol_mask: u32 = 0x7fffffff;
6464pub const SHN_ATOM: u16 = 0x100;
6565
66pub fn init(self: *ZigObject, elf_file: *Elf) !void {
66const InitOptions = struct {
67 symbol_count_hint: u64,
68 program_code_size_hint: u64,
69};
70
71pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
6772 const comp = elf_file.base.comp;
6873 const gpa = comp.gpa;
74 const ptr_size = elf_file.ptrWidthBytes();
75 const target = elf_file.getTarget();
76 const ptr_bit_width = target.ptrBitWidth();
6977
7078 try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section
7179 try self.relocs.append(gpa, .{}); // null relocs section
7280 try self.strtab.buffer.append(gpa, 0);
7381
74 const name_off = try self.strtab.insert(gpa, self.path);
75 const symbol_index = try self.newLocalSymbol(gpa, name_off);
76 const sym = self.symbol(symbol_index);
77 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
78 esym.st_info = elf.STT_FILE;
79 esym.st_shndx = elf.SHN_ABS;
82 {
83 const name_off = try self.strtab.insert(gpa, self.path);
84 const symbol_index = try self.newLocalSymbol(gpa, name_off);
85 const sym = self.symbol(symbol_index);
86 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
87 esym.st_info = elf.STT_FILE;
88 esym.st_shndx = elf.SHN_ABS;
89 }
90
91 const fillSection = struct {
92 fn fillSection(ef: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) !void {
93 if (ef.base.isRelocatable()) {
94 const off = try ef.findFreeSpace(size, shdr.sh_addralign);
95 shdr.sh_offset = off;
96 shdr.sh_size = size;
97 } else {
98 const phdr = ef.phdrs.items[phndx.?];
99 shdr.sh_addr = phdr.p_vaddr;
100 shdr.sh_offset = phdr.p_offset;
101 shdr.sh_size = phdr.p_memsz;
102 }
103 }
104 }.fillSection;
105
106 comptime assert(Elf.number_of_zig_segments == 4);
107
108 if (!elf_file.base.isRelocatable()) {
109 if (elf_file.phdr_zig_load_re_index == null) {
110 const filesz = options.program_code_size_hint;
111 const off = try elf_file.findFreeSpace(filesz, elf_file.page_size);
112 elf_file.phdr_zig_load_re_index = try elf_file.addPhdr(.{
113 .type = elf.PT_LOAD,
114 .offset = off,
115 .filesz = filesz,
116 .addr = if (ptr_bit_width >= 32) 0x4000000 else 0x4000,
117 .memsz = filesz,
118 .@"align" = elf_file.page_size,
119 .flags = elf.PF_X | elf.PF_R | elf.PF_W,
120 });
121 }
122
123 if (elf_file.phdr_zig_load_ro_index == null) {
124 const alignment = elf_file.page_size;
125 const filesz: u64 = 1024;
126 const off = try elf_file.findFreeSpace(filesz, alignment);
127 elf_file.phdr_zig_load_ro_index = try elf_file.addPhdr(.{
128 .type = elf.PT_LOAD,
129 .offset = off,
130 .filesz = filesz,
131 .addr = if (ptr_bit_width >= 32) 0xc000000 else 0xa000,
132 .memsz = filesz,
133 .@"align" = alignment,
134 .flags = elf.PF_R | elf.PF_W,
135 });
136 }
137
138 if (elf_file.phdr_zig_load_rw_index == null) {
139 const alignment = elf_file.page_size;
140 const filesz: u64 = 1024;
141 const off = try elf_file.findFreeSpace(filesz, alignment);
142 elf_file.phdr_zig_load_rw_index = try elf_file.addPhdr(.{
143 .type = elf.PT_LOAD,
144 .offset = off,
145 .filesz = filesz,
146 .addr = if (ptr_bit_width >= 32) 0x10000000 else 0xc000,
147 .memsz = filesz,
148 .@"align" = alignment,
149 .flags = elf.PF_R | elf.PF_W,
150 });
151 }
152
153 if (elf_file.phdr_zig_load_zerofill_index == null) {
154 const alignment = elf_file.page_size;
155 elf_file.phdr_zig_load_zerofill_index = try elf_file.addPhdr(.{
156 .type = elf.PT_LOAD,
157 .addr = if (ptr_bit_width >= 32) 0x14000000 else 0xf000,
158 .memsz = 1024,
159 .@"align" = alignment,
160 .flags = elf.PF_R | elf.PF_W,
161 });
162 }
163 }
164
165 if (elf_file.zig_text_section_index == null) {
166 elf_file.zig_text_section_index = try elf_file.addSection(.{
167 .name = try elf_file.insertShString(".text.zig"),
168 .type = elf.SHT_PROGBITS,
169 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
170 .addralign = 1,
171 .offset = std.math.maxInt(u64),
172 });
173 const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_text_section_index.?];
174 const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_text_section_index.?];
175 try fillSection(elf_file, shdr, options.program_code_size_hint, elf_file.phdr_zig_load_re_index);
176 if (elf_file.base.isRelocatable()) {
177 _ = try elf_file.addRelaShdr(
178 try elf_file.insertShString(".rela.text.zig"),
179 elf_file.zig_text_section_index.?,
180 );
181 } else {
182 phndx.* = elf_file.phdr_zig_load_re_index.?;
183 }
184 }
185
186 if (elf_file.zig_data_rel_ro_section_index == null) {
187 elf_file.zig_data_rel_ro_section_index = try elf_file.addSection(.{
188 .name = try elf_file.insertShString(".data.rel.ro.zig"),
189 .type = elf.SHT_PROGBITS,
190 .addralign = 1,
191 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
192 .offset = std.math.maxInt(u64),
193 });
194 const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_data_rel_ro_section_index.?];
195 const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_data_rel_ro_section_index.?];
196 try fillSection(elf_file, shdr, 1024, elf_file.phdr_zig_load_ro_index);
197 if (elf_file.base.isRelocatable()) {
198 _ = try elf_file.addRelaShdr(
199 try elf_file.insertShString(".rela.data.rel.ro.zig"),
200 elf_file.zig_data_rel_ro_section_index.?,
201 );
202 } else {
203 phndx.* = elf_file.phdr_zig_load_ro_index.?;
204 }
205 }
206
207 if (elf_file.zig_data_section_index == null) {
208 elf_file.zig_data_section_index = try elf_file.addSection(.{
209 .name = try elf_file.insertShString(".data.zig"),
210 .type = elf.SHT_PROGBITS,
211 .addralign = ptr_size,
212 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
213 .offset = std.math.maxInt(u64),
214 });
215 const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_data_section_index.?];
216 const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_data_section_index.?];
217 try fillSection(elf_file, shdr, 1024, elf_file.phdr_zig_load_rw_index);
218 if (elf_file.base.isRelocatable()) {
219 _ = try elf_file.addRelaShdr(
220 try elf_file.insertShString(".rela.data.zig"),
221 elf_file.zig_data_section_index.?,
222 );
223 } else {
224 phndx.* = elf_file.phdr_zig_load_rw_index.?;
225 }
226 }
227
228 if (elf_file.zig_bss_section_index == null) {
229 elf_file.zig_bss_section_index = try elf_file.addSection(.{
230 .name = try elf_file.insertShString(".bss.zig"),
231 .type = elf.SHT_NOBITS,
232 .addralign = ptr_size,
233 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
234 .offset = 0,
235 });
236 const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_bss_section_index.?];
237 const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_bss_section_index.?];
238 if (elf_file.base.isRelocatable()) {
239 shdr.sh_size = 1024;
240 } else {
241 phndx.* = elf_file.phdr_zig_load_zerofill_index.?;
242 const phdr = elf_file.phdrs.items[phndx.*.?];
243 shdr.sh_addr = phdr.p_vaddr;
244 shdr.sh_size = phdr.p_memsz;
245 }
246 }
80247
81248 switch (comp.config.debug_format) {
82249 .strip => {},
83 .dwarf => |v| self.dwarf = Dwarf.init(&elf_file.base, v),
250 .dwarf => |v| {
251 var dwarf = Dwarf.init(&elf_file.base, v);
252
253 const addSectionSymbol = struct {
254 fn addSectionSymbol(
255 zig_object: *ZigObject,
256 alloc: Allocator,
257 name: [:0]const u8,
258 alignment: Atom.Alignment,
259 shndx: u32,
260 ) !Symbol.Index {
261 const name_off = try zig_object.addString(alloc, name);
262 const index = try zig_object.newSymbolWithAtom(alloc, name_off);
263 const sym = zig_object.symbol(index);
264 const esym = &zig_object.symtab.items(.elf_sym)[sym.esym_index];
265 esym.st_info |= elf.STT_SECTION;
266 const atom_ptr = zig_object.atom(sym.ref.index).?;
267 atom_ptr.alignment = alignment;
268 atom_ptr.output_section_index = shndx;
269 return index;
270 }
271 }.addSectionSymbol;
272
273 if (elf_file.debug_str_section_index == null) {
274 elf_file.debug_str_section_index = try elf_file.addSection(.{
275 .name = try elf_file.insertShString(".debug_str"),
276 .flags = elf.SHF_MERGE | elf.SHF_STRINGS,
277 .entsize = 1,
278 .type = elf.SHT_PROGBITS,
279 .addralign = 1,
280 });
281 self.debug_str_section_dirty = true;
282 self.debug_str_index = try addSectionSymbol(self, gpa, ".debug_str", .@"1", elf_file.debug_str_section_index.?);
283 }
284
285 if (elf_file.debug_info_section_index == null) {
286 elf_file.debug_info_section_index = try elf_file.addSection(.{
287 .name = try elf_file.insertShString(".debug_info"),
288 .type = elf.SHT_PROGBITS,
289 .addralign = 1,
290 });
291 self.debug_info_section_dirty = true;
292 self.debug_info_index = try addSectionSymbol(self, gpa, ".debug_info", .@"1", elf_file.debug_info_section_index.?);
293 }
294
295 if (elf_file.debug_abbrev_section_index == null) {
296 elf_file.debug_abbrev_section_index = try elf_file.addSection(.{
297 .name = try elf_file.insertShString(".debug_abbrev"),
298 .type = elf.SHT_PROGBITS,
299 .addralign = 1,
300 });
301 self.debug_abbrev_section_dirty = true;
302 self.debug_abbrev_index = try addSectionSymbol(self, gpa, ".debug_abbrev", .@"1", elf_file.debug_abbrev_section_index.?);
303 }
304
305 if (elf_file.debug_aranges_section_index == null) {
306 elf_file.debug_aranges_section_index = try elf_file.addSection(.{
307 .name = try elf_file.insertShString(".debug_aranges"),
308 .type = elf.SHT_PROGBITS,
309 .addralign = 16,
310 });
311 self.debug_aranges_section_dirty = true;
312 self.debug_aranges_index = try addSectionSymbol(self, gpa, ".debug_aranges", .@"16", elf_file.debug_aranges_section_index.?);
313 }
314
315 if (elf_file.debug_line_section_index == null) {
316 elf_file.debug_line_section_index = try elf_file.addSection(.{
317 .name = try elf_file.insertShString(".debug_line"),
318 .type = elf.SHT_PROGBITS,
319 .addralign = 1,
320 });
321 self.debug_line_section_dirty = true;
322 self.debug_line_index = try addSectionSymbol(self, gpa, ".debug_line", .@"1", elf_file.debug_line_section_index.?);
323 }
324
325 if (elf_file.debug_line_str_section_index == null) {
326 elf_file.debug_line_str_section_index = try elf_file.addSection(.{
327 .name = try elf_file.insertShString(".debug_line_str"),
328 .flags = elf.SHF_MERGE | elf.SHF_STRINGS,
329 .entsize = 1,
330 .type = elf.SHT_PROGBITS,
331 .addralign = 1,
332 });
333 self.debug_line_str_section_dirty = true;
334 self.debug_line_str_index = try addSectionSymbol(self, gpa, ".debug_line_str", .@"1", elf_file.debug_line_str_section_index.?);
335 }
336
337 if (elf_file.debug_loclists_section_index == null) {
338 elf_file.debug_loclists_section_index = try elf_file.addSection(.{
339 .name = try elf_file.insertShString(".debug_loclists"),
340 .type = elf.SHT_PROGBITS,
341 .addralign = 1,
342 });
343 self.debug_loclists_section_dirty = true;
344 self.debug_loclists_index = try addSectionSymbol(self, gpa, ".debug_loclists", .@"1", elf_file.debug_loclists_section_index.?);
345 }
346
347 if (elf_file.debug_rnglists_section_index == null) {
348 elf_file.debug_rnglists_section_index = try elf_file.addSection(.{
349 .name = try elf_file.insertShString(".debug_rnglists"),
350 .type = elf.SHT_PROGBITS,
351 .addralign = 1,
352 });
353 self.debug_rnglists_section_dirty = true;
354 self.debug_rnglists_index = try addSectionSymbol(self, gpa, ".debug_rnglists", .@"1", elf_file.debug_rnglists_section_index.?);
355 }
356
357 try dwarf.initMetadata();
358 self.dwarf = dwarf;
359 },
84360 .code_view => unreachable,
85361 }
86362}
......@@ -198,7 +474,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
198474 const atom_ptr = self.atom(sym.ref.index).?;
199475 if (!atom_ptr.alive) continue;
200476 const shndx = sym.outputShndx(elf_file).?;
201 const shdr = elf_file.shdrs.items[shndx];
477 const shdr = elf_file.sections.items(.shdr)[shndx];
202478 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
203479 esym.st_size = shdr.sh_size;
204480 atom_ptr.size = shdr.sh_size;
......@@ -358,13 +634,10 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
358634 }
359635
360636 if (elf_file.base.isRelocatable() and relocs.items.len > 0) {
361 const gop = try elf_file.output_rela_sections.getOrPut(gpa, shndx);
362 if (!gop.found_existing) {
363 const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{elf_file.getShString(shdr.sh_name)});
364 defer gpa.free(rela_sect_name);
365 const rela_sh_name = try elf_file.insertShString(rela_sect_name);
366 const rela_shndx = try elf_file.addRelaShdr(rela_sh_name, shndx);
367 gop.value_ptr.* = .{ .shndx = rela_shndx };
637 const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{elf_file.getShString(shdr.sh_name)});
638 defer gpa.free(rela_sect_name);
639 if (elf_file.sectionByName(rela_sect_name) == null) {
640 _ = try elf_file.addRelaShdr(try elf_file.insertShString(rela_sect_name), shndx);
368641 }
369642 }
370643 }
......@@ -446,7 +719,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index {
446719 return index;
447720}
448721
449pub fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
722fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
450723 const atom_index = try self.newAtom(allocator, name_off);
451724 const sym_index = try self.newLocalSymbol(allocator, name_off);
452725 const sym = self.symbol(sym_index);
......@@ -460,7 +733,7 @@ pub fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32)
460733pub fn inputShdr(self: *ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.Elf64_Shdr {
461734 const atom_ptr = self.atom(atom_index) orelse return Elf.null_shdr;
462735 const shndx = atom_ptr.output_section_index;
463 var shdr = elf_file.shdrs.items[shndx];
736 var shdr = elf_file.sections.items(.shdr)[shndx];
464737 shdr.sh_addr = 0;
465738 shdr.sh_offset = 0;
466739 shdr.sh_size = atom_ptr.size;
......@@ -638,8 +911,8 @@ pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void {
638911 .p32 => @sizeOf(elf.Elf32_Shdr),
639912 .p64 => @sizeOf(elf.Elf64_Shdr),
640913 };
641 var end_pos: u64 = elf_file.shdr_table_offset.? + elf_file.shdrs.items.len * shsize;
642 for (elf_file.shdrs.items) |shdr| {
914 var end_pos: u64 = elf_file.shdr_table_offset.? + elf_file.sections.items(.shdr).len * shsize;
915 for (elf_file.sections.items(.shdr)) |shdr| {
643916 if (shdr.sh_type == elf.SHT_NOBITS) continue;
644917 end_pos = @max(end_pos, shdr.sh_offset + shdr.sh_size);
645918 }
......@@ -692,12 +965,14 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
692965 // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level
693966 if (self.relocs.items[rela_shndx].items.len == 0) continue;
694967 const out_shndx = atom_ptr.output_section_index;
695 const out_shdr = elf_file.shdrs.items[out_shndx];
968 const out_shdr = elf_file.sections.items(.shdr)[out_shndx];
696969 if (out_shdr.sh_type == elf.SHT_NOBITS) continue;
697
970 const out_rela_shndx = for (elf_file.sections.items(.shdr), 0..) |out_rela_shdr, out_rela_shndx| {
971 if (out_rela_shdr.sh_type == elf.SHT_RELA and out_rela_shdr.sh_info == out_shndx) break out_rela_shndx;
972 } else unreachable;
973 const atom_list = &elf_file.sections.items(.atom_list)[out_rela_shndx];
698974 const gpa = elf_file.base.comp.gpa;
699 const sec = elf_file.output_rela_sections.getPtr(out_shndx).?;
700 try sec.atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
975 try atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
701976 }
702977}
703978
......@@ -767,7 +1042,7 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
7671042pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
7681043 const gpa = elf_file.base.comp.gpa;
7691044 const atom_ptr = self.atom(atom_index).?;
770 const shdr = &elf_file.shdrs.items[atom_ptr.output_section_index];
1045 const shdr = &elf_file.sections.items(.shdr)[atom_ptr.output_section_index];
7711046
7721047 if (shdr.sh_flags & elf.SHF_TLS != 0) {
7731048 const tlv = self.tls_variables.get(atom_index).?;
......@@ -1094,7 +1369,7 @@ fn updateNavCode(
10941369 }
10951370 }
10961371
1097 const shdr = elf_file.shdrs.items[shdr_index];
1372 const shdr = elf_file.sections.items(.shdr)[shdr_index];
10981373 if (shdr.sh_type != elf.SHT_NOBITS) {
10991374 const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
11001375 try elf_file.base.file.?.pwriteAll(code, file_offset);
......@@ -1149,16 +1424,13 @@ fn updateTlv(
11491424 gop.value_ptr.* = .{ .symbol_index = sym_index };
11501425
11511426 // We only store the data for the TLV if it's non-zerofill.
1152 if (elf_file.shdrs.items[shndx].sh_type != elf.SHT_NOBITS) {
1427 if (elf_file.sections.items(.shdr)[shndx].sh_type != elf.SHT_NOBITS) {
11531428 gop.value_ptr.code = try gpa.dupe(u8, code);
11541429 }
11551430 }
11561431
1157 {
1158 const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index);
1159 if (!gop.found_existing) gop.value_ptr.* = .{};
1160 try gop.value_ptr.append(gpa, .{ .index = atom_ptr.atom_index, .file = self.index });
1161 }
1432 const atom_list = &elf_file.sections.items(.atom_list)[atom_ptr.output_section_index];
1433 try atom_list.append(gpa, .{ .index = atom_ptr.atom_index, .file = self.index });
11621434}
11631435
11641436pub fn updateFunc(
......@@ -1210,7 +1482,7 @@ pub fn updateFunc(
12101482 const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, sym_index, code);
12111483 log.debug("setting shdr({x},{s}) for {}", .{
12121484 shndx,
1213 elf_file.getShString(elf_file.shdrs.items[shndx].sh_name),
1485 elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),
12141486 ip.getNav(func.owner_nav).fqn.fmt(ip),
12151487 });
12161488 const old_rva, const old_alignment = blk: {
......@@ -1338,10 +1610,10 @@ pub fn updateNav(
13381610 const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, sym_index, code);
13391611 log.debug("setting shdr({x},{s}) for {}", .{
13401612 shndx,
1341 elf_file.getShString(elf_file.shdrs.items[shndx].sh_name),
1613 elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name),
13421614 nav.fqn.fmt(ip),
13431615 });
1344 if (elf_file.shdrs.items[shndx].sh_flags & elf.SHF_TLS != 0)
1616 if (elf_file.sections.items(.shdr)[shndx].sh_flags & elf.SHF_TLS != 0)
13451617 try self.updateTlv(elf_file, pt, nav_index, sym_index, shndx, code)
13461618 else
13471619 try self.updateNavCode(elf_file, pt, nav_index, sym_index, shndx, code, elf.STT_OBJECT);
......@@ -1440,7 +1712,7 @@ fn updateLazySymbol(
14401712 local_sym.value = 0;
14411713 local_esym.st_value = 0;
14421714
1443 const shdr = elf_file.shdrs.items[output_section_index];
1715 const shdr = elf_file.sections.items(.shdr)[output_section_index];
14441716 const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
14451717 try elf_file.base.file.?.pwriteAll(code, file_offset);
14461718}
......@@ -1496,7 +1768,7 @@ fn lowerConst(
14961768 // TODO rename and re-audit this method
14971769 errdefer self.freeNavMetadata(elf_file, sym_index);
14981770
1499 const shdr = elf_file.shdrs.items[output_section_index];
1771 const shdr = elf_file.sections.items(.shdr)[output_section_index];
15001772 const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
15011773 try elf_file.base.file.?.pwriteAll(code, file_offset);
15021774
......@@ -1660,7 +1932,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 {
16601932
16611933fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
16621934 const atom_ptr = tr_sym.atom(elf_file).?;
1663 const shdr = elf_file.shdrs.items[atom_ptr.output_section_index];
1935 const shdr = elf_file.sections.items(.shdr)[atom_ptr.output_section_index];
16641936 const fileoff = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
16651937 const source_addr = tr_sym.address(.{}, elf_file);
16661938 const target_addr = target.address(.{ .trampoline = false }, elf_file);
src/link/Elf/eh_frame.zig+12-7
......@@ -13,7 +13,7 @@ pub const Fde = struct {
1313
1414 pub fn address(fde: Fde, elf_file: *Elf) u64 {
1515 const base: u64 = if (elf_file.eh_frame_section_index) |shndx|
16 elf_file.shdrs.items[shndx].sh_addr
16 elf_file.sections.items(.shdr)[shndx].sh_addr
1717 else
1818 0;
1919 return base + fde.out_offset;
......@@ -112,7 +112,7 @@ pub const Cie = struct {
112112
113113 pub fn address(cie: Cie, elf_file: *Elf) u64 {
114114 const base: u64 = if (elf_file.eh_frame_section_index) |shndx|
115 elf_file.shdrs.items[shndx].sh_addr
115 elf_file.sections.items(.shdr)[shndx].sh_addr
116116 else
117117 0;
118118 return base + cie.out_offset;
......@@ -326,7 +326,9 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
326326}
327327
328328pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
329 relocs_log.debug("{x}: .eh_frame", .{elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr});
329 relocs_log.debug("{x}: .eh_frame", .{
330 elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr,
331 });
330332
331333 var has_reloc_errors = false;
332334
......@@ -423,7 +425,7 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re
423425 switch (sym.type(elf_file)) {
424426 elf.STT_SECTION => {
425427 r_addend += @intCast(sym.address(.{}, elf_file));
426 r_sym = elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?);
428 r_sym = sym.outputShndx(elf_file).?;
427429 },
428430 else => {
429431 r_sym = sym.outputSymtabIndex(elf_file) orelse 0;
......@@ -446,7 +448,9 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re
446448}
447449
448450pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
449 relocs_log.debug("{x}: .eh_frame", .{elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr});
451 relocs_log.debug("{x}: .eh_frame", .{
452 elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr,
453 });
450454
451455 for (elf_file.objects.items) |index| {
452456 const object = elf_file.file(index).?.object;
......@@ -482,8 +486,9 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
482486 try writer.writeByte(EH_PE.udata4);
483487 try writer.writeByte(EH_PE.datarel | EH_PE.sdata4);
484488
485 const eh_frame_shdr = elf_file.shdrs.items[elf_file.eh_frame_section_index.?];
486 const eh_frame_hdr_shdr = elf_file.shdrs.items[elf_file.eh_frame_hdr_section_index.?];
489 const shdrs = elf_file.sections.items(.shdr);
490 const eh_frame_shdr = shdrs[elf_file.eh_frame_section_index.?];
491 const eh_frame_hdr_shdr = shdrs[elf_file.eh_frame_hdr_section_index.?];
487492 const num_fdes = @as(u32, @intCast(@divExact(eh_frame_hdr_shdr.sh_size - eh_frame_hdr_header_size, 8)));
488493 try writer.writeInt(
489494 u32,
src/link/Elf/merge_section.zig+2-4
......@@ -29,7 +29,7 @@ pub const MergeSection = struct {
2929 }
3030
3131 pub fn address(msec: MergeSection, elf_file: *Elf) i64 {
32 const shdr = elf_file.shdrs.items[msec.output_section_index];
32 const shdr = elf_file.sections.items(.shdr)[msec.output_section_index];
3333 return @intCast(shdr.sh_addr + msec.value);
3434 }
3535
......@@ -108,13 +108,11 @@ pub const MergeSection = struct {
108108 }
109109
110110 pub fn initOutputSection(msec: *MergeSection, elf_file: *Elf) !void {
111 const shndx = elf_file.sectionByName(msec.name(elf_file)) orelse try elf_file.addSection(.{
111 msec.output_section_index = elf_file.sectionByName(msec.name(elf_file)) orelse try elf_file.addSection(.{
112112 .name = msec.name_offset,
113113 .type = msec.type,
114114 .flags = msec.flags,
115115 });
116 try elf_file.output_sections.put(elf_file.base.comp.gpa, shndx, .{});
117 msec.output_section_index = shndx;
118116 }
119117
120118 pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index {
src/link/Elf/relocatable.zig+37-38
......@@ -347,36 +347,36 @@ fn initComdatGroups(elf_file: *Elf) !void {
347347}
348348
349349fn updateSectionSizes(elf_file: *Elf) !void {
350 for (elf_file.output_sections.keys(), elf_file.output_sections.values()) |shndx, atom_list| {
351 const shdr = &elf_file.shdrs.items[shndx];
352 for (atom_list.items) |ref| {
353 const atom_ptr = elf_file.atom(ref) orelse continue;
354 if (!atom_ptr.alive) continue;
355 const offset = atom_ptr.alignment.forward(shdr.sh_size);
356 const padding = offset - shdr.sh_size;
357 atom_ptr.value = @intCast(offset);
358 shdr.sh_size += padding + atom_ptr.size;
359 shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1);
360 }
361 }
350 const slice = elf_file.sections.slice();
351 for (slice.items(.shdr), 0..) |*shdr, shndx| {
352 const atom_list = slice.items(.atom_list)[shndx];
353 if (shdr.sh_type != elf.SHT_RELA) {
354 for (atom_list.items) |ref| {
355 const atom_ptr = elf_file.atom(ref) orelse continue;
356 if (!atom_ptr.alive) continue;
357 const offset = atom_ptr.alignment.forward(shdr.sh_size);
358 const padding = offset - shdr.sh_size;
359 atom_ptr.value = @intCast(offset);
360 shdr.sh_size += padding + atom_ptr.size;
361 shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1);
362 }
363 } else {
364 for (atom_list.items) |ref| {
365 const atom_ptr = elf_file.atom(ref) orelse continue;
366 if (!atom_ptr.alive) continue;
367 const relocs = atom_ptr.relocs(elf_file);
368 shdr.sh_size += shdr.sh_entsize * relocs.len;
369 }
362370
363 for (elf_file.output_rela_sections.values()) |sec| {
364 const shdr = &elf_file.shdrs.items[sec.shndx];
365 for (sec.atom_list.items) |ref| {
366 const atom_ptr = elf_file.atom(ref) orelse continue;
367 if (!atom_ptr.alive) continue;
368 const relocs = atom_ptr.relocs(elf_file);
369 shdr.sh_size += shdr.sh_entsize * relocs.len;
371 if (shdr.sh_size == 0) shdr.sh_offset = 0;
370372 }
371
372 if (shdr.sh_size == 0) shdr.sh_offset = 0;
373373 }
374374
375375 if (elf_file.eh_frame_section_index) |index| {
376 elf_file.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(elf_file);
376 slice.items(.shdr)[index].sh_size = try eh_frame.calcEhFrameSize(elf_file);
377377 }
378378 if (elf_file.eh_frame_rela_section_index) |index| {
379 const shdr = &elf_file.shdrs.items[index];
379 const shdr = &slice.items(.shdr)[index];
380380 shdr.sh_size = eh_frame.calcEhFrameRelocs(elf_file) * shdr.sh_entsize;
381381 }
382382
......@@ -387,19 +387,18 @@ fn updateSectionSizes(elf_file: *Elf) !void {
387387
388388fn updateComdatGroupsSizes(elf_file: *Elf) void {
389389 for (elf_file.comdat_group_sections.items) |cg| {
390 const shdr = &elf_file.shdrs.items[cg.shndx];
390 const shdr = &elf_file.sections.items(.shdr)[cg.shndx];
391391 shdr.sh_size = cg.size(elf_file);
392392 shdr.sh_link = elf_file.symtab_section_index.?;
393393
394394 const sym = cg.symbol(elf_file);
395 shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse
396 elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?);
395 shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse sym.outputShndx(elf_file).?;
397396 }
398397}
399398
400399/// Allocates alloc sections when merging relocatable objects files together.
401400fn allocateAllocSections(elf_file: *Elf) !void {
402 for (elf_file.shdrs.items) |*shdr| {
401 for (elf_file.sections.items(.shdr)) |*shdr| {
403402 if (shdr.sh_type == elf.SHT_NULL) continue;
404403 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
405404 if (shdr.sh_type == elf.SHT_NOBITS) {
......@@ -418,13 +417,13 @@ fn allocateAllocSections(elf_file: *Elf) !void {
418417
419418fn writeAtoms(elf_file: *Elf) !void {
420419 const gpa = elf_file.base.comp.gpa;
420 const slice = elf_file.sections.slice();
421421
422422 // TODO iterate over `output_sections` directly
423 for (elf_file.shdrs.items, 0..) |shdr, shndx| {
423 for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| {
424424 if (shdr.sh_type == elf.SHT_NULL) continue;
425425 if (shdr.sh_type == elf.SHT_NOBITS) continue;
426
427 const atom_list = elf_file.output_sections.get(@intCast(shndx)) orelse continue;
426 if (shdr.sh_type == elf.SHT_RELA) continue;
428427 if (atom_list.items.len == 0) continue;
429428
430429 log.debug("writing atoms in '{s}' section", .{elf_file.getShString(shdr.sh_name)});
......@@ -490,18 +489,18 @@ fn writeAtoms(elf_file: *Elf) !void {
490489
491490fn writeSyntheticSections(elf_file: *Elf) !void {
492491 const gpa = elf_file.base.comp.gpa;
492 const slice = elf_file.sections.slice();
493493
494 for (elf_file.output_rela_sections.values()) |sec| {
495 if (sec.atom_list.items.len == 0) continue;
496
497 const shdr = elf_file.shdrs.items[sec.shndx];
494 for (slice.items(.shdr), slice.items(.atom_list)) |shdr, atom_list| {
495 if (shdr.sh_type != elf.SHT_RELA) continue;
496 if (atom_list.items.len == 0) continue;
498497
499498 const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse
500499 return error.Overflow;
501500 var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs);
502501 defer relocs.deinit();
503502
504 for (sec.atom_list.items) |ref| {
503 for (atom_list.items) |ref| {
505504 const atom_ptr = elf_file.atom(ref) orelse continue;
506505 if (!atom_ptr.alive) continue;
507506 try atom_ptr.writeRelocs(elf_file, &relocs);
......@@ -527,7 +526,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
527526 }
528527
529528 if (elf_file.eh_frame_section_index) |shndx| {
530 const shdr = elf_file.shdrs.items[shndx];
529 const shdr = slice.items(.shdr)[shndx];
531530 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
532531 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
533532 defer buffer.deinit();
......@@ -540,7 +539,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
540539 try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
541540 }
542541 if (elf_file.eh_frame_rela_section_index) |shndx| {
543 const shdr = elf_file.shdrs.items[shndx];
542 const shdr = slice.items(.shdr)[shndx];
544543 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
545544 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
546545 defer buffer.deinit();
......@@ -561,7 +560,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
561560fn writeComdatGroups(elf_file: *Elf) !void {
562561 const gpa = elf_file.base.comp.gpa;
563562 for (elf_file.comdat_group_sections.items) |cgs| {
564 const shdr = elf_file.shdrs.items[cgs.shndx];
563 const shdr = elf_file.sections.items(.shdr)[cgs.shndx];
565564 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
566565 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
567566 defer buffer.deinit();
src/link/Elf/synthetic_sections.zig+30-22
......@@ -95,6 +95,8 @@ pub const DynamicSection = struct {
9595 }
9696
9797 pub fn write(dt: DynamicSection, elf_file: *Elf, writer: anytype) !void {
98 const shdrs = elf_file.sections.items(.shdr);
99
98100 // NEEDED
99101 for (dt.needed.items) |off| {
100102 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off });
......@@ -112,33 +114,33 @@ pub const DynamicSection = struct {
112114
113115 // INIT
114116 if (elf_file.sectionByName(".init")) |shndx| {
115 const addr = elf_file.shdrs.items[shndx].sh_addr;
117 const addr = shdrs[shndx].sh_addr;
116118 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr });
117119 }
118120
119121 // FINI
120122 if (elf_file.sectionByName(".fini")) |shndx| {
121 const addr = elf_file.shdrs.items[shndx].sh_addr;
123 const addr = shdrs[shndx].sh_addr;
122124 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr });
123125 }
124126
125127 // INIT_ARRAY
126128 if (elf_file.sectionByName(".init_array")) |shndx| {
127 const shdr = elf_file.shdrs.items[shndx];
129 const shdr = shdrs[shndx];
128130 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr });
129131 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size });
130132 }
131133
132134 // FINI_ARRAY
133135 if (elf_file.sectionByName(".fini_array")) |shndx| {
134 const shdr = elf_file.shdrs.items[shndx];
136 const shdr = shdrs[shndx];
135137 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr });
136138 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size });
137139 }
138140
139141 // RELA
140142 if (elf_file.rela_dyn_section_index) |shndx| {
141 const shdr = elf_file.shdrs.items[shndx];
143 const shdr = shdrs[shndx];
142144 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr });
143145 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size });
144146 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize });
......@@ -146,7 +148,7 @@ pub const DynamicSection = struct {
146148
147149 // JMPREL
148150 if (elf_file.rela_plt_section_index) |shndx| {
149 const shdr = elf_file.shdrs.items[shndx];
151 const shdr = shdrs[shndx];
150152 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr });
151153 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size });
152154 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA });
......@@ -154,18 +156,18 @@ pub const DynamicSection = struct {
154156
155157 // PLTGOT
156158 if (elf_file.got_plt_section_index) |shndx| {
157 const addr = elf_file.shdrs.items[shndx].sh_addr;
159 const addr = shdrs[shndx].sh_addr;
158160 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr });
159161 }
160162
161163 {
162164 assert(elf_file.hash_section_index != null);
163 const addr = elf_file.shdrs.items[elf_file.hash_section_index.?].sh_addr;
165 const addr = shdrs[elf_file.hash_section_index.?].sh_addr;
164166 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr });
165167 }
166168
167169 if (elf_file.gnu_hash_section_index) |shndx| {
168 const addr = elf_file.shdrs.items[shndx].sh_addr;
170 const addr = shdrs[shndx].sh_addr;
169171 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr });
170172 }
171173
......@@ -177,7 +179,7 @@ pub const DynamicSection = struct {
177179 // SYMTAB + SYMENT
178180 {
179181 assert(elf_file.dynsymtab_section_index != null);
180 const shdr = elf_file.shdrs.items[elf_file.dynsymtab_section_index.?];
182 const shdr = shdrs[elf_file.dynsymtab_section_index.?];
181183 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr });
182184 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize });
183185 }
......@@ -185,20 +187,20 @@ pub const DynamicSection = struct {
185187 // STRTAB + STRSZ
186188 {
187189 assert(elf_file.dynstrtab_section_index != null);
188 const shdr = elf_file.shdrs.items[elf_file.dynstrtab_section_index.?];
190 const shdr = shdrs[elf_file.dynstrtab_section_index.?];
189191 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr });
190192 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size });
191193 }
192194
193195 // VERSYM
194196 if (elf_file.versym_section_index) |shndx| {
195 const addr = elf_file.shdrs.items[shndx].sh_addr;
197 const addr = shdrs[shndx].sh_addr;
196198 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr });
197199 }
198200
199201 // VERNEED + VERNEEDNUM
200202 if (elf_file.verneed_section_index) |shndx| {
201 const addr = elf_file.shdrs.items[shndx].sh_addr;
203 const addr = shdrs[shndx].sh_addr;
202204 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr });
203205 try writer.writeStruct(elf.Elf64_Dyn{
204206 .d_tag = elf.DT_VERNEEDNUM,
......@@ -259,7 +261,7 @@ pub const GotSection = struct {
259261
260262 pub fn address(entry: Entry, elf_file: *Elf) i64 {
261263 const ptr_bytes = elf_file.archPtrWidthBytes();
262 const shdr = &elf_file.shdrs.items[elf_file.got_section_index.?];
264 const shdr = &elf_file.sections.items(.shdr)[elf_file.got_section_index.?];
263265 return @as(i64, @intCast(shdr.sh_addr)) + entry.cell_index * ptr_bytes;
264266 }
265267 };
......@@ -759,8 +761,9 @@ pub const PltSection = struct {
759761
760762 const x86_64 = struct {
761763 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
762 const plt_addr = elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr;
763 const got_plt_addr = elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr;
764 const shdrs = elf_file.sections.items(.shdr);
765 const plt_addr = shdrs[elf_file.plt_section_index.?].sh_addr;
766 const got_plt_addr = shdrs[elf_file.got_plt_section_index.?].sh_addr;
764767 var preamble = [_]u8{
765768 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
766769 0x41, 0x53, // push r11
......@@ -794,8 +797,9 @@ pub const PltSection = struct {
794797 const aarch64 = struct {
795798 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
796799 {
797 const plt_addr: i64 = @intCast(elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr);
798 const got_plt_addr: i64 = @intCast(elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr);
800 const shdrs = elf_file.sections.items(.shdr);
801 const plt_addr: i64 = @intCast(shdrs[elf_file.plt_section_index.?].sh_addr);
802 const got_plt_addr: i64 = @intCast(shdrs[elf_file.got_plt_section_index.?].sh_addr);
799803 // TODO: relax if possible
800804 // .got.plt[2]
801805 const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);
......@@ -869,7 +873,7 @@ pub const GotPltSection = struct {
869873 try writer.writeInt(u64, 0x0, .little);
870874 try writer.writeInt(u64, 0x0, .little);
871875 if (elf_file.plt_section_index) |shndx| {
872 const plt_addr = elf_file.shdrs.items[shndx].sh_addr;
876 const plt_addr = elf_file.sections.items(.shdr)[shndx].sh_addr;
873877 for (0..elf_file.plt.symbols.items.len) |_| {
874878 // [N]: .plt
875879 try writer.writeInt(u64, plt_addr, .little);
......@@ -1027,7 +1031,7 @@ pub const CopyRelSection = struct {
10271031 }
10281032
10291033 pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u32, elf_file: *Elf) !void {
1030 const shdr = &elf_file.shdrs.items[shndx];
1034 const shdr = &elf_file.sections.items(.shdr)[shndx];
10311035 for (copy_rel.symbols.items) |ref| {
10321036 const symbol = elf_file.symbol(ref).?;
10331037 const shared_object = symbol.file(elf_file).?.shared_object;
......@@ -1487,8 +1491,12 @@ pub const ComdatGroupSection = struct {
14871491 elf.SHT_RELA => {
14881492 const atom_index = object.atoms_indexes.items[shdr.sh_info];
14891493 const atom = object.atom(atom_index).?;
1490 const rela = elf_file.output_rela_sections.get(atom.output_section_index).?;
1491 try writer.writeInt(u32, rela.shndx, .little);
1494 const rela_shndx = for (elf_file.sections.items(.shdr), 0..) |rela_shdr, rela_shndx| {
1495 if (rela_shdr.sh_type == elf.SHT_RELA and
1496 atom.output_section_index == rela_shdr.sh_info)
1497 break rela_shndx;
1498 } else unreachable;
1499 try writer.writeInt(u32, @intCast(rela_shndx), .little);
14921500 },
14931501 else => {
14941502 const atom_index = object.atoms_indexes.items[shndx];
src/link/Elf/thunks.zig+3-4
......@@ -1,9 +1,8 @@
1pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
1pub fn createThunks(shdr: *elf.Elf64_Shdr, shndx: u32, elf_file: *Elf) !void {
22 const gpa = elf_file.base.comp.gpa;
33 const cpu_arch = elf_file.getTarget().cpu.arch;
44 const max_distance = maxAllowedDistance(cpu_arch);
5 const shdr = &elf_file.shdrs.items[shndx];
6 const atoms = elf_file.output_sections.get(shndx).?.items;
5 const atoms = elf_file.sections.items(.atom_list)[shndx].items;
76 assert(atoms.len > 0);
87
98 for (atoms) |ref| {
......@@ -89,7 +88,7 @@ pub const Thunk = struct {
8988 }
9089
9190 pub fn address(thunk: Thunk, elf_file: *Elf) i64 {
92 const shdr = elf_file.shdrs.items[thunk.output_section_index];
91 const shdr = elf_file.sections.items(.shdr)[thunk.output_section_index];
9392 return @as(i64, @intCast(shdr.sh_addr)) + thunk.value;
9493 }
9594