authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-09 17:43:17-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-10-09 17:43:17-07:00
log2e2927735d26fc6047343f0c620f20e9048ebaa5
treeb405962660ed41a6c2682e912cb9ccbcfe3748c9
parent5d7ed6110391bc8f6ff7fb9fa225bfa03fd19191
parent73c3b9b8ab056c3bcbde3a7a9b893b8814553c45
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21629 from ziglang/elf-incr

elf: more incremental progress

10 files changed, 384 insertions(+), 414 deletions(-)

src/link/Dwarf.zig+16-19
...@@ -389,15 +389,10 @@ pub const Section = struct {...@@ -389,15 +389,10 @@ pub const Section = struct {
389 if (dwarf.bin_file.cast(.elf)) |elf_file| {389 if (dwarf.bin_file.cast(.elf)) |elf_file| {
390 const zo = elf_file.zigObjectPtr().?;390 const zo = elf_file.zigObjectPtr().?;
391 const atom = zo.symbol(sec.index).atom(elf_file).?;391 const atom = zo.symbol(sec.index).atom(elf_file).?;
392 const shndx = atom.output_section_index;392 atom.size = len;
393 if (sec == &dwarf.debug_frame.section)393 atom.alignment = sec.alignment;
394 try elf_file.growAllocSection(shndx, len, sec.alignment.toByteUnits().?)394 sec.len = len;
395 else395 try zo.allocateAtom(atom, false, elf_file);
396 try elf_file.growNonAllocSection(shndx, len, sec.alignment.toByteUnits().?, true);
397 const shdr = elf_file.sections.items(.shdr)[shndx];
398 atom.size = shdr.sh_size;
399 atom.alignment = InternPool.Alignment.fromNonzeroByteUnits(shdr.sh_addralign);
400 sec.len = shdr.sh_size;
401 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {396 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
402 const header = if (macho_file.d_sym) |*d_sym| header: {397 const header = if (macho_file.d_sym) |*d_sym| header: {
403 try d_sym.growSection(@intCast(sec.index), len, true, macho_file);398 try d_sym.growSection(@intCast(sec.index), len, true, macho_file);
...@@ -418,11 +413,15 @@ pub const Section = struct {...@@ -418,11 +413,15 @@ pub const Section = struct {
418 if (dwarf.bin_file.cast(.elf)) |elf_file| {413 if (dwarf.bin_file.cast(.elf)) |elf_file| {
419 const zo = elf_file.zigObjectPtr().?;414 const zo = elf_file.zigObjectPtr().?;
420 const atom = zo.symbol(sec.index).atom(elf_file).?;415 const atom = zo.symbol(sec.index).atom(elf_file).?;
421 const shndx = atom.output_section_index;416 if (atom.prevAtom(elf_file)) |_| {
422 const shdr = &elf_file.sections.items(.shdr)[shndx];417 // FIXME:JK trimming/shrinking has to be reworked on ZigObject/Elf level
423 atom.size = sec.len;418 atom.value += len;
424 shdr.sh_offset += len;419 } else {
425 shdr.sh_size = sec.len;420 const shdr = &elf_file.sections.items(.shdr)[atom.output_section_index];
421 shdr.sh_offset += len;
422 atom.value = 0;
423 }
424 atom.size -= len;
426 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {425 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
427 const header = if (macho_file.d_sym) |*d_sym|426 const header = if (macho_file.d_sym) |*d_sym|
428 &d_sym.sections.items[sec.index]427 &d_sym.sections.items[sec.index]
...@@ -911,11 +910,9 @@ const Entry = struct {...@@ -911,11 +910,9 @@ const Entry = struct {
911 if (std.debug.runtime_safety) {910 if (std.debug.runtime_safety) {
912 log.err("missing {} from {s}", .{911 log.err("missing {} from {s}", .{
913 @as(Entry.Index, @enumFromInt(entry - unit.entries.items.ptr)),912 @as(Entry.Index, @enumFromInt(entry - unit.entries.items.ptr)),
914 std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file| sh_name: {913 std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file|
915 const zo = elf_file.zigObjectPtr().?;914 elf_file.zigObjectPtr().?.symbol(sec.index).name(elf_file)
916 const shndx = zo.symbol(sec.index).atom(elf_file).?.output_section_index;915 else if (dwarf.bin_file.cast(.macho)) |macho_file|
917 break :sh_name elf_file.shstrtab.items[elf_file.sections.items(.shdr)[shndx].sh_name..];
918 } else if (dwarf.bin_file.cast(.macho)) |macho_file|
919 if (macho_file.d_sym) |*d_sym|916 if (macho_file.d_sym) |*d_sym|
920 &d_sym.sections.items[sec.index].segname917 &d_sym.sections.items[sec.index].segname
921 else918 else
src/link/Elf.zig+131-195
...@@ -548,16 +548,6 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {...@@ -548,16 +548,6 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {
548 return min_pos - start;548 return min_pos - start;
549}549}
550550
551fn allocatedVirtualSize(self: *Elf, start: u64) u64 {
552 if (start == 0) return 0;
553 var min_pos: u64 = std.math.maxInt(u64);
554 for (self.phdrs.items) |phdr| {
555 if (phdr.p_vaddr <= start) continue;
556 if (phdr.p_vaddr < min_pos) min_pos = phdr.p_vaddr;
557 }
558 return min_pos - start;
559}
560
561pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {551pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {
562 var start: u64 = 0;552 var start: u64 = 0;
563 while (try self.detectAllocCollision(start, object_size)) |item_end| {553 while (try self.detectAllocCollision(start, object_size)) |item_end| {
...@@ -566,90 +556,49 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {...@@ -566,90 +556,49 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {
566 return start;556 return start;
567}557}
568558
569pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void {559pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void {
570 const slice = self.sections.slice();560 const shdr = &self.sections.items(.shdr)[shdr_index];
571 const shdr = &slice.items(.shdr)[shdr_index];
572 assert(shdr.sh_flags & elf.SHF_ALLOC != 0);
573 const phndx = slice.items(.phndx)[shdr_index];
574 const maybe_phdr = if (phndx) |ndx| &self.phdrs.items[ndx] else null;
575
576 log.debug("allocated size {x} of {s}, needed size {x}", .{
577 self.allocatedSize(shdr.sh_offset),
578 self.getShString(shdr.sh_name),
579 needed_size,
580 });
581561
582 if (shdr.sh_type != elf.SHT_NOBITS) {562 if (shdr.sh_type != elf.SHT_NOBITS) {
583 const allocated_size = self.allocatedSize(shdr.sh_offset);563 const allocated_size = self.allocatedSize(shdr.sh_offset);
564 log.debug("allocated size {x} of '{s}', needed size {x}", .{
565 allocated_size,
566 self.getShString(shdr.sh_name),
567 needed_size,
568 });
569
584 if (needed_size > allocated_size) {570 if (needed_size > allocated_size) {
585 const existing_size = shdr.sh_size;571 const existing_size = shdr.sh_size;
586 shdr.sh_size = 0;572 shdr.sh_size = 0;
587 // Must move the entire section.573 // Must move the entire section.
588 const new_offset = try self.findFreeSpace(needed_size, min_alignment);574 const new_offset = try self.findFreeSpace(needed_size, min_alignment);
589575
590 log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{576 log.debug("moving '{s}' from 0x{x} to 0x{x}", .{
591 self.getShString(shdr.sh_name),577 self.getShString(shdr.sh_name),
578 shdr.sh_offset,
592 new_offset,579 new_offset,
593 new_offset + existing_size,
594 });580 });
595581
596 const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, existing_size);
597 // TODO figure out what to about this error condition - how to communicate it up.
598 if (amt != existing_size) return error.InputOutput;
599
600 shdr.sh_offset = new_offset;
601 if (maybe_phdr) |phdr| phdr.p_offset = new_offset;
602 } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {
603 try self.base.file.?.setEndPos(shdr.sh_offset + needed_size);
604 }
605 if (maybe_phdr) |phdr| phdr.p_filesz = needed_size;
606 }
607 shdr.sh_size = needed_size;
608 self.markDirty(shdr_index);
609}
610
611pub fn growNonAllocSection(
612 self: *Elf,
613 shdr_index: u32,
614 needed_size: u64,
615 min_alignment: u64,
616 requires_file_copy: bool,
617) !void {
618 const shdr = &self.sections.items(.shdr)[shdr_index];
619 assert(shdr.sh_flags & elf.SHF_ALLOC == 0);
620
621 const allocated_size = self.allocatedSize(shdr.sh_offset);
622 if (needed_size > allocated_size) {
623 const existing_size = shdr.sh_size;
624 shdr.sh_size = 0;
625 // Move all the symbols to a new file location.
626 const new_offset = try self.findFreeSpace(needed_size, min_alignment);
627
628 log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{
629 self.getShString(shdr.sh_name),
630 new_offset,
631 new_offset + existing_size,
632 });
633
634 if (requires_file_copy) {
635 const amt = try self.base.file.?.copyRangeAll(582 const amt = try self.base.file.?.copyRangeAll(
636 shdr.sh_offset,583 shdr.sh_offset,
637 self.base.file.?,584 self.base.file.?,
638 new_offset,585 new_offset,
639 existing_size,586 existing_size,
640 );587 );
588 // TODO figure out what to about this error condition - how to communicate it up.
641 if (amt != existing_size) return error.InputOutput;589 if (amt != existing_size) return error.InputOutput;
642 }
643590
644 shdr.sh_offset = new_offset;591 shdr.sh_offset = new_offset;
645 } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {592 } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {
646 try self.base.file.?.setEndPos(shdr.sh_offset + needed_size);593 try self.base.file.?.setEndPos(shdr.sh_offset + needed_size);
594 }
647 }595 }
596
648 shdr.sh_size = needed_size;597 shdr.sh_size = needed_size;
649 self.markDirty(shdr_index);598 self.markDirty(shdr_index);
650}599}
651600
652pub fn markDirty(self: *Elf, shdr_index: u32) void {601fn markDirty(self: *Elf, shdr_index: u32) void {
653 if (self.zigObjectPtr()) |zo| {602 if (self.zigObjectPtr()) |zo| {
654 for ([_]?Symbol.Index{603 for ([_]?Symbol.Index{
655 zo.debug_info_index,604 zo.debug_info_index,
...@@ -742,25 +691,27 @@ pub fn allocateChunk(self: *Elf, args: struct {...@@ -742,25 +691,27 @@ pub fn allocateChunk(self: *Elf, args: struct {
742 }691 }
743 };692 };
744693
745 log.debug("allocated chunk (size({x}),align({x})) at 0x{x} (file(0x{x}))", .{
746 args.size,
747 args.alignment.toByteUnits().?,
748 shdr.sh_addr + res.value,
749 shdr.sh_offset + res.value,
750 });
751
752 const expand_section = if (self.atom(res.placement)) |placement_atom|694 const expand_section = if (self.atom(res.placement)) |placement_atom|
753 placement_atom.nextAtom(self) == null695 placement_atom.nextAtom(self) == null
754 else696 else
755 true;697 true;
756 if (expand_section) {698 if (expand_section) {
757 const needed_size = res.value + args.size;699 const needed_size = res.value + args.size;
758 if (shdr.sh_flags & elf.SHF_ALLOC != 0)700 try self.growSection(args.shndx, needed_size, args.alignment.toByteUnits().?);
759 try self.growAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?)
760 else
761 try self.growNonAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?, true);
762 }701 }
763702
703 log.debug("allocated chunk (size({x}),align({x})) in {s} at 0x{x} (file(0x{x}))", .{
704 args.size,
705 args.alignment.toByteUnits().?,
706 self.getShString(shdr.sh_name),
707 shdr.sh_addr + res.value,
708 shdr.sh_offset + res.value,
709 });
710 log.debug(" placement {}, {s}", .{
711 res.placement,
712 if (self.atom(res.placement)) |atom_ptr| atom_ptr.name(self) else "",
713 });
714
764 return res;715 return res;
765}716}
766717
...@@ -809,8 +760,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -809,8 +760,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
809760
810 const csu = try CsuObjects.init(arena, comp);761 const csu = try CsuObjects.init(arena, comp);
811762
812 // Here we will parse object and library files (if referenced).
813
814 // csu prelude763 // csu prelude
815 if (csu.crt0) |path| try parseObjectReportingFailure(self, path);764 if (csu.crt0) |path| try parseObjectReportingFailure(self, path);
816 if (csu.crti) |path| try parseObjectReportingFailure(self, path);765 if (csu.crti) |path| try parseObjectReportingFailure(self, path);
...@@ -1040,6 +989,13 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -1040,6 +989,13 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
1040989
1041 // Beyond this point, everything has been allocated a virtual address and we can resolve990 // Beyond this point, everything has been allocated a virtual address and we can resolve
1042 // the relocations, and commit objects to file.991 // the relocations, and commit objects to file.
992 for (self.objects.items) |index| {
993 self.file(index).?.object.dirty = false;
994 }
995 // TODO: would state tracking be more appropriate here? perhaps even custom relocation type?
996 self.rela_dyn.clearRetainingCapacity();
997 self.rela_plt.clearRetainingCapacity();
998
1043 if (self.zigObjectPtr()) |zo| {999 if (self.zigObjectPtr()) |zo| {
1044 var has_reloc_errors = false;1000 var has_reloc_errors = false;
1045 for (zo.atoms_indexes.items) |atom_index| {1001 for (zo.atoms_indexes.items) |atom_index| {
...@@ -1069,6 +1025,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -1069,6 +1025,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
1069 try self.writeShdrTable();1025 try self.writeShdrTable();
1070 try self.writeAtoms();1026 try self.writeAtoms();
1071 try self.writeMergeSections();1027 try self.writeMergeSections();
1028
1072 self.writeSyntheticSections() catch |err| switch (err) {1029 self.writeSyntheticSections() catch |err| switch (err) {
1073 error.RelocFailure => return error.FlushFailure,1030 error.RelocFailure => return error.FlushFailure,
1074 error.UnsupportedCpuArch => {1031 error.UnsupportedCpuArch => {
...@@ -1401,7 +1358,6 @@ pub fn parseLibraryReportingFailure(self: *Elf, lib: SystemLib, must_link: bool)...@@ -1401,7 +1358,6 @@ pub fn parseLibraryReportingFailure(self: *Elf, lib: SystemLib, must_link: bool)
1401fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool) ParseError!void {1358fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool) ParseError!void {
1402 const tracy = trace(@src());1359 const tracy = trace(@src());
1403 defer tracy.end();1360 defer tracy.end();
1404
1405 if (try Archive.isArchive(lib.path)) {1361 if (try Archive.isArchive(lib.path)) {
1406 try self.parseArchive(lib.path, must_link);1362 try self.parseArchive(lib.path, must_link);
1407 } else if (try SharedObject.isSharedObject(lib.path)) {1363 } else if (try SharedObject.isSharedObject(lib.path)) {
...@@ -2801,9 +2757,10 @@ pub fn resolveMergeSections(self: *Elf) !void {...@@ -2801,9 +2757,10 @@ pub fn resolveMergeSections(self: *Elf) !void {
28012757
2802 var has_errors = false;2758 var has_errors = false;
2803 for (self.objects.items) |index| {2759 for (self.objects.items) |index| {
2804 const file_ptr = self.file(index).?;2760 const object = self.file(index).?.object;
2805 if (!file_ptr.isAlive()) continue;2761 if (!object.alive) continue;
2806 file_ptr.object.initInputMergeSections(self) catch |err| switch (err) {2762 if (!object.dirty) continue;
2763 object.initInputMergeSections(self) catch |err| switch (err) {
2807 error.LinkFailure => has_errors = true,2764 error.LinkFailure => has_errors = true,
2808 else => |e| return e,2765 else => |e| return e,
2809 };2766 };
...@@ -2812,15 +2769,17 @@ pub fn resolveMergeSections(self: *Elf) !void {...@@ -2812,15 +2769,17 @@ pub fn resolveMergeSections(self: *Elf) !void {
2812 if (has_errors) return error.FlushFailure;2769 if (has_errors) return error.FlushFailure;
28132770
2814 for (self.objects.items) |index| {2771 for (self.objects.items) |index| {
2815 const file_ptr = self.file(index).?;2772 const object = self.file(index).?.object;
2816 if (!file_ptr.isAlive()) continue;2773 if (!object.alive) continue;
2817 try file_ptr.object.initOutputMergeSections(self);2774 if (!object.dirty) continue;
2775 try object.initOutputMergeSections(self);
2818 }2776 }
28192777
2820 for (self.objects.items) |index| {2778 for (self.objects.items) |index| {
2821 const file_ptr = self.file(index).?;2779 const object = self.file(index).?.object;
2822 if (!file_ptr.isAlive()) continue;2780 if (!object.alive) continue;
2823 file_ptr.object.resolveMergeSubsections(self) catch |err| switch (err) {2781 if (!object.dirty) continue;
2782 object.resolveMergeSubsections(self) catch |err| switch (err) {
2824 error.LinkFailure => has_errors = true,2783 error.LinkFailure => has_errors = true,
2825 else => |e| return e,2784 else => |e| return e,
2826 };2785 };
...@@ -2907,7 +2866,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2907,7 +2866,6 @@ fn initSyntheticSections(self: *Elf) !void {
2907 elf.SHT_PROGBITS,2866 elf.SHT_PROGBITS,
2908 .flags = elf.SHF_ALLOC,2867 .flags = elf.SHF_ALLOC,
2909 .addralign = ptr_size,2868 .addralign = ptr_size,
2910 .offset = std.math.maxInt(u64),
2911 });2869 });
2912 }2870 }
2913 if (comp.link_eh_frame_hdr and self.eh_frame_hdr_section_index == null) {2871 if (comp.link_eh_frame_hdr and self.eh_frame_hdr_section_index == null) {
...@@ -2916,7 +2874,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2916,7 +2874,6 @@ fn initSyntheticSections(self: *Elf) !void {
2916 .type = elf.SHT_PROGBITS,2874 .type = elf.SHT_PROGBITS,
2917 .flags = elf.SHF_ALLOC,2875 .flags = elf.SHF_ALLOC,
2918 .addralign = 4,2876 .addralign = 4,
2919 .offset = std.math.maxInt(u64),
2920 });2877 });
2921 }2878 }
2922 }2879 }
...@@ -2927,7 +2884,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2927,7 +2884,6 @@ fn initSyntheticSections(self: *Elf) !void {
2927 .type = elf.SHT_PROGBITS,2884 .type = elf.SHT_PROGBITS,
2928 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,2885 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
2929 .addralign = ptr_size,2886 .addralign = ptr_size,
2930 .offset = std.math.maxInt(u64),
2931 });2887 });
2932 }2888 }
29332889
...@@ -2937,7 +2893,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2937,7 +2893,6 @@ fn initSyntheticSections(self: *Elf) !void {
2937 .type = elf.SHT_PROGBITS,2893 .type = elf.SHT_PROGBITS,
2938 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,2894 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
2939 .addralign = @alignOf(u64),2895 .addralign = @alignOf(u64),
2940 .offset = std.math.maxInt(u64),
2941 });2896 });
2942 }2897 }
29432898
...@@ -2959,7 +2914,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2959,7 +2914,6 @@ fn initSyntheticSections(self: *Elf) !void {
2959 .flags = elf.SHF_ALLOC,2914 .flags = elf.SHF_ALLOC,
2960 .addralign = @alignOf(elf.Elf64_Rela),2915 .addralign = @alignOf(elf.Elf64_Rela),
2961 .entsize = @sizeOf(elf.Elf64_Rela),2916 .entsize = @sizeOf(elf.Elf64_Rela),
2962 .offset = std.math.maxInt(u64),
2963 });2917 });
2964 }2918 }
29652919
...@@ -2970,7 +2924,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2970,7 +2924,6 @@ fn initSyntheticSections(self: *Elf) !void {
2970 .type = elf.SHT_PROGBITS,2924 .type = elf.SHT_PROGBITS,
2971 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,2925 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
2972 .addralign = 16,2926 .addralign = 16,
2973 .offset = std.math.maxInt(u64),
2974 });2927 });
2975 }2928 }
2976 if (self.rela_plt_section_index == null) {2929 if (self.rela_plt_section_index == null) {
...@@ -2980,7 +2933,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2980,7 +2933,6 @@ fn initSyntheticSections(self: *Elf) !void {
2980 .flags = elf.SHF_ALLOC,2933 .flags = elf.SHF_ALLOC,
2981 .addralign = @alignOf(elf.Elf64_Rela),2934 .addralign = @alignOf(elf.Elf64_Rela),
2982 .entsize = @sizeOf(elf.Elf64_Rela),2935 .entsize = @sizeOf(elf.Elf64_Rela),
2983 .offset = std.math.maxInt(u64),
2984 });2936 });
2985 }2937 }
2986 }2938 }
...@@ -2991,7 +2943,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2991,7 +2943,6 @@ fn initSyntheticSections(self: *Elf) !void {
2991 .type = elf.SHT_PROGBITS,2943 .type = elf.SHT_PROGBITS,
2992 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,2944 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
2993 .addralign = 16,2945 .addralign = 16,
2994 .offset = std.math.maxInt(u64),
2995 });2946 });
2996 }2947 }
29972948
...@@ -3000,7 +2951,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3000,7 +2951,6 @@ fn initSyntheticSections(self: *Elf) !void {
3000 .name = try self.insertShString(".copyrel"),2951 .name = try self.insertShString(".copyrel"),
3001 .type = elf.SHT_NOBITS,2952 .type = elf.SHT_NOBITS,
3002 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,2953 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
3003 .offset = std.math.maxInt(u64),
3004 });2954 });
3005 }2955 }
30062956
...@@ -3019,7 +2969,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3019,7 +2969,6 @@ fn initSyntheticSections(self: *Elf) !void {
3019 .type = elf.SHT_PROGBITS,2969 .type = elf.SHT_PROGBITS,
3020 .flags = elf.SHF_ALLOC,2970 .flags = elf.SHF_ALLOC,
3021 .addralign = 1,2971 .addralign = 1,
3022 .offset = std.math.maxInt(u64),
3023 });2972 });
3024 }2973 }
30252974
...@@ -3031,7 +2980,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3031,7 +2980,6 @@ fn initSyntheticSections(self: *Elf) !void {
3031 .type = elf.SHT_STRTAB,2980 .type = elf.SHT_STRTAB,
3032 .entsize = 1,2981 .entsize = 1,
3033 .addralign = 1,2982 .addralign = 1,
3034 .offset = std.math.maxInt(u64),
3035 });2983 });
3036 }2984 }
3037 if (self.dynamic_section_index == null) {2985 if (self.dynamic_section_index == null) {
...@@ -3041,7 +2989,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3041,7 +2989,6 @@ fn initSyntheticSections(self: *Elf) !void {
3041 .type = elf.SHT_DYNAMIC,2989 .type = elf.SHT_DYNAMIC,
3042 .entsize = @sizeOf(elf.Elf64_Dyn),2990 .entsize = @sizeOf(elf.Elf64_Dyn),
3043 .addralign = @alignOf(elf.Elf64_Dyn),2991 .addralign = @alignOf(elf.Elf64_Dyn),
3044 .offset = std.math.maxInt(u64),
3045 });2992 });
3046 }2993 }
3047 if (self.dynsymtab_section_index == null) {2994 if (self.dynsymtab_section_index == null) {
...@@ -3052,7 +2999,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3052,7 +2999,6 @@ fn initSyntheticSections(self: *Elf) !void {
3052 .addralign = @alignOf(elf.Elf64_Sym),2999 .addralign = @alignOf(elf.Elf64_Sym),
3053 .entsize = @sizeOf(elf.Elf64_Sym),3000 .entsize = @sizeOf(elf.Elf64_Sym),
3054 .info = 1,3001 .info = 1,
3055 .offset = std.math.maxInt(u64),
3056 });3002 });
3057 }3003 }
3058 if (self.hash_section_index == null) {3004 if (self.hash_section_index == null) {
...@@ -3062,7 +3008,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3062,7 +3008,6 @@ fn initSyntheticSections(self: *Elf) !void {
3062 .type = elf.SHT_HASH,3008 .type = elf.SHT_HASH,
3063 .addralign = 4,3009 .addralign = 4,
3064 .entsize = 4,3010 .entsize = 4,
3065 .offset = std.math.maxInt(u64),
3066 });3011 });
3067 }3012 }
3068 if (self.gnu_hash_section_index == null) {3013 if (self.gnu_hash_section_index == null) {
...@@ -3071,7 +3016,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3071,7 +3016,6 @@ fn initSyntheticSections(self: *Elf) !void {
3071 .flags = elf.SHF_ALLOC,3016 .flags = elf.SHF_ALLOC,
3072 .type = elf.SHT_GNU_HASH,3017 .type = elf.SHT_GNU_HASH,
3073 .addralign = 8,3018 .addralign = 8,
3074 .offset = std.math.maxInt(u64),
3075 });3019 });
3076 }3020 }
30773021
...@@ -3087,7 +3031,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3087,7 +3031,6 @@ fn initSyntheticSections(self: *Elf) !void {
3087 .type = elf.SHT_GNU_VERSYM,3031 .type = elf.SHT_GNU_VERSYM,
3088 .addralign = @alignOf(elf.Elf64_Versym),3032 .addralign = @alignOf(elf.Elf64_Versym),
3089 .entsize = @sizeOf(elf.Elf64_Versym),3033 .entsize = @sizeOf(elf.Elf64_Versym),
3090 .offset = std.math.maxInt(u64),
3091 });3034 });
3092 }3035 }
3093 if (self.verneed_section_index == null) {3036 if (self.verneed_section_index == null) {
...@@ -3096,7 +3039,6 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3096,7 +3039,6 @@ fn initSyntheticSections(self: *Elf) !void {
3096 .flags = elf.SHF_ALLOC,3039 .flags = elf.SHF_ALLOC,
3097 .type = elf.SHT_GNU_VERNEED,3040 .type = elf.SHT_GNU_VERNEED,
3098 .addralign = @alignOf(elf.Elf64_Verneed),3041 .addralign = @alignOf(elf.Elf64_Verneed),
3099 .offset = std.math.maxInt(u64),
3100 });3042 });
3101 }3043 }
3102 }3044 }
...@@ -3117,7 +3059,6 @@ pub fn initSymtab(self: *Elf) !void {...@@ -3117,7 +3059,6 @@ pub fn initSymtab(self: *Elf) !void {
3117 .type = elf.SHT_SYMTAB,3059 .type = elf.SHT_SYMTAB,
3118 .addralign = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym),3060 .addralign = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym),
3119 .entsize = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym),3061 .entsize = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym),
3120 .offset = std.math.maxInt(u64),
3121 });3062 });
3122 }3063 }
3123 if (self.strtab_section_index == null) {3064 if (self.strtab_section_index == null) {
...@@ -3126,7 +3067,6 @@ pub fn initSymtab(self: *Elf) !void {...@@ -3126,7 +3067,6 @@ pub fn initSymtab(self: *Elf) !void {
3126 .type = elf.SHT_STRTAB,3067 .type = elf.SHT_STRTAB,
3127 .entsize = 1,3068 .entsize = 1,
3128 .addralign = 1,3069 .addralign = 1,
3129 .offset = std.math.maxInt(u64),
3130 });3070 });
3131 }3071 }
3132}3072}
...@@ -3138,7 +3078,6 @@ pub fn initShStrtab(self: *Elf) !void {...@@ -3138,7 +3078,6 @@ pub fn initShStrtab(self: *Elf) !void {
3138 .type = elf.SHT_STRTAB,3078 .type = elf.SHT_STRTAB,
3139 .entsize = 1,3079 .entsize = 1,
3140 .addralign = 1,3080 .addralign = 1,
3141 .offset = std.math.maxInt(u64),
3142 });3081 });
3143 }3082 }
3144}3083}
...@@ -3219,7 +3158,7 @@ fn sortInitFini(self: *Elf) !void {...@@ -3219,7 +3158,7 @@ fn sortInitFini(self: *Elf) !void {
32193158
3220 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {3159 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {
3221 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;3160 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
3222 if (atom_list.atoms.items.len == 0) continue;3161 if (atom_list.atoms.keys().len == 0) continue;
32233162
3224 var is_init_fini = false;3163 var is_init_fini = false;
3225 var is_ctor_dtor = false;3164 var is_ctor_dtor = false;
...@@ -3236,10 +3175,10 @@ fn sortInitFini(self: *Elf) !void {...@@ -3236,10 +3175,10 @@ fn sortInitFini(self: *Elf) !void {
3236 if (!is_init_fini and !is_ctor_dtor) continue;3175 if (!is_init_fini and !is_ctor_dtor) continue;
32373176
3238 var entries = std.ArrayList(Entry).init(gpa);3177 var entries = std.ArrayList(Entry).init(gpa);
3239 try entries.ensureTotalCapacityPrecise(atom_list.atoms.items.len);3178 try entries.ensureTotalCapacityPrecise(atom_list.atoms.keys().len);
3240 defer entries.deinit();3179 defer entries.deinit();
32413180
3242 for (atom_list.atoms.items) |ref| {3181 for (atom_list.atoms.keys()) |ref| {
3243 const atom_ptr = self.atom(ref).?;3182 const atom_ptr = self.atom(ref).?;
3244 const object = atom_ptr.file(self).?.object;3183 const object = atom_ptr.file(self).?.object;
3245 const priority = blk: {3184 const priority = blk: {
...@@ -3260,7 +3199,7 @@ fn sortInitFini(self: *Elf) !void {...@@ -3260,7 +3199,7 @@ fn sortInitFini(self: *Elf) !void {
32603199
3261 atom_list.atoms.clearRetainingCapacity();3200 atom_list.atoms.clearRetainingCapacity();
3262 for (entries.items) |entry| {3201 for (entries.items) |entry| {
3263 atom_list.atoms.appendAssumeCapacity(entry.atom_ref);3202 _ = atom_list.atoms.getOrPutAssumeCapacity(entry.atom_ref);
3264 }3203 }
3265 }3204 }
3266}3205}
...@@ -3506,7 +3445,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {...@@ -3506,7 +3445,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
3506 const slice = self.sections.slice();3445 const slice = self.sections.slice();
3507 for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| {3446 for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| {
3508 atom_list.output_section_index = backlinks[atom_list.output_section_index];3447 atom_list.output_section_index = backlinks[atom_list.output_section_index];
3509 for (atom_list.atoms.items) |ref| {3448 for (atom_list.atoms.keys()) |ref| {
3510 self.atom(ref).?.output_section_index = atom_list.output_section_index;3449 self.atom(ref).?.output_section_index = atom_list.output_section_index;
3511 }3450 }
3512 if (shdr.sh_type == elf.SHT_RELA) {3451 if (shdr.sh_type == elf.SHT_RELA) {
...@@ -3518,12 +3457,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {...@@ -3518,12 +3457,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
3518 }3457 }
3519 }3458 }
35203459
3521 if (self.zigObjectPtr()) |zo| {3460 if (self.zigObjectPtr()) |zo| zo.resetShdrIndexes(backlinks);
3522 for (zo.atoms_indexes.items) |atom_index| {
3523 const atom_ptr = zo.atom(atom_index) orelse continue;
3524 atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];
3525 }
3526 }
35273461
3528 for (self.comdat_group_sections.items) |*cg| {3462 for (self.comdat_group_sections.items) |*cg| {
3529 cg.shndx = backlinks[cg.shndx];3463 cg.shndx = backlinks[cg.shndx];
...@@ -3585,20 +3519,24 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {...@@ -3585,20 +3519,24 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
3585fn updateSectionSizes(self: *Elf) !void {3519fn updateSectionSizes(self: *Elf) !void {
3586 const slice = self.sections.slice();3520 const slice = self.sections.slice();
3587 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {3521 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {
3588 if (atom_list.atoms.items.len == 0) continue;3522 if (atom_list.atoms.keys().len == 0) continue;
3523 if (!atom_list.dirty) continue;
3589 if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;3524 if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;
3590 atom_list.updateSize(self);3525 atom_list.updateSize(self);
3591 try atom_list.allocate(self);3526 try atom_list.allocate(self);
3527 atom_list.dirty = false;
3592 }3528 }
35933529
3594 if (self.requiresThunks()) {3530 if (self.requiresThunks()) {
3595 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {3531 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| {
3596 if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue;3532 if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue;
3597 if (atom_list.atoms.items.len == 0) continue;3533 if (atom_list.atoms.keys().len == 0) continue;
3534 if (!atom_list.dirty) continue;
35983535
3599 // Create jump/branch range extenders if needed.3536 // Create jump/branch range extenders if needed.
3600 try self.createThunks(atom_list);3537 try self.createThunks(atom_list);
3601 try atom_list.allocate(self);3538 try atom_list.allocate(self);
3539 atom_list.dirty = false;
3602 }3540 }
36033541
3604 // FIXME:JK this will hopefully not be needed once we create a link from Atom/Thunk to AtomList.3542 // FIXME:JK this will hopefully not be needed once we create a link from Atom/Thunk to AtomList.
...@@ -3882,57 +3820,55 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -3882,57 +3820,55 @@ pub fn allocateAllocSections(self: *Elf) !void {
3882 }3820 }
38833821
3884 const first = slice.items(.shdr)[cover.items[0]];3822 const first = slice.items(.shdr)[cover.items[0]];
3885 var new_offset = try self.findFreeSpace(filesz, @"align");
3886 const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).?;3823 const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).?;
3887 const phdr = &self.phdrs.items[phndx];3824 const phdr = &self.phdrs.items[phndx];
3888 phdr.p_offset = new_offset;3825 const allocated_size = self.allocatedSize(phdr.p_offset);
3889 phdr.p_vaddr = first.sh_addr;3826 if (filesz > allocated_size) {
3890 phdr.p_paddr = first.sh_addr;3827 const old_offset = phdr.p_offset;
3891 phdr.p_memsz = memsz;3828 phdr.p_offset = 0;
3892 phdr.p_filesz = filesz;3829 var new_offset = try self.findFreeSpace(filesz, @"align");
3893 phdr.p_align = @"align";3830 phdr.p_offset = new_offset;
3831
3832 log.debug("moving phdr({d}) from 0x{x} to 0x{x}", .{ phndx, old_offset, new_offset });
3833
3834 for (cover.items) |shndx| {
3835 const shdr = &slice.items(.shdr)[shndx];
3836 slice.items(.phndx)[shndx] = phndx;
3837 if (shdr.sh_type == elf.SHT_NOBITS) {
3838 shdr.sh_offset = 0;
3839 continue;
3840 }
3841 new_offset = alignment.@"align"(shndx, shdr.sh_addralign, new_offset);
38943842
3895 for (cover.items) |shndx| {
3896 const shdr = &slice.items(.shdr)[shndx];
3897 slice.items(.phndx)[shndx] = phndx;
3898 if (shdr.sh_type == elf.SHT_NOBITS) {
3899 shdr.sh_offset = 0;
3900 continue;
3901 }
3902 new_offset = alignment.@"align"(shndx, shdr.sh_addralign, new_offset);
3903
3904 if (self.zigObjectPtr()) |zo| blk: {
3905 const existing_size = for ([_]?Symbol.Index{
3906 zo.text_index,
3907 zo.rodata_index,
3908 zo.data_relro_index,
3909 zo.data_index,
3910 zo.tdata_index,
3911 zo.eh_frame_index,
3912 }) |maybe_sym_index| {
3913 const sect_sym_index = maybe_sym_index orelse continue;
3914 const sect_atom_ptr = zo.symbol(sect_sym_index).atom(self).?;
3915 if (sect_atom_ptr.output_section_index != shndx) continue;
3916 break sect_atom_ptr.size;
3917 } else break :blk;
3918 log.debug("moving {s} from 0x{x} to 0x{x}", .{3843 log.debug("moving {s} from 0x{x} to 0x{x}", .{
3919 self.getShString(shdr.sh_name),3844 self.getShString(shdr.sh_name),
3920 shdr.sh_offset,3845 shdr.sh_offset,
3921 new_offset,3846 new_offset,
3922 });3847 });
3923 const amt = try self.base.file.?.copyRangeAll(
3924 shdr.sh_offset,
3925 self.base.file.?,
3926 new_offset,
3927 existing_size,
3928 );
3929 if (amt != existing_size) return error.InputOutput;
3930 }
39313848
3932 shdr.sh_offset = new_offset;3849 if (shdr.sh_offset > 0) {
3933 new_offset += shdr.sh_size;3850 // Get size actually commited to the output file.
3851 const existing_size = self.sectionSize(shndx);
3852 const amt = try self.base.file.?.copyRangeAll(
3853 shdr.sh_offset,
3854 self.base.file.?,
3855 new_offset,
3856 existing_size,
3857 );
3858 if (amt != existing_size) return error.InputOutput;
3859 }
3860
3861 shdr.sh_offset = new_offset;
3862 new_offset += shdr.sh_size;
3863 }
3934 }3864 }
39353865
3866 phdr.p_vaddr = first.sh_addr;
3867 phdr.p_paddr = first.sh_addr;
3868 phdr.p_memsz = memsz;
3869 phdr.p_filesz = filesz;
3870 phdr.p_align = @"align";
3871
3936 addr = mem.alignForward(u64, addr, self.page_size);3872 addr = mem.alignForward(u64, addr, self.page_size);
3937 }3873 }
3938}3874}
...@@ -3947,27 +3883,14 @@ pub fn allocateNonAllocSections(self: *Elf) !void {...@@ -3947,27 +3883,14 @@ pub fn allocateNonAllocSections(self: *Elf) !void {
3947 shdr.sh_size = 0;3883 shdr.sh_size = 0;
3948 const new_offset = try self.findFreeSpace(needed_size, shdr.sh_addralign);3884 const new_offset = try self.findFreeSpace(needed_size, shdr.sh_addralign);
39493885
3950 if (self.zigObjectPtr()) |zo| blk: {3886 log.debug("moving {s} from 0x{x} to 0x{x}", .{
3951 const existing_size = for ([_]?Symbol.Index{3887 self.getShString(shdr.sh_name),
3952 zo.debug_info_index,3888 shdr.sh_offset,
3953 zo.debug_abbrev_index,3889 new_offset,
3954 zo.debug_aranges_index,3890 });
3955 zo.debug_str_index,3891
3956 zo.debug_line_index,3892 if (shdr.sh_offset > 0) {
3957 zo.debug_line_str_index,3893 const existing_size = self.sectionSize(@intCast(shndx));
3958 zo.debug_loclists_index,
3959 zo.debug_rnglists_index,
3960 }) |maybe_sym_index| {
3961 const sym_index = maybe_sym_index orelse continue;
3962 const sym = zo.symbol(sym_index);
3963 const atom_ptr = sym.atom(self).?;
3964 if (atom_ptr.output_section_index == shndx) break atom_ptr.size;
3965 } else break :blk;
3966 log.debug("moving {s} from 0x{x} to 0x{x}", .{
3967 self.getShString(shdr.sh_name),
3968 shdr.sh_offset,
3969 new_offset,
3970 });
3971 const amt = try self.base.file.?.copyRangeAll(3894 const amt = try self.base.file.?.copyRangeAll(
3972 shdr.sh_offset,3895 shdr.sh_offset,
3973 self.base.file.?,3896 self.base.file.?,
...@@ -4058,7 +3981,7 @@ fn writeAtoms(self: *Elf) !void {...@@ -4058,7 +3981,7 @@ fn writeAtoms(self: *Elf) !void {
4058 var has_reloc_errors = false;3981 var has_reloc_errors = false;
4059 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {3982 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {
4060 if (shdr.sh_type == elf.SHT_NOBITS) continue;3983 if (shdr.sh_type == elf.SHT_NOBITS) continue;
4061 if (atom_list.atoms.items.len == 0) continue;3984 if (atom_list.atoms.keys().len == 0) continue;
4062 atom_list.write(&buffer, &undefs, self) catch |err| switch (err) {3985 atom_list.write(&buffer, &undefs, self) catch |err| switch (err) {
4063 error.UnsupportedCpuArch => {3986 error.UnsupportedCpuArch => {
4064 try self.reportUnsupportedCpuArch();3987 try self.reportUnsupportedCpuArch();
...@@ -4816,7 +4739,6 @@ pub fn addRelaShdr(self: *Elf, name: u32, shndx: u32) !u32 {...@@ -4816,7 +4739,6 @@ pub fn addRelaShdr(self: *Elf, name: u32, shndx: u32) !u32 {
4816 .entsize = entsize,4739 .entsize = entsize,
4817 .info = shndx,4740 .info = shndx,
4818 .addralign = addralign,4741 .addralign = addralign,
4819 .offset = std.math.maxInt(u64),
4820 });4742 });
4821}4743}
48224744
...@@ -4828,7 +4750,6 @@ pub const AddSectionOpts = struct {...@@ -4828,7 +4750,6 @@ pub const AddSectionOpts = struct {
4828 info: u32 = 0,4750 info: u32 = 0,
4829 addralign: u64 = 0,4751 addralign: u64 = 0,
4830 entsize: u64 = 0,4752 entsize: u64 = 0,
4831 offset: u64 = 0,
4832};4753};
48334754
4834pub fn addSection(self: *Elf, opts: AddSectionOpts) !u32 {4755pub fn addSection(self: *Elf, opts: AddSectionOpts) !u32 {
...@@ -4840,7 +4761,7 @@ pub fn addSection(self: *Elf, opts: AddSectionOpts) !u32 {...@@ -4840,7 +4761,7 @@ pub fn addSection(self: *Elf, opts: AddSectionOpts) !u32 {
4840 .sh_type = opts.type,4761 .sh_type = opts.type,
4841 .sh_flags = opts.flags,4762 .sh_flags = opts.flags,
4842 .sh_addr = 0,4763 .sh_addr = 0,
4843 .sh_offset = opts.offset,4764 .sh_offset = 0,
4844 .sh_size = 0,4765 .sh_size = 0,
4845 .sh_link = opts.link,4766 .sh_link = opts.link,
4846 .sh_info = opts.info,4767 .sh_info = opts.info,
...@@ -4863,6 +4784,7 @@ const RelaDyn = struct {...@@ -4863,6 +4784,7 @@ const RelaDyn = struct {
4863 sym: u64 = 0,4784 sym: u64 = 0,
4864 type: u32,4785 type: u32,
4865 addend: i64 = 0,4786 addend: i64 = 0,
4787 target: ?*const Symbol = null,
4866};4788};
48674789
4868pub fn addRelaDyn(self: *Elf, opts: RelaDyn) !void {4790pub fn addRelaDyn(self: *Elf, opts: RelaDyn) !void {
...@@ -4871,6 +4793,13 @@ pub fn addRelaDyn(self: *Elf, opts: RelaDyn) !void {...@@ -4871,6 +4793,13 @@ pub fn addRelaDyn(self: *Elf, opts: RelaDyn) !void {
4871}4793}
48724794
4873pub fn addRelaDynAssumeCapacity(self: *Elf, opts: RelaDyn) void {4795pub fn addRelaDynAssumeCapacity(self: *Elf, opts: RelaDyn) void {
4796 relocs_log.debug(" {s}: [{x} => {d}({s})] + {x}", .{
4797 relocation.fmtRelocType(opts.type, self.getTarget().cpu.arch),
4798 opts.offset,
4799 opts.sym,
4800 if (opts.target) |sym| sym.name(self) else "",
4801 opts.addend,
4802 });
4874 self.rela_dyn.appendAssumeCapacity(.{4803 self.rela_dyn.appendAssumeCapacity(.{
4875 .r_offset = opts.offset,4804 .r_offset = opts.offset,
4876 .r_info = (opts.sym << 32) | opts.type,4805 .r_info = (opts.sym << 32) | opts.type,
...@@ -5703,6 +5632,12 @@ const Section = struct {...@@ -5703,6 +5632,12 @@ const Section = struct {
5703 free_list: std.ArrayListUnmanaged(Ref) = .empty,5632 free_list: std.ArrayListUnmanaged(Ref) = .empty,
5704};5633};
57055634
5635pub fn sectionSize(self: *Elf, shndx: u32) u64 {
5636 const last_atom_ref = self.sections.items(.last_atom)[shndx];
5637 const atom_ptr = self.atom(last_atom_ref) orelse return 0;
5638 return @as(u64, @intCast(atom_ptr.value)) + atom_ptr.size;
5639}
5640
5706fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {5641fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {
5707 return switch (cpu_arch) {5642 return switch (cpu_arch) {
5708 .mips, .mipsel, .mips64, .mips64el => "__start",5643 .mips, .mipsel, .mips64, .mips64el => "__start",
...@@ -5732,20 +5667,20 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {...@@ -5732,20 +5667,20 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
5732 }5667 }
5733 }.advance;5668 }.advance;
57345669
5735 for (atom_list.atoms.items) |ref| {5670 for (atom_list.atoms.keys()) |ref| {
5736 elf_file.atom(ref).?.value = -1;5671 elf_file.atom(ref).?.value = -1;
5737 }5672 }
57385673
5739 var i: usize = 0;5674 var i: usize = 0;
5740 while (i < atom_list.atoms.items.len) {5675 while (i < atom_list.atoms.keys().len) {
5741 const start = i;5676 const start = i;
5742 const start_atom = elf_file.atom(atom_list.atoms.items[start]).?;5677 const start_atom = elf_file.atom(atom_list.atoms.keys()[start]).?;
5743 assert(start_atom.alive);5678 assert(start_atom.alive);
5744 start_atom.value = try advance(atom_list, start_atom.size, start_atom.alignment);5679 start_atom.value = try advance(atom_list, start_atom.size, start_atom.alignment);
5745 i += 1;5680 i += 1;
57465681
5747 while (i < atom_list.atoms.items.len) : (i += 1) {5682 while (i < atom_list.atoms.keys().len) : (i += 1) {
5748 const atom_ptr = elf_file.atom(atom_list.atoms.items[i]).?;5683 const atom_ptr = elf_file.atom(atom_list.atoms.keys()[i]).?;
5749 assert(atom_ptr.alive);5684 assert(atom_ptr.alive);
5750 if (@as(i64, @intCast(atom_ptr.alignment.forward(atom_list.size))) - start_atom.value >= max_distance)5685 if (@as(i64, @intCast(atom_ptr.alignment.forward(atom_list.size))) - start_atom.value >= max_distance)
5751 break;5686 break;
...@@ -5758,7 +5693,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {...@@ -5758,7 +5693,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void {
5758 thunk_ptr.output_section_index = atom_list.output_section_index;5693 thunk_ptr.output_section_index = atom_list.output_section_index;
57595694
5760 // Scan relocs in the group and create trampolines for any unreachable callsite5695 // Scan relocs in the group and create trampolines for any unreachable callsite
5761 for (atom_list.atoms.items[start..i]) |ref| {5696 for (atom_list.atoms.keys()[start..i]) |ref| {
5762 const atom_ptr = elf_file.atom(ref).?;5697 const atom_ptr = elf_file.atom(ref).?;
5763 const file_ptr = atom_ptr.file(elf_file).?;5698 const file_ptr = atom_ptr.file(elf_file).?;
5764 log.debug("atom({}) {s}", .{ ref, atom_ptr.name(elf_file) });5699 log.debug("atom({}) {s}", .{ ref, atom_ptr.name(elf_file) });
...@@ -5801,6 +5736,7 @@ const assert = std.debug.assert;...@@ -5801,6 +5736,7 @@ const assert = std.debug.assert;
5801const elf = std.elf;5736const elf = std.elf;
5802const fs = std.fs;5737const fs = std.fs;
5803const log = std.log.scoped(.link);5738const log = std.log.scoped(.link);
5739const relocs_log = std.log.scoped(.link_relocs);
5804const state_log = std.log.scoped(.link_state);5740const state_log = std.log.scoped(.link_state);
5805const math = std.math;5741const math = std.math;
5806const mem = std.mem;5742const mem = std.mem;
src/link/Elf/Atom.zig+17-2
...@@ -118,10 +118,19 @@ pub fn capacity(self: Atom, elf_file: *Elf) u64 {...@@ -118,10 +118,19 @@ pub fn capacity(self: Atom, elf_file: *Elf) u64 {
118 return @intCast(next_addr - self.address(elf_file));118 return @intCast(next_addr - self.address(elf_file));
119}119}
120120
121pub fn fileCapacity(self: Atom, elf_file: *Elf) u64 {
122 const self_off = self.offset(elf_file);
123 const next_off = if (self.nextAtom(elf_file)) |next_atom|
124 next_atom.offset(elf_file)
125 else
126 self_off + elf_file.allocatedSize(self_off);
127 return @intCast(next_off - self_off);
128}
129
121pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {130pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
122 // No need to keep a free list node for the last block.131 // No need to keep a free list node for the last block.
123 const next = self.nextAtom(elf_file) orelse return false;132 const next = self.nextAtom(elf_file) orelse return false;
124 const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file));133 const cap: u64 = @intCast(next.value - self.value);
125 const ideal_cap = Elf.padToIdeal(self.size);134 const ideal_cap = Elf.padToIdeal(self.size);
126 if (cap <= ideal_cap) return false;135 if (cap <= ideal_cap) return false;
127 const surplus = cap - ideal_cap;136 const surplus = cap - ideal_cap;
...@@ -723,6 +732,7 @@ fn resolveDynAbsReloc(...@@ -723,6 +732,7 @@ fn resolveDynAbsReloc(
723 .sym = target.extra(elf_file).dynamic,732 .sym = target.extra(elf_file).dynamic,
724 .type = relocation.encode(.abs, cpu_arch),733 .type = relocation.encode(.abs, cpu_arch),
725 .addend = A,734 .addend = A,
735 .target = target,
726 });736 });
727 try applyDynamicReloc(A, elf_file, writer);737 try applyDynamicReloc(A, elf_file, writer);
728 } else {738 } else {
...@@ -737,6 +747,7 @@ fn resolveDynAbsReloc(...@@ -737,6 +747,7 @@ fn resolveDynAbsReloc(
737 .sym = target.extra(elf_file).dynamic,747 .sym = target.extra(elf_file).dynamic,
738 .type = relocation.encode(.abs, cpu_arch),748 .type = relocation.encode(.abs, cpu_arch),
739 .addend = A,749 .addend = A,
750 .target = target,
740 });751 });
741 try applyDynamicReloc(A, elf_file, writer);752 try applyDynamicReloc(A, elf_file, writer);
742 } else {753 } else {
...@@ -750,6 +761,7 @@ fn resolveDynAbsReloc(...@@ -750,6 +761,7 @@ fn resolveDynAbsReloc(
750 .sym = target.extra(elf_file).dynamic,761 .sym = target.extra(elf_file).dynamic,
751 .type = relocation.encode(.abs, cpu_arch),762 .type = relocation.encode(.abs, cpu_arch),
752 .addend = A,763 .addend = A,
764 .target = target,
753 });765 });
754 try applyDynamicReloc(A, elf_file, writer);766 try applyDynamicReloc(A, elf_file, writer);
755 },767 },
...@@ -759,6 +771,7 @@ fn resolveDynAbsReloc(...@@ -759,6 +771,7 @@ fn resolveDynAbsReloc(
759 .offset = P,771 .offset = P,
760 .type = relocation.encode(.rel, cpu_arch),772 .type = relocation.encode(.rel, cpu_arch),
761 .addend = S + A,773 .addend = S + A,
774 .target = target,
762 });775 });
763 try applyDynamicReloc(S + A, elf_file, writer);776 try applyDynamicReloc(S + A, elf_file, writer);
764 },777 },
...@@ -769,6 +782,7 @@ fn resolveDynAbsReloc(...@@ -769,6 +782,7 @@ fn resolveDynAbsReloc(
769 .offset = P,782 .offset = P,
770 .type = relocation.encode(.irel, cpu_arch),783 .type = relocation.encode(.irel, cpu_arch),
771 .addend = S_ + A,784 .addend = S_ + A,
785 .target = target,
772 });786 });
773 try applyDynamicReloc(S_ + A, elf_file, writer);787 try applyDynamicReloc(S_ + A, elf_file, writer);
774 },788 },
...@@ -922,9 +936,10 @@ fn format2(...@@ -922,9 +936,10 @@ fn format2(
922 _ = unused_fmt_string;936 _ = unused_fmt_string;
923 const atom = ctx.atom;937 const atom = ctx.atom;
924 const elf_file = ctx.elf_file;938 const elf_file = ctx.elf_file;
925 try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x})", .{939 try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x}) : prev({}) : next({})", .{
926 atom.atom_index, atom.name(elf_file), atom.address(elf_file),940 atom.atom_index, atom.name(elf_file), atom.address(elf_file),
927 atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size,941 atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size,
942 atom.prev_atom_ref, atom.next_atom_ref,
928 });943 });
929 if (atom.fdes(elf_file).len > 0) {944 if (atom.fdes(elf_file).len > 0) {
930 try writer.writeAll(" : fdes{ ");945 try writer.writeAll(" : fdes{ ");
src/link/Elf/AtomList.zig+27-19
...@@ -2,7 +2,10 @@ value: i64 = 0,...@@ -2,7 +2,10 @@ value: i64 = 0,
2size: u64 = 0,2size: u64 = 0,
3alignment: Atom.Alignment = .@"1",3alignment: Atom.Alignment = .@"1",
4output_section_index: u32 = 0,4output_section_index: u32 = 0,
5atoms: std.ArrayListUnmanaged(Elf.Ref) = .empty,5// atoms: std.ArrayListUnmanaged(Elf.Ref) = .empty,
6atoms: std.AutoArrayHashMapUnmanaged(Elf.Ref, void) = .empty,
7
8dirty: bool = true,
69
7pub fn deinit(list: *AtomList, allocator: Allocator) void {10pub fn deinit(list: *AtomList, allocator: Allocator) void {
8 list.atoms.deinit(allocator);11 list.atoms.deinit(allocator);
...@@ -19,10 +22,8 @@ pub fn offset(list: AtomList, elf_file: *Elf) u64 {...@@ -19,10 +22,8 @@ pub fn offset(list: AtomList, elf_file: *Elf) u64 {
19}22}
2023
21pub fn updateSize(list: *AtomList, elf_file: *Elf) void {24pub fn updateSize(list: *AtomList, elf_file: *Elf) void {
22 // TODO perhaps a 'stale' flag would be better here?25 assert(list.dirty);
23 list.size = 0;26 for (list.atoms.keys()) |ref| {
24 list.alignment = .@"1";
25 for (list.atoms.items) |ref| {
26 const atom_ptr = elf_file.atom(ref).?;27 const atom_ptr = elf_file.atom(ref).?;
27 assert(atom_ptr.alive);28 assert(atom_ptr.alive);
28 const off = atom_ptr.alignment.forward(list.size);29 const off = atom_ptr.alignment.forward(list.size);
...@@ -34,6 +35,8 @@ pub fn updateSize(list: *AtomList, elf_file: *Elf) void {...@@ -34,6 +35,8 @@ pub fn updateSize(list: *AtomList, elf_file: *Elf) void {
34}35}
3536
36pub fn allocate(list: *AtomList, elf_file: *Elf) !void {37pub fn allocate(list: *AtomList, elf_file: *Elf) !void {
38 assert(list.dirty);
39
37 const alloc_res = try elf_file.allocateChunk(.{40 const alloc_res = try elf_file.allocateChunk(.{
38 .shndx = list.output_section_index,41 .shndx = list.output_section_index,
39 .size = list.size,42 .size = list.size,
...@@ -42,6 +45,8 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {...@@ -42,6 +45,8 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {
42 });45 });
43 list.value = @intCast(alloc_res.value);46 list.value = @intCast(alloc_res.value);
4447
48 log.debug("allocated atom_list({d}) at 0x{x}", .{ list.output_section_index, list.address(elf_file) });
49
45 const slice = elf_file.sections.slice();50 const slice = elf_file.sections.slice();
46 const shdr = &slice.items(.shdr)[list.output_section_index];51 const shdr = &slice.items(.shdr)[list.output_section_index];
47 const last_atom_ref = &slice.items(.last_atom)[list.output_section_index];52 const last_atom_ref = &slice.items(.last_atom)[list.output_section_index];
...@@ -56,13 +61,13 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {...@@ -56,13 +61,13 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {
56 // FIXME:JK this currently ignores Thunks as valid chunks.61 // FIXME:JK this currently ignores Thunks as valid chunks.
57 {62 {
58 var idx: usize = 0;63 var idx: usize = 0;
59 while (idx < list.atoms.items.len) : (idx += 1) {64 while (idx < list.atoms.keys().len) : (idx += 1) {
60 const curr_atom_ptr = elf_file.atom(list.atoms.items[idx]).?;65 const curr_atom_ptr = elf_file.atom(list.atoms.keys()[idx]).?;
61 if (idx > 0) {66 if (idx > 0) {
62 curr_atom_ptr.prev_atom_ref = list.atoms.items[idx - 1];67 curr_atom_ptr.prev_atom_ref = list.atoms.keys()[idx - 1];
63 }68 }
64 if (idx + 1 < list.atoms.items.len) {69 if (idx + 1 < list.atoms.keys().len) {
65 curr_atom_ptr.next_atom_ref = list.atoms.items[idx + 1];70 curr_atom_ptr.next_atom_ref = list.atoms.keys()[idx + 1];
66 }71 }
67 }72 }
68 }73 }
...@@ -74,17 +79,20 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {...@@ -74,17 +79,20 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {
74 }79 }
7580
76 // FIXME:JK if we had a link from Atom to parent AtomList we would not need to update Atom's value or osec index81 // FIXME:JK if we had a link from Atom to parent AtomList we would not need to update Atom's value or osec index
77 for (list.atoms.items) |ref| {82 for (list.atoms.keys()) |ref| {
78 const atom_ptr = elf_file.atom(ref).?;83 const atom_ptr = elf_file.atom(ref).?;
79 atom_ptr.output_section_index = list.output_section_index;84 atom_ptr.output_section_index = list.output_section_index;
80 atom_ptr.value += list.value;85 atom_ptr.value += list.value;
81 }86 }
87
88 list.dirty = false;
82}89}
8390
84pub fn write(list: AtomList, buffer: *std.ArrayList(u8), undefs: anytype, elf_file: *Elf) !void {91pub fn write(list: AtomList, buffer: *std.ArrayList(u8), undefs: anytype, elf_file: *Elf) !void {
85 const gpa = elf_file.base.comp.gpa;92 const gpa = elf_file.base.comp.gpa;
86 const osec = elf_file.sections.items(.shdr)[list.output_section_index];93 const osec = elf_file.sections.items(.shdr)[list.output_section_index];
87 assert(osec.sh_type != elf.SHT_NOBITS);94 assert(osec.sh_type != elf.SHT_NOBITS);
95 assert(!list.dirty);
8896
89 log.debug("writing atoms in section '{s}'", .{elf_file.getShString(osec.sh_name)});97 log.debug("writing atoms in section '{s}'", .{elf_file.getShString(osec.sh_name)});
9098
...@@ -92,7 +100,7 @@ pub fn write(list: AtomList, buffer: *std.ArrayList(u8), undefs: anytype, elf_fi...@@ -92,7 +100,7 @@ pub fn write(list: AtomList, buffer: *std.ArrayList(u8), undefs: anytype, elf_fi
92 try buffer.ensureUnusedCapacity(list_size);100 try buffer.ensureUnusedCapacity(list_size);
93 buffer.appendNTimesAssumeCapacity(0, list_size);101 buffer.appendNTimesAssumeCapacity(0, list_size);
94102
95 for (list.atoms.items) |ref| {103 for (list.atoms.keys()) |ref| {
96 const atom_ptr = elf_file.atom(ref).?;104 const atom_ptr = elf_file.atom(ref).?;
97 assert(atom_ptr.alive);105 assert(atom_ptr.alive);
98106
...@@ -128,7 +136,7 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E...@@ -128,7 +136,7 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E
128 try buffer.ensureUnusedCapacity(list_size);136 try buffer.ensureUnusedCapacity(list_size);
129 buffer.appendNTimesAssumeCapacity(0, list_size);137 buffer.appendNTimesAssumeCapacity(0, list_size);
130138
131 for (list.atoms.items) |ref| {139 for (list.atoms.keys()) |ref| {
132 const atom_ptr = elf_file.atom(ref).?;140 const atom_ptr = elf_file.atom(ref).?;
133 assert(atom_ptr.alive);141 assert(atom_ptr.alive);
134142
...@@ -149,13 +157,13 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E...@@ -149,13 +157,13 @@ pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *E
149}157}
150158
151pub fn firstAtom(list: AtomList, elf_file: *Elf) *Atom {159pub fn firstAtom(list: AtomList, elf_file: *Elf) *Atom {
152 assert(list.atoms.items.len > 0);160 assert(list.atoms.keys().len > 0);
153 return elf_file.atom(list.atoms.items[0]).?;161 return elf_file.atom(list.atoms.keys()[0]).?;
154}162}
155163
156pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom {164pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom {
157 assert(list.atoms.items.len > 0);165 assert(list.atoms.keys().len > 0);
158 return elf_file.atom(list.atoms.items[list.atoms.items.len - 1]).?;166 return elf_file.atom(list.atoms.keys()[list.atoms.keys().len - 1]).?;
159}167}
160168
161pub fn format(169pub fn format(
...@@ -191,9 +199,9 @@ fn format2(...@@ -191,9 +199,9 @@ fn format2(
191 list.alignment.toByteUnits() orelse 0, list.size,199 list.alignment.toByteUnits() orelse 0, list.size,
192 });200 });
193 try writer.writeAll(" : atoms{ ");201 try writer.writeAll(" : atoms{ ");
194 for (list.atoms.items, 0..) |ref, i| {202 for (list.atoms.keys(), 0..) |ref, i| {
195 try writer.print("{}", .{ref});203 try writer.print("{}", .{ref});
196 if (i < list.atoms.items.len - 1) try writer.writeAll(", ");204 if (i < list.atoms.keys().len - 1) try writer.writeAll(", ");
197 }205 }
198 try writer.writeAll(" }");206 try writer.writeAll(" }");
199}207}
src/link/Elf/Object.zig+2-1
...@@ -29,6 +29,7 @@ cies: std.ArrayListUnmanaged(Cie) = .empty,...@@ -29,6 +29,7 @@ cies: std.ArrayListUnmanaged(Cie) = .empty,
29eh_frame_data: std.ArrayListUnmanaged(u8) = .empty,29eh_frame_data: std.ArrayListUnmanaged(u8) = .empty,
3030
31alive: bool = true,31alive: bool = true,
32dirty: bool = true,
32num_dynrelocs: u32 = 0,33num_dynrelocs: u32 = 0,
3334
34output_symtab_ctx: Elf.SymtabCtx = .{},35output_symtab_ctx: Elf.SymtabCtx = .{},
...@@ -917,7 +918,7 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void {...@@ -917,7 +918,7 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void {
917 });918 });
918 const atom_list = &elf_file.sections.items(.atom_list_2)[osec];919 const atom_list = &elf_file.sections.items(.atom_list_2)[osec];
919 atom_list.output_section_index = osec;920 atom_list.output_section_index = osec;
920 try atom_list.atoms.append(elf_file.base.comp.gpa, atom_ptr.ref());921 _ = try atom_list.atoms.getOrPut(elf_file.base.comp.gpa, atom_ptr.ref());
921 }922 }
922}923}
923924
src/link/Elf/Symbol.zig+10-5
...@@ -112,13 +112,16 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool...@@ -112,13 +112,16 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool
112 if (symbol.flags.has_trampoline and opts.trampoline) {112 if (symbol.flags.has_trampoline and opts.trampoline) {
113 return symbol.trampolineAddress(elf_file);113 return symbol.trampolineAddress(elf_file);
114 }114 }
115 if (symbol.flags.has_plt and opts.plt) {115 if (opts.plt) {
116 if (!symbol.flags.is_canonical and symbol.flags.has_got) {116 if (symbol.flags.has_pltgot) {
117 assert(!symbol.flags.is_canonical);
117 // We have a non-lazy bound function pointer, use that!118 // We have a non-lazy bound function pointer, use that!
118 return symbol.pltGotAddress(elf_file);119 return symbol.pltGotAddress(elf_file);
119 }120 }
120 // Lazy-bound function it is!121 if (symbol.flags.has_plt) {
121 return symbol.pltAddress(elf_file);122 // Lazy-bound function it is!
123 return symbol.pltAddress(elf_file);
124 }
122 }125 }
123 if (symbol.atom(elf_file)) |atom_ptr| {126 if (symbol.atom(elf_file)) |atom_ptr| {
124 if (!atom_ptr.alive) {127 if (!atom_ptr.alive) {
...@@ -171,7 +174,7 @@ pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 {...@@ -171,7 +174,7 @@ pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 {
171}174}
172175
173pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {176pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
174 if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0;177 if (!symbol.flags.has_pltgot) return 0;
175 const extras = symbol.extra(elf_file);178 const extras = symbol.extra(elf_file);
176 const shdr = elf_file.sections.items(.shdr)[elf_file.plt_got_section_index.?];179 const shdr = elf_file.sections.items(.shdr)[elf_file.plt_got_section_index.?];
177 const cpu_arch = elf_file.getTarget().cpu.arch;180 const cpu_arch = elf_file.getTarget().cpu.arch;
...@@ -430,6 +433,8 @@ pub const Flags = packed struct {...@@ -430,6 +433,8 @@ pub const Flags = packed struct {
430 has_plt: bool = false,433 has_plt: bool = false,
431 /// Whether the PLT entry is canonical.434 /// Whether the PLT entry is canonical.
432 is_canonical: bool = false,435 is_canonical: bool = false,
436 /// Whether the PLT entry is indirected via GOT.
437 has_pltgot: bool = false,
433438
434 /// Whether the symbol contains COPYREL directive.439 /// Whether the symbol contains COPYREL directive.
435 needs_copy_rel: bool = false,440 needs_copy_rel: bool = false,
src/link/Elf/ZigObject.zig+135-142
...@@ -101,6 +101,28 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -101,6 +101,28 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
101 .dwarf => |v| {101 .dwarf => |v| {
102 var dwarf = Dwarf.init(&elf_file.base, v);102 var dwarf = Dwarf.init(&elf_file.base, v);
103103
104 const addSectionSymbolWithAtom = struct {
105 fn addSectionSymbolWithAtom(
106 zo: *ZigObject,
107 allocator: Allocator,
108 name: [:0]const u8,
109 alignment: Atom.Alignment,
110 shndx: u32,
111 ) !Symbol.Index {
112 const name_off = try zo.addString(allocator, name);
113 const sym_index = try zo.addSectionSymbol(allocator, name_off, shndx);
114 const sym = zo.symbol(sym_index);
115 const atom_index = try zo.newAtom(allocator, name_off);
116 const atom_ptr = zo.atom(atom_index).?;
117 atom_ptr.alignment = alignment;
118 atom_ptr.output_section_index = shndx;
119 sym.ref = .{ .index = atom_index, .file = zo.index };
120 zo.symtab.items(.shndx)[sym.esym_index] = atom_index;
121 zo.symtab.items(.elf_sym)[sym.esym_index].st_shndx = SHN_ATOM;
122 return sym_index;
123 }
124 }.addSectionSymbolWithAtom;
125
104 if (self.debug_str_index == null) {126 if (self.debug_str_index == null) {
105 const osec = try elf_file.addSection(.{127 const osec = try elf_file.addSection(.{
106 .name = try elf_file.insertShString(".debug_str"),128 .name = try elf_file.insertShString(".debug_str"),
...@@ -110,8 +132,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -110,8 +132,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
110 .addralign = 1,132 .addralign = 1,
111 });133 });
112 self.debug_str_section_dirty = true;134 self.debug_str_section_dirty = true;
113 self.debug_str_index = try self.addSectionSymbol(gpa, ".debug_str", .@"1", osec);135 self.debug_str_index = try addSectionSymbolWithAtom(self, gpa, ".debug_str", .@"1", osec);
114 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_str_index.?).ref;
115 }136 }
116137
117 if (self.debug_info_index == null) {138 if (self.debug_info_index == null) {
...@@ -121,8 +142,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -121,8 +142,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
121 .addralign = 1,142 .addralign = 1,
122 });143 });
123 self.debug_info_section_dirty = true;144 self.debug_info_section_dirty = true;
124 self.debug_info_index = try self.addSectionSymbol(gpa, ".debug_info", .@"1", osec);145 self.debug_info_index = try addSectionSymbolWithAtom(self, gpa, ".debug_info", .@"1", osec);
125 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_info_index.?).ref;
126 }146 }
127147
128 if (self.debug_abbrev_index == null) {148 if (self.debug_abbrev_index == null) {
...@@ -132,8 +152,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -132,8 +152,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
132 .addralign = 1,152 .addralign = 1,
133 });153 });
134 self.debug_abbrev_section_dirty = true;154 self.debug_abbrev_section_dirty = true;
135 self.debug_abbrev_index = try self.addSectionSymbol(gpa, ".debug_abbrev", .@"1", osec);155 self.debug_abbrev_index = try addSectionSymbolWithAtom(self, gpa, ".debug_abbrev", .@"1", osec);
136 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_abbrev_index.?).ref;
137 }156 }
138157
139 if (self.debug_aranges_index == null) {158 if (self.debug_aranges_index == null) {
...@@ -143,8 +162,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -143,8 +162,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
143 .addralign = 16,162 .addralign = 16,
144 });163 });
145 self.debug_aranges_section_dirty = true;164 self.debug_aranges_section_dirty = true;
146 self.debug_aranges_index = try self.addSectionSymbol(gpa, ".debug_aranges", .@"16", osec);165 self.debug_aranges_index = try addSectionSymbolWithAtom(self, gpa, ".debug_aranges", .@"16", osec);
147 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_aranges_index.?).ref;
148 }166 }
149167
150 if (self.debug_line_index == null) {168 if (self.debug_line_index == null) {
...@@ -154,8 +172,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -154,8 +172,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
154 .addralign = 1,172 .addralign = 1,
155 });173 });
156 self.debug_line_section_dirty = true;174 self.debug_line_section_dirty = true;
157 self.debug_line_index = try self.addSectionSymbol(gpa, ".debug_line", .@"1", osec);175 self.debug_line_index = try addSectionSymbolWithAtom(self, gpa, ".debug_line", .@"1", osec);
158 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_index.?).ref;
159 }176 }
160177
161 if (self.debug_line_str_index == null) {178 if (self.debug_line_str_index == null) {
...@@ -167,8 +184,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -167,8 +184,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
167 .addralign = 1,184 .addralign = 1,
168 });185 });
169 self.debug_line_str_section_dirty = true;186 self.debug_line_str_section_dirty = true;
170 self.debug_line_str_index = try self.addSectionSymbol(gpa, ".debug_line_str", .@"1", osec);187 self.debug_line_str_index = try addSectionSymbolWithAtom(self, gpa, ".debug_line_str", .@"1", osec);
171 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_str_index.?).ref;
172 }188 }
173189
174 if (self.debug_loclists_index == null) {190 if (self.debug_loclists_index == null) {
...@@ -178,8 +194,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -178,8 +194,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
178 .addralign = 1,194 .addralign = 1,
179 });195 });
180 self.debug_loclists_section_dirty = true;196 self.debug_loclists_section_dirty = true;
181 self.debug_loclists_index = try self.addSectionSymbol(gpa, ".debug_loclists", .@"1", osec);197 self.debug_loclists_index = try addSectionSymbolWithAtom(self, gpa, ".debug_loclists", .@"1", osec);
182 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_loclists_index.?).ref;
183 }198 }
184199
185 if (self.debug_rnglists_index == null) {200 if (self.debug_rnglists_index == null) {
...@@ -189,8 +204,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -189,8 +204,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
189 .addralign = 1,204 .addralign = 1,
190 });205 });
191 self.debug_rnglists_section_dirty = true;206 self.debug_rnglists_section_dirty = true;
192 self.debug_rnglists_index = try self.addSectionSymbol(gpa, ".debug_rnglists", .@"1", osec);207 self.debug_rnglists_index = try addSectionSymbolWithAtom(self, gpa, ".debug_rnglists", .@"1", osec);
193 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_rnglists_index.?).ref;
194 }208 }
195209
196 if (self.eh_frame_index == null) {210 if (self.eh_frame_index == null) {
...@@ -204,8 +218,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -204,8 +218,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
204 .addralign = ptr_size,218 .addralign = ptr_size,
205 });219 });
206 self.eh_frame_section_dirty = true;220 self.eh_frame_section_dirty = true;
207 self.eh_frame_index = try self.addSectionSymbol(gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), osec);221 self.eh_frame_index = try addSectionSymbolWithAtom(self, gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), osec);
208 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.eh_frame_index.?).ref;
209 }222 }
210223
211 try dwarf.initMetadata();224 try dwarf.initMetadata();
...@@ -336,8 +349,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi...@@ -336,8 +349,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
336 const atom_ptr = self.atom(sym.ref.index).?;349 const atom_ptr = self.atom(sym.ref.index).?;
337 if (!atom_ptr.alive) continue;350 if (!atom_ptr.alive) continue;
338351
339 log.debug("parsing relocs in {s}", .{sym.name(elf_file)});
340
341 const relocs = &self.relocs.items[atom_ptr.relocsShndx().?];352 const relocs = &self.relocs.items[atom_ptr.relocsShndx().?];
342 for (sect.units.items) |*unit| {353 for (sect.units.items) |*unit| {
343 try relocs.ensureUnusedCapacity(gpa, unit.cross_unit_relocs.items.len +354 try relocs.ensureUnusedCapacity(gpa, unit.cross_unit_relocs.items.len +
...@@ -350,12 +361,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi...@@ -350,12 +361,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
350 else361 else
351 0));362 0));
352 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);363 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);
353 log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{
354 self.symbol(sym_index).name(elf_file),
355 r_offset,
356 r_addend,
357 relocation.fmtRelocType(r_type, cpu_arch),
358 });
359 atom_ptr.addRelocAssumeCapacity(.{364 atom_ptr.addRelocAssumeCapacity(.{
360 .r_offset = r_offset,365 .r_offset = r_offset,
361 .r_addend = r_addend,366 .r_addend = r_addend,
...@@ -384,12 +389,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi...@@ -384,12 +389,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
384 else389 else
385 0));390 0));
386 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);391 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);
387 log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{
388 self.symbol(target_sym_index).name(elf_file),
389 r_offset,
390 r_addend,
391 relocation.fmtRelocType(r_type, cpu_arch),
392 });
393 atom_ptr.addRelocAssumeCapacity(.{392 atom_ptr.addRelocAssumeCapacity(.{
394 .r_offset = r_offset,393 .r_offset = r_offset,
395 .r_addend = r_addend,394 .r_addend = r_addend,
...@@ -410,12 +409,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi...@@ -410,12 +409,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
410 else409 else
411 0));410 0));
412 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);411 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);
413 log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{
414 self.symbol(sym_index).name(elf_file),
415 r_offset,
416 r_addend,
417 relocation.fmtRelocType(r_type, cpu_arch),
418 });
419 atom_ptr.addRelocAssumeCapacity(.{412 atom_ptr.addRelocAssumeCapacity(.{
420 .r_offset = r_offset,413 .r_offset = r_offset,
421 .r_addend = r_addend,414 .r_addend = r_addend,
...@@ -430,12 +423,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi...@@ -430,12 +423,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
430 else423 else
431 0));424 0));
432 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);425 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);
433 log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{
434 self.symbol(sym_index).name(elf_file),
435 r_offset,
436 r_addend,
437 relocation.fmtRelocType(r_type, cpu_arch),
438 });
439 atom_ptr.addRelocAssumeCapacity(.{426 atom_ptr.addRelocAssumeCapacity(.{
440 .r_offset = r_offset,427 .r_offset = r_offset,
441 .r_addend = r_addend,428 .r_addend = r_addend,
...@@ -464,12 +451,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi...@@ -464,12 +451,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
464 else451 else
465 0));452 0));
466 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);453 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);
467 log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{
468 self.symbol(target_sym_index).name(elf_file),
469 r_offset,
470 r_addend,
471 relocation.fmtRelocType(r_type, cpu_arch),
472 });
473 atom_ptr.addRelocAssumeCapacity(.{454 atom_ptr.addRelocAssumeCapacity(.{
474 .r_offset = r_offset,455 .r_offset = r_offset,
475 .r_addend = r_addend,456 .r_addend = r_addend,
...@@ -481,12 +462,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi...@@ -481,12 +462,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
481 const r_offset = entry_off + reloc.source_off;462 const r_offset = entry_off + reloc.source_off;
482 const r_addend: i64 = @intCast(reloc.target_off);463 const r_addend: i64 = @intCast(reloc.target_off);
483 const r_type = relocation.dwarf.externalRelocType(target_sym.*, sect_index, dwarf.address_size, cpu_arch);464 const r_type = relocation.dwarf.externalRelocType(target_sym.*, sect_index, dwarf.address_size, cpu_arch);
484 log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{
485 target_sym.name(elf_file),
486 r_offset,
487 r_addend,
488 relocation.fmtRelocType(r_type, cpu_arch),
489 });
490 atom_ptr.addRelocAssumeCapacity(.{465 atom_ptr.addRelocAssumeCapacity(.{
491 .r_offset = r_offset,466 .r_offset = r_offset,
492 .r_addend = r_addend,467 .r_addend = r_addend,
...@@ -1035,16 +1010,15 @@ pub fn lowerUav(...@@ -1035,16 +1010,15 @@ pub fn lowerUav(
1035 }1010 }
10361011
1037 const osec = if (self.data_relro_index) |sym_index|1012 const osec = if (self.data_relro_index) |sym_index|
1038 self.symbol(sym_index).atom(elf_file).?.output_section_index1013 self.symbol(sym_index).outputShndx(elf_file).?
1039 else osec: {1014 else osec: {
1040 const osec = try elf_file.addSection(.{1015 const osec = try elf_file.addSection(.{
1041 .name = try elf_file.insertShString(".data.rel.ro"),1016 .name = try elf_file.insertShString(".data.rel.ro"),
1042 .type = elf.SHT_PROGBITS,1017 .type = elf.SHT_PROGBITS,
1043 .addralign = 1,1018 .addralign = 1,
1044 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,1019 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
1045 .offset = std.math.maxInt(u64),
1046 });1020 });
1047 self.data_relro_index = try self.addSectionSymbol(gpa, ".data.rel.ro", .@"1", osec);1021 self.data_relro_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data.rel.ro"), osec);
1048 break :osec osec;1022 break :osec osec;
1049 };1023 };
10501024
...@@ -1150,24 +1124,14 @@ pub fn getOrCreateMetadataForNav(...@@ -1150,24 +1124,14 @@ pub fn getOrCreateMetadataForNav(
1150 return gop.value_ptr.symbol_index;1124 return gop.value_ptr.symbol_index;
1151}1125}
11521126
1153// FIXME: we always create an atom to basically store size and alignment, however, this is only true for1127fn addSectionSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, shndx: u32) !Symbol.Index {
1154// sections that have a single atom like the debug sections. It would be a better solution to decouple this1128 const index = try self.newLocalSymbol(allocator, name_off);
1155// concept from the atom, maybe.
1156fn addSectionSymbol(
1157 self: *ZigObject,
1158 allocator: Allocator,
1159 name: [:0]const u8,
1160 alignment: Atom.Alignment,
1161 shndx: u32,
1162) !Symbol.Index {
1163 const name_off = try self.addString(allocator, name);
1164 const index = try self.newSymbolWithAtom(allocator, name_off);
1165 const sym = self.symbol(index);1129 const sym = self.symbol(index);
1166 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];1130 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
1167 esym.st_info |= elf.STT_SECTION;1131 esym.st_info |= elf.STT_SECTION;
1168 const atom_ptr = self.atom(sym.ref.index).?;1132 // TODO create fake shdrs?
1169 atom_ptr.alignment = alignment;1133 // esym.st_shndx = shndx;
1170 atom_ptr.output_section_index = shndx;1134 sym.output_section_index = shndx;
1171 return index;1135 return index;
1172}1136}
11731137
...@@ -1186,15 +1150,14 @@ fn getNavShdrIndex(...@@ -1186,15 +1150,14 @@ fn getNavShdrIndex(
1186 const nav_val = zcu.navValue(nav_index);1150 const nav_val = zcu.navValue(nav_index);
1187 if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) {1151 if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) {
1188 if (self.text_index) |symbol_index|1152 if (self.text_index) |symbol_index|
1189 return self.symbol(symbol_index).atom(elf_file).?.output_section_index;1153 return self.symbol(symbol_index).outputShndx(elf_file).?;
1190 const osec = try elf_file.addSection(.{1154 const osec = try elf_file.addSection(.{
1191 .type = elf.SHT_PROGBITS,1155 .type = elf.SHT_PROGBITS,
1192 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,1156 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
1193 .name = try elf_file.insertShString(".text"),1157 .name = try elf_file.insertShString(".text"),
1194 .addralign = 1,1158 .addralign = 1,
1195 .offset = std.math.maxInt(u64),
1196 });1159 });
1197 self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec);1160 self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec);
1198 return osec;1161 return osec;
1199 }1162 }
1200 const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {1163 const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
...@@ -1209,71 +1172,63 @@ fn getNavShdrIndex(...@@ -1209,71 +1172,63 @@ fn getNavShdrIndex(
1209 } else true;1172 } else true;
1210 if (is_bss) {1173 if (is_bss) {
1211 if (self.tbss_index) |symbol_index|1174 if (self.tbss_index) |symbol_index|
1212 return self.symbol(symbol_index).atom(elf_file).?.output_section_index;1175 return self.symbol(symbol_index).outputShndx(elf_file).?;
1213 const osec = try elf_file.addSection(.{1176 const osec = try elf_file.addSection(.{
1214 .name = try elf_file.insertShString(".tbss"),1177 .name = try elf_file.insertShString(".tbss"),
1215 .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS,1178 .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS,
1216 .type = elf.SHT_NOBITS,1179 .type = elf.SHT_NOBITS,
1217 .addralign = 1,1180 .addralign = 1,
1218 });1181 });
1219 self.tbss_index = try self.addSectionSymbol(gpa, ".tbss", .@"1", osec);1182 self.tbss_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".tbss"), osec);
1220 return osec;1183 return osec;
1221 }1184 }
1222 if (self.tdata_index) |symbol_index|1185 if (self.tdata_index) |symbol_index|
1223 return self.symbol(symbol_index).atom(elf_file).?.output_section_index;1186 return self.symbol(symbol_index).outputShndx(elf_file).?;
1224 const osec = try elf_file.addSection(.{1187 const osec = try elf_file.addSection(.{
1225 .type = elf.SHT_PROGBITS,1188 .type = elf.SHT_PROGBITS,
1226 .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS,1189 .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS,
1227 .name = try elf_file.insertShString(".tdata"),1190 .name = try elf_file.insertShString(".tdata"),
1228 .addralign = 1,1191 .addralign = 1,
1229 .offset = std.math.maxInt(u64),
1230 });1192 });
1231 self.tdata_index = try self.addSectionSymbol(gpa, ".tdata", .@"1", osec);1193 self.tdata_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".tdata"), osec);
1232 return osec;1194 return osec;
1233 }1195 }
1234 if (is_const) {1196 if (is_const) {
1235 if (self.data_relro_index) |symbol_index|1197 if (self.data_relro_index) |symbol_index|
1236 return self.symbol(symbol_index).atom(elf_file).?.output_section_index;1198 return self.symbol(symbol_index).outputShndx(elf_file).?;
1237 const osec = try elf_file.addSection(.{1199 const osec = try elf_file.addSection(.{
1238 .name = try elf_file.insertShString(".data.rel.ro"),1200 .name = try elf_file.insertShString(".data.rel.ro"),
1239 .type = elf.SHT_PROGBITS,1201 .type = elf.SHT_PROGBITS,
1240 .addralign = 1,1202 .addralign = 1,
1241 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,1203 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
1242 .offset = std.math.maxInt(u64),
1243 });1204 });
1244 self.data_relro_index = try self.addSectionSymbol(gpa, ".data.rel.ro", .@"1", osec);1205 self.data_relro_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data.rel.ro"), osec);
1245 return osec;1206 return osec;
1246 }1207 }
1247 if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu))1208 if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu))
1248 return switch (zcu.navFileScope(nav_index).mod.optimize_mode) {1209 return switch (zcu.navFileScope(nav_index).mod.optimize_mode) {
1249 .Debug, .ReleaseSafe => {1210 .Debug, .ReleaseSafe => {
1250 if (self.data_index) |symbol_index|1211 if (self.data_index) |symbol_index|
1251 return self.symbol(symbol_index).atom(elf_file).?.output_section_index;1212 return self.symbol(symbol_index).outputShndx(elf_file).?;
1252 const osec = try elf_file.addSection(.{1213 const osec = try elf_file.addSection(.{
1253 .name = try elf_file.insertShString(".data"),1214 .name = try elf_file.insertShString(".data"),
1254 .type = elf.SHT_PROGBITS,1215 .type = elf.SHT_PROGBITS,
1255 .addralign = ptr_size,1216 .addralign = ptr_size,
1256 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,1217 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
1257 .offset = std.math.maxInt(u64),
1258 });1218 });
1259 self.data_index = try self.addSectionSymbol(1219 self.data_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data"), osec);
1260 gpa,
1261 ".data",
1262 Atom.Alignment.fromNonzeroByteUnits(ptr_size),
1263 osec,
1264 );
1265 return osec;1220 return osec;
1266 },1221 },
1267 .ReleaseFast, .ReleaseSmall => {1222 .ReleaseFast, .ReleaseSmall => {
1268 if (self.bss_index) |symbol_index|1223 if (self.bss_index) |symbol_index|
1269 return self.symbol(symbol_index).atom(elf_file).?.output_section_index;1224 return self.symbol(symbol_index).outputShndx(elf_file).?;
1270 const osec = try elf_file.addSection(.{1225 const osec = try elf_file.addSection(.{
1271 .type = elf.SHT_NOBITS,1226 .type = elf.SHT_NOBITS,
1272 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,1227 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
1273 .name = try elf_file.insertShString(".bss"),1228 .name = try elf_file.insertShString(".bss"),
1274 .addralign = 1,1229 .addralign = 1,
1275 });1230 });
1276 self.bss_index = try self.addSectionSymbol(gpa, ".bss", .@"1", osec);1231 self.bss_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".bss"), osec);
1277 return osec;1232 return osec;
1278 },1233 },
1279 };1234 };
...@@ -1282,31 +1237,25 @@ fn getNavShdrIndex(...@@ -1282,31 +1237,25 @@ fn getNavShdrIndex(
1282 } else true;1237 } else true;
1283 if (is_bss) {1238 if (is_bss) {
1284 if (self.bss_index) |symbol_index|1239 if (self.bss_index) |symbol_index|
1285 return self.symbol(symbol_index).atom(elf_file).?.output_section_index;1240 return self.symbol(symbol_index).outputShndx(elf_file).?;
1286 const osec = try elf_file.addSection(.{1241 const osec = try elf_file.addSection(.{
1287 .type = elf.SHT_NOBITS,1242 .type = elf.SHT_NOBITS,
1288 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,1243 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
1289 .name = try elf_file.insertShString(".bss"),1244 .name = try elf_file.insertShString(".bss"),
1290 .addralign = 1,1245 .addralign = 1,
1291 });1246 });
1292 self.bss_index = try self.addSectionSymbol(gpa, ".bss", .@"1", osec);1247 self.bss_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".bss"), osec);
1293 return osec;1248 return osec;
1294 }1249 }
1295 if (self.data_index) |symbol_index|1250 if (self.data_index) |symbol_index|
1296 return self.symbol(symbol_index).atom(elf_file).?.output_section_index;1251 return self.symbol(symbol_index).outputShndx(elf_file).?;
1297 const osec = try elf_file.addSection(.{1252 const osec = try elf_file.addSection(.{
1298 .name = try elf_file.insertShString(".data"),1253 .name = try elf_file.insertShString(".data"),
1299 .type = elf.SHT_PROGBITS,1254 .type = elf.SHT_PROGBITS,
1300 .addralign = ptr_size,1255 .addralign = ptr_size,
1301 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,1256 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
1302 .offset = std.math.maxInt(u64),
1303 });1257 });
1304 self.data_index = try self.addSectionSymbol(1258 self.data_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data"), osec);
1305 gpa,
1306 ".data",
1307 Atom.Alignment.fromNonzeroByteUnits(ptr_size),
1308 osec,
1309 );
1310 return osec;1259 return osec;
1311}1260}
13121261
...@@ -1354,7 +1303,7 @@ fn updateNavCode(...@@ -1354,7 +1303,7 @@ fn updateNavCode(
1354 const capacity = atom_ptr.capacity(elf_file);1303 const capacity = atom_ptr.capacity(elf_file);
1355 const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value));1304 const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value));
1356 if (need_realloc) {1305 if (need_realloc) {
1357 try self.growAtom(atom_ptr, elf_file);1306 try self.allocateAtom(atom_ptr, true, elf_file);
1358 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value });1307 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value });
1359 if (old_vaddr != atom_ptr.value) {1308 if (old_vaddr != atom_ptr.value) {
1360 sym.value = 0;1309 sym.value = 0;
...@@ -1364,7 +1313,7 @@ fn updateNavCode(...@@ -1364,7 +1313,7 @@ fn updateNavCode(
1364 // TODO shrink section size1313 // TODO shrink section size
1365 }1314 }
1366 } else {1315 } else {
1367 try self.allocateAtom(atom_ptr, elf_file);1316 try self.allocateAtom(atom_ptr, true, elf_file);
1368 errdefer self.freeNavMetadata(elf_file, sym_index);1317 errdefer self.freeNavMetadata(elf_file, sym_index);
1369 sym.value = 0;1318 sym.value = 0;
1370 esym.st_value = 0;1319 esym.st_value = 0;
...@@ -1439,7 +1388,7 @@ fn updateTlv(...@@ -1439,7 +1388,7 @@ fn updateTlv(
1439 const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index);1388 const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index);
1440 assert(!gop.found_existing); // TODO incremental updates1389 assert(!gop.found_existing); // TODO incremental updates
14411390
1442 try self.allocateAtom(atom_ptr, elf_file);1391 try self.allocateAtom(atom_ptr, true, elf_file);
1443 sym.value = 0;1392 sym.value = 0;
1444 esym.st_value = 0;1393 esym.st_value = 0;
14451394
...@@ -1557,9 +1506,8 @@ pub fn updateFunc(...@@ -1557,9 +1506,8 @@ pub fn updateFunc(
1557 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,1506 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
1558 .type = elf.SHT_PROGBITS,1507 .type = elf.SHT_PROGBITS,
1559 .addralign = 1,1508 .addralign = 1,
1560 .offset = std.math.maxInt(u64),
1561 });1509 });
1562 self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec);1510 self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec);
1563 break :osec osec;1511 break :osec osec;
1564 };1512 };
1565 const name_off = try self.addString(gpa, name);1513 const name_off = try self.addString(gpa, name);
...@@ -1726,29 +1674,27 @@ fn updateLazySymbol(...@@ -1726,29 +1674,27 @@ fn updateLazySymbol(
17261674
1727 const output_section_index = switch (sym.kind) {1675 const output_section_index = switch (sym.kind) {
1728 .code => if (self.text_index) |sym_index|1676 .code => if (self.text_index) |sym_index|
1729 self.symbol(sym_index).atom(elf_file).?.output_section_index1677 self.symbol(sym_index).outputShndx(elf_file).?
1730 else osec: {1678 else osec: {
1731 const osec = try elf_file.addSection(.{1679 const osec = try elf_file.addSection(.{
1732 .name = try elf_file.insertShString(".text"),1680 .name = try elf_file.insertShString(".text"),
1733 .type = elf.SHT_PROGBITS,1681 .type = elf.SHT_PROGBITS,
1734 .addralign = 1,1682 .addralign = 1,
1735 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,1683 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
1736 .offset = std.math.maxInt(u64),
1737 });1684 });
1738 self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec);1685 self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec);
1739 break :osec osec;1686 break :osec osec;
1740 },1687 },
1741 .const_data => if (self.rodata_index) |sym_index|1688 .const_data => if (self.rodata_index) |sym_index|
1742 self.symbol(sym_index).atom(elf_file).?.output_section_index1689 self.symbol(sym_index).outputShndx(elf_file).?
1743 else osec: {1690 else osec: {
1744 const osec = try elf_file.addSection(.{1691 const osec = try elf_file.addSection(.{
1745 .name = try elf_file.insertShString(".rodata"),1692 .name = try elf_file.insertShString(".rodata"),
1746 .type = elf.SHT_PROGBITS,1693 .type = elf.SHT_PROGBITS,
1747 .addralign = 1,1694 .addralign = 1,
1748 .flags = elf.SHF_ALLOC,1695 .flags = elf.SHF_ALLOC,
1749 .offset = std.math.maxInt(u64),
1750 });1696 });
1751 self.rodata_index = try self.addSectionSymbol(gpa, ".rodata", .@"1", osec);1697 self.rodata_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".rodata"), osec);
1752 break :osec osec;1698 break :osec osec;
1753 },1699 },
1754 };1700 };
...@@ -1765,7 +1711,7 @@ fn updateLazySymbol(...@@ -1765,7 +1711,7 @@ fn updateLazySymbol(
1765 atom_ptr.size = code.len;1711 atom_ptr.size = code.len;
1766 atom_ptr.output_section_index = output_section_index;1712 atom_ptr.output_section_index = output_section_index;
17671713
1768 try self.allocateAtom(atom_ptr, elf_file);1714 try self.allocateAtom(atom_ptr, true, elf_file);
1769 errdefer self.freeNavMetadata(elf_file, symbol_index);1715 errdefer self.freeNavMetadata(elf_file, symbol_index);
17701716
1771 local_sym.value = 0;1717 local_sym.value = 0;
...@@ -1820,7 +1766,7 @@ fn lowerConst(...@@ -1820,7 +1766,7 @@ fn lowerConst(
1820 atom_ptr.size = code.len;1766 atom_ptr.size = code.len;
1821 atom_ptr.output_section_index = output_section_index;1767 atom_ptr.output_section_index = output_section_index;
18221768
1823 try self.allocateAtom(atom_ptr, elf_file);1769 try self.allocateAtom(atom_ptr, true, elf_file);
1824 errdefer self.freeNavMetadata(elf_file, sym_index);1770 errdefer self.freeNavMetadata(elf_file, sym_index);
18251771
1826 try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file));1772 try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file));
...@@ -2017,17 +1963,27 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {...@@ -2017,17 +1963,27 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
2017 }1963 }
2018}1964}
20191965
2020fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {1966pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, elf_file: *Elf) !void {
1967 const slice = elf_file.sections.slice();
1968 const shdr = &slice.items(.shdr)[atom_ptr.output_section_index];
1969 const last_atom_ref = &slice.items(.last_atom)[atom_ptr.output_section_index];
1970
1971 // FIXME:JK this only works if this atom is the only atom in the output section
1972 // In every other case, we need to redo the prev/next links
1973 if (last_atom_ref.eql(atom_ptr.ref())) last_atom_ref.* = .{};
1974
2021 const alloc_res = try elf_file.allocateChunk(.{1975 const alloc_res = try elf_file.allocateChunk(.{
2022 .shndx = atom_ptr.output_section_index,1976 .shndx = atom_ptr.output_section_index,
2023 .size = atom_ptr.size,1977 .size = atom_ptr.size,
2024 .alignment = atom_ptr.alignment,1978 .alignment = atom_ptr.alignment,
1979 .requires_padding = requires_padding,
2025 });1980 });
2026 atom_ptr.value = @intCast(alloc_res.value);1981 atom_ptr.value = @intCast(alloc_res.value);
20271982 log.debug("allocated {s} at {x}\n placement {?}", .{
2028 const slice = elf_file.sections.slice();1983 atom_ptr.name(elf_file),
2029 const shdr = &slice.items(.shdr)[atom_ptr.output_section_index];1984 atom_ptr.offset(elf_file),
2030 const last_atom_ref = &slice.items(.last_atom)[atom_ptr.output_section_index];1985 alloc_res.placement,
1986 });
20311987
2032 const expand_section = if (elf_file.atom(alloc_res.placement)) |placement_atom|1988 const expand_section = if (elf_file.atom(alloc_res.placement)) |placement_atom|
2033 placement_atom.nextAtom(elf_file) == null1989 placement_atom.nextAtom(elf_file) == null
...@@ -2049,22 +2005,6 @@ fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {...@@ -2049,22 +2005,6 @@ fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
2049 }2005 }
2050 shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits().?);2006 shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits().?);
20512007
2052 const sect_atom_ptr = for ([_]?Symbol.Index{
2053 self.text_index,
2054 self.rodata_index,
2055 self.data_relro_index,
2056 self.data_index,
2057 self.tdata_index,
2058 }) |maybe_sym_index| {
2059 const sect_sym_index = maybe_sym_index orelse continue;
2060 const sect_atom_ptr = self.symbol(sect_sym_index).atom(elf_file).?;
2061 if (sect_atom_ptr.output_section_index == atom_ptr.output_section_index) break sect_atom_ptr;
2062 } else null;
2063 if (sect_atom_ptr) |sap| {
2064 sap.size = shdr.sh_size;
2065 sap.alignment = Atom.Alignment.fromNonzeroByteUnits(shdr.sh_addralign);
2066 }
2067
2068 // This function can also reallocate an atom.2008 // This function can also reallocate an atom.
2069 // In this case we need to "unplug" it from its previous location before2009 // In this case we need to "unplug" it from its previous location before
2070 // plugging it in to its new location.2010 // plugging it in to its new location.
...@@ -2083,11 +2023,37 @@ fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {...@@ -2083,11 +2023,37 @@ fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
2083 atom_ptr.prev_atom_ref = .{ .index = 0, .file = 0 };2023 atom_ptr.prev_atom_ref = .{ .index = 0, .file = 0 };
2084 atom_ptr.next_atom_ref = .{ .index = 0, .file = 0 };2024 atom_ptr.next_atom_ref = .{ .index = 0, .file = 0 };
2085 }2025 }
2026
2027 log.debug(" prev {?}, next {?}", .{ atom_ptr.prev_atom_ref, atom_ptr.next_atom_ref });
2086}2028}
20872029
2088fn growAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {2030pub fn resetShdrIndexes(self: *ZigObject, backlinks: anytype) void {
2089 if (!atom_ptr.alignment.check(@intCast(atom_ptr.value)) or atom_ptr.size > atom_ptr.capacity(elf_file)) {2031 for (self.atoms_indexes.items) |atom_index| {
2090 try self.allocateAtom(atom_ptr, elf_file);2032 const atom_ptr = self.atom(atom_index) orelse continue;
2033 atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];
2034 }
2035 inline for ([_]?Symbol.Index{
2036 self.text_index,
2037 self.rodata_index,
2038 self.data_relro_index,
2039 self.data_index,
2040 self.bss_index,
2041 self.tdata_index,
2042 self.tbss_index,
2043 self.eh_frame_index,
2044 self.debug_info_index,
2045 self.debug_abbrev_index,
2046 self.debug_aranges_index,
2047 self.debug_str_index,
2048 self.debug_line_index,
2049 self.debug_line_str_index,
2050 self.debug_loclists_index,
2051 self.debug_rnglists_index,
2052 }) |maybe_sym_index| {
2053 if (maybe_sym_index) |sym_index| {
2054 const sym = self.symbol(sym_index);
2055 sym.output_section_index = backlinks[sym.output_section_index];
2056 }
2091 }2057 }
2092}2058}
20932059
...@@ -2095,6 +2061,33 @@ pub fn asFile(self: *ZigObject) File {...@@ -2095,6 +2061,33 @@ pub fn asFile(self: *ZigObject) File {
2095 return .{ .zig_object = self };2061 return .{ .zig_object = self };
2096}2062}
20972063
2064pub fn sectionSymbol(self: *ZigObject, shndx: u32, elf_file: *Elf) ?*Symbol {
2065 inline for ([_]?Symbol.Index{
2066 self.text_index,
2067 self.rodata_index,
2068 self.data_relro_index,
2069 self.data_index,
2070 self.bss_index,
2071 self.tdata_index,
2072 self.tbss_index,
2073 self.eh_frame_index,
2074 self.debug_info_index,
2075 self.debug_abbrev_index,
2076 self.debug_aranges_index,
2077 self.debug_str_index,
2078 self.debug_line_index,
2079 self.debug_line_str_index,
2080 self.debug_loclists_index,
2081 self.debug_rnglists_index,
2082 }) |maybe_sym_index| {
2083 if (maybe_sym_index) |sym_index| {
2084 const sym = self.symbol(sym_index);
2085 if (sym.outputShndx(elf_file) == shndx) return sym;
2086 }
2087 }
2088 return null;
2089}
2090
2098pub fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 {2091pub fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 {
2099 return self.strtab.insert(allocator, string);2092 return self.strtab.insert(allocator, string);
2100}2093}
src/link/Elf/file.zig+7-7
...@@ -95,19 +95,19 @@ pub const File = union(enum) {...@@ -95,19 +95,19 @@ pub const File = union(enum) {
95 log.debug("'{s}' is non-local", .{sym.name(ef)});95 log.debug("'{s}' is non-local", .{sym.name(ef)});
96 try ef.dynsym.addSymbol(ref, ef);96 try ef.dynsym.addSymbol(ref, ef);
97 }97 }
98 if (sym.flags.needs_got) {98 if (sym.flags.needs_got and !sym.flags.has_got) {
99 log.debug("'{s}' needs GOT", .{sym.name(ef)});99 log.debug("'{s}' needs GOT", .{sym.name(ef)});
100 _ = try ef.got.addGotSymbol(ref, ef);100 _ = try ef.got.addGotSymbol(ref, ef);
101 }101 }
102 if (sym.flags.needs_plt) {102 if (sym.flags.needs_plt) {
103 if (sym.flags.is_canonical) {103 if (sym.flags.is_canonical and !sym.flags.has_plt) {
104 log.debug("'{s}' needs CPLT", .{sym.name(ef)});104 log.debug("'{s}' needs CPLT", .{sym.name(ef)});
105 sym.flags.@"export" = true;105 sym.flags.@"export" = true;
106 try ef.plt.addSymbol(ref, ef);106 try ef.plt.addSymbol(ref, ef);
107 } else if (sym.flags.needs_got) {107 } else if (sym.flags.needs_got and !sym.flags.has_pltgot) {
108 log.debug("'{s}' needs PLTGOT", .{sym.name(ef)});108 log.debug("'{s}' needs PLTGOT", .{sym.name(ef)});
109 try ef.plt_got.addSymbol(ref, ef);109 try ef.plt_got.addSymbol(ref, ef);
110 } else {110 } else if (!sym.flags.has_plt) {
111 log.debug("'{s}' needs PLT", .{sym.name(ef)});111 log.debug("'{s}' needs PLT", .{sym.name(ef)});
112 try ef.plt.addSymbol(ref, ef);112 try ef.plt.addSymbol(ref, ef);
113 }113 }
...@@ -116,15 +116,15 @@ pub const File = union(enum) {...@@ -116,15 +116,15 @@ pub const File = union(enum) {
116 log.debug("'{s}' needs COPYREL", .{sym.name(ef)});116 log.debug("'{s}' needs COPYREL", .{sym.name(ef)});
117 try ef.copy_rel.addSymbol(ref, ef);117 try ef.copy_rel.addSymbol(ref, ef);
118 }118 }
119 if (sym.flags.needs_tlsgd) {119 if (sym.flags.needs_tlsgd and !sym.flags.has_tlsgd) {
120 log.debug("'{s}' needs TLSGD", .{sym.name(ef)});120 log.debug("'{s}' needs TLSGD", .{sym.name(ef)});
121 try ef.got.addTlsGdSymbol(ref, ef);121 try ef.got.addTlsGdSymbol(ref, ef);
122 }122 }
123 if (sym.flags.needs_gottp) {123 if (sym.flags.needs_gottp and !sym.flags.has_gottp) {
124 log.debug("'{s}' needs GOTTP", .{sym.name(ef)});124 log.debug("'{s}' needs GOTTP", .{sym.name(ef)});
125 try ef.got.addGotTpSymbol(ref, ef);125 try ef.got.addGotTpSymbol(ref, ef);
126 }126 }
127 if (sym.flags.needs_tlsdesc) {127 if (sym.flags.needs_tlsdesc and !sym.flags.has_tlsdesc) {
128 log.debug("'{s}' needs TLSDESC", .{sym.name(ef)});128 log.debug("'{s}' needs TLSDESC", .{sym.name(ef)});
129 try ef.got.addTlsDescSymbol(ref, ef);129 try ef.got.addTlsDescSymbol(ref, ef);
130 }130 }
src/link/Elf/relocatable.zig+12-22
...@@ -295,7 +295,6 @@ fn initSections(elf_file: *Elf) !void {...@@ -295,7 +295,6 @@ fn initSections(elf_file: *Elf) !void {
295 elf.SHT_PROGBITS,295 elf.SHT_PROGBITS,
296 .flags = elf.SHF_ALLOC,296 .flags = elf.SHF_ALLOC,
297 .addralign = elf_file.ptrWidthBytes(),297 .addralign = elf_file.ptrWidthBytes(),
298 .offset = std.math.maxInt(u64),
299 });298 });
300 }299 }
301 elf_file.eh_frame_rela_section_index = elf_file.sectionByName(".rela.eh_frame") orelse300 elf_file.eh_frame_rela_section_index = elf_file.sectionByName(".rela.eh_frame") orelse
...@@ -324,7 +323,6 @@ fn initComdatGroups(elf_file: *Elf) !void {...@@ -324,7 +323,6 @@ fn initComdatGroups(elf_file: *Elf) !void {
324 .type = elf.SHT_GROUP,323 .type = elf.SHT_GROUP,
325 .entsize = @sizeOf(u32),324 .entsize = @sizeOf(u32),
326 .addralign = @alignOf(u32),325 .addralign = @alignOf(u32),
327 .offset = std.math.maxInt(u64),
328 }),326 }),
329 .cg_ref = .{ .index = @intCast(cg_index), .file = index },327 .cg_ref = .{ .index = @intCast(cg_index), .file = index },
330 };328 };
...@@ -335,9 +333,11 @@ fn initComdatGroups(elf_file: *Elf) !void {...@@ -335,9 +333,11 @@ fn initComdatGroups(elf_file: *Elf) !void {
335fn updateSectionSizes(elf_file: *Elf) !void {333fn updateSectionSizes(elf_file: *Elf) !void {
336 const slice = elf_file.sections.slice();334 const slice = elf_file.sections.slice();
337 for (slice.items(.atom_list_2)) |*atom_list| {335 for (slice.items(.atom_list_2)) |*atom_list| {
338 if (atom_list.atoms.items.len == 0) continue;336 if (atom_list.atoms.keys().len == 0) continue;
337 if (!atom_list.dirty) continue;
339 atom_list.updateSize(elf_file);338 atom_list.updateSize(elf_file);
340 try atom_list.allocate(elf_file);339 try atom_list.allocate(elf_file);
340 atom_list.dirty = false;
341 }341 }
342342
343 for (slice.items(.shdr), 0..) |*shdr, shndx| {343 for (slice.items(.shdr), 0..) |*shdr, shndx| {
...@@ -392,24 +392,14 @@ fn allocateAllocSections(elf_file: *Elf) !void {...@@ -392,24 +392,14 @@ fn allocateAllocSections(elf_file: *Elf) !void {
392 shdr.sh_size = 0;392 shdr.sh_size = 0;
393 const new_offset = try elf_file.findFreeSpace(needed_size, shdr.sh_addralign);393 const new_offset = try elf_file.findFreeSpace(needed_size, shdr.sh_addralign);
394394
395 if (elf_file.zigObjectPtr()) |zo| blk: {395 log.debug("moving {s} from 0x{x} to 0x{x}", .{
396 const existing_size = for ([_]?Symbol.Index{396 elf_file.getShString(shdr.sh_name),
397 zo.text_index,397 shdr.sh_offset,
398 zo.rodata_index,398 new_offset,
399 zo.data_relro_index,399 });
400 zo.data_index,400
401 zo.tdata_index,401 if (shdr.sh_offset > 0) {
402 zo.eh_frame_index,402 const existing_size = elf_file.sectionSize(@intCast(shndx));
403 }) |maybe_sym_index| {
404 const sect_sym_index = maybe_sym_index orelse continue;
405 const sect_atom_ptr = zo.symbol(sect_sym_index).atom(elf_file).?;
406 if (sect_atom_ptr.output_section_index == shndx) break sect_atom_ptr.size;
407 } else break :blk;
408 log.debug("moving {s} from 0x{x} to 0x{x}", .{
409 elf_file.getShString(shdr.sh_name),
410 shdr.sh_offset,
411 new_offset,
412 });
413 const amt = try elf_file.base.file.?.copyRangeAll(403 const amt = try elf_file.base.file.?.copyRangeAll(
414 shdr.sh_offset,404 shdr.sh_offset,
415 elf_file.base.file.?,405 elf_file.base.file.?,
...@@ -434,7 +424,7 @@ fn writeAtoms(elf_file: *Elf) !void {...@@ -434,7 +424,7 @@ fn writeAtoms(elf_file: *Elf) !void {
434 const slice = elf_file.sections.slice();424 const slice = elf_file.sections.slice();
435 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {425 for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| {
436 if (shdr.sh_type == elf.SHT_NOBITS) continue;426 if (shdr.sh_type == elf.SHT_NOBITS) continue;
437 if (atom_list.atoms.items.len == 0) continue;427 if (atom_list.atoms.keys().len == 0) continue;
438 try atom_list.writeRelocatable(&buffer, elf_file);428 try atom_list.writeRelocatable(&buffer, elf_file);
439 }429 }
440}430}
src/link/Elf/synthetic_sections.zig+27-2
...@@ -435,6 +435,8 @@ pub const GotSection = struct {...@@ -435,6 +435,8 @@ pub const GotSection = struct {
435 const cpu_arch = elf_file.getTarget().cpu.arch;435 const cpu_arch = elf_file.getTarget().cpu.arch;
436 try elf_file.rela_dyn.ensureUnusedCapacity(gpa, got.numRela(elf_file));436 try elf_file.rela_dyn.ensureUnusedCapacity(gpa, got.numRela(elf_file));
437437
438 relocs_log.debug(".got", .{});
439
438 for (got.entries.items) |entry| {440 for (got.entries.items) |entry| {
439 const symbol = elf_file.symbol(entry.ref);441 const symbol = elf_file.symbol(entry.ref);
440 const extra = if (symbol) |s| s.extra(elf_file) else null;442 const extra = if (symbol) |s| s.extra(elf_file) else null;
...@@ -447,6 +449,7 @@ pub const GotSection = struct {...@@ -447,6 +449,7 @@ pub const GotSection = struct {
447 .offset = offset,449 .offset = offset,
448 .sym = extra.?.dynamic,450 .sym = extra.?.dynamic,
449 .type = relocation.encode(.glob_dat, cpu_arch),451 .type = relocation.encode(.glob_dat, cpu_arch),
452 .target = symbol,
450 });453 });
451 continue;454 continue;
452 }455 }
...@@ -455,6 +458,7 @@ pub const GotSection = struct {...@@ -455,6 +458,7 @@ pub const GotSection = struct {
455 .offset = offset,458 .offset = offset,
456 .type = relocation.encode(.irel, cpu_arch),459 .type = relocation.encode(.irel, cpu_arch),
457 .addend = symbol.?.address(.{ .plt = false }, elf_file),460 .addend = symbol.?.address(.{ .plt = false }, elf_file),
461 .target = symbol,
458 });462 });
459 continue;463 continue;
460 }464 }
...@@ -465,6 +469,7 @@ pub const GotSection = struct {...@@ -465,6 +469,7 @@ pub const GotSection = struct {
465 .offset = offset,469 .offset = offset,
466 .type = relocation.encode(.rel, cpu_arch),470 .type = relocation.encode(.rel, cpu_arch),
467 .addend = symbol.?.address(.{ .plt = false }, elf_file),471 .addend = symbol.?.address(.{ .plt = false }, elf_file),
472 .target = symbol,
468 });473 });
469 }474 }
470 },475 },
...@@ -486,17 +491,20 @@ pub const GotSection = struct {...@@ -486,17 +491,20 @@ pub const GotSection = struct {
486 .offset = offset,491 .offset = offset,
487 .sym = extra.?.dynamic,492 .sym = extra.?.dynamic,
488 .type = relocation.encode(.dtpmod, cpu_arch),493 .type = relocation.encode(.dtpmod, cpu_arch),
494 .target = symbol,
489 });495 });
490 elf_file.addRelaDynAssumeCapacity(.{496 elf_file.addRelaDynAssumeCapacity(.{
491 .offset = offset + 8,497 .offset = offset + 8,
492 .sym = extra.?.dynamic,498 .sym = extra.?.dynamic,
493 .type = relocation.encode(.dtpoff, cpu_arch),499 .type = relocation.encode(.dtpoff, cpu_arch),
500 .target = symbol,
494 });501 });
495 } else if (is_dyn_lib) {502 } else if (is_dyn_lib) {
496 elf_file.addRelaDynAssumeCapacity(.{503 elf_file.addRelaDynAssumeCapacity(.{
497 .offset = offset,504 .offset = offset,
498 .sym = extra.?.dynamic,505 .sym = extra.?.dynamic,
499 .type = relocation.encode(.dtpmod, cpu_arch),506 .type = relocation.encode(.dtpmod, cpu_arch),
507 .target = symbol,
500 });508 });
501 }509 }
502 },510 },
...@@ -508,12 +516,14 @@ pub const GotSection = struct {...@@ -508,12 +516,14 @@ pub const GotSection = struct {
508 .offset = offset,516 .offset = offset,
509 .sym = extra.?.dynamic,517 .sym = extra.?.dynamic,
510 .type = relocation.encode(.tpoff, cpu_arch),518 .type = relocation.encode(.tpoff, cpu_arch),
519 .target = symbol,
511 });520 });
512 } else if (is_dyn_lib) {521 } else if (is_dyn_lib) {
513 elf_file.addRelaDynAssumeCapacity(.{522 elf_file.addRelaDynAssumeCapacity(.{
514 .offset = offset,523 .offset = offset,
515 .type = relocation.encode(.tpoff, cpu_arch),524 .type = relocation.encode(.tpoff, cpu_arch),
516 .addend = symbol.?.address(.{}, elf_file) - elf_file.tlsAddress(),525 .addend = symbol.?.address(.{}, elf_file) - elf_file.tlsAddress(),
526 .target = symbol,
517 });527 });
518 }528 }
519 },529 },
...@@ -525,6 +535,7 @@ pub const GotSection = struct {...@@ -525,6 +535,7 @@ pub const GotSection = struct {
525 .sym = if (symbol.?.flags.import) extra.?.dynamic else 0,535 .sym = if (symbol.?.flags.import) extra.?.dynamic else 0,
526 .type = relocation.encode(.tlsdesc, cpu_arch),536 .type = relocation.encode(.tlsdesc, cpu_arch),
527 .addend = if (symbol.?.flags.import) 0 else symbol.?.address(.{}, elf_file) - elf_file.tlsAddress(),537 .addend = if (symbol.?.flags.import) 0 else symbol.?.address(.{}, elf_file) - elf_file.tlsAddress(),
538 .target = symbol,
528 });539 });
529 },540 },
530 }541 }
...@@ -681,6 +692,9 @@ pub const PltSection = struct {...@@ -681,6 +692,9 @@ pub const PltSection = struct {
681 const gpa = comp.gpa;692 const gpa = comp.gpa;
682 const cpu_arch = elf_file.getTarget().cpu.arch;693 const cpu_arch = elf_file.getTarget().cpu.arch;
683 try elf_file.rela_plt.ensureUnusedCapacity(gpa, plt.numRela());694 try elf_file.rela_plt.ensureUnusedCapacity(gpa, plt.numRela());
695
696 relocs_log.debug(".plt", .{});
697
684 for (plt.symbols.items) |ref| {698 for (plt.symbols.items) |ref| {
685 const sym = elf_file.symbol(ref).?;699 const sym = elf_file.symbol(ref).?;
686 assert(sym.flags.import);700 assert(sym.flags.import);
...@@ -688,6 +702,14 @@ pub const PltSection = struct {...@@ -688,6 +702,14 @@ pub const PltSection = struct {
688 const r_offset: u64 = @intCast(sym.gotPltAddress(elf_file));702 const r_offset: u64 = @intCast(sym.gotPltAddress(elf_file));
689 const r_sym: u64 = extra.dynamic;703 const r_sym: u64 = extra.dynamic;
690 const r_type = relocation.encode(.jump_slot, cpu_arch);704 const r_type = relocation.encode(.jump_slot, cpu_arch);
705
706 relocs_log.debug(" {s}: [{x} => {d}({s})] + 0", .{
707 relocation.fmtRelocType(r_type, cpu_arch),
708 r_offset,
709 r_sym,
710 sym.name(elf_file),
711 });
712
691 elf_file.rela_plt.appendAssumeCapacity(.{713 elf_file.rela_plt.appendAssumeCapacity(.{
692 .r_offset = r_offset,714 .r_offset = r_offset,
693 .r_info = (r_sym << 32) | r_type,715 .r_info = (r_sym << 32) | r_type,
...@@ -895,8 +917,7 @@ pub const PltGotSection = struct {...@@ -895,8 +917,7 @@ pub const PltGotSection = struct {
895 const gpa = comp.gpa;917 const gpa = comp.gpa;
896 const index = @as(u32, @intCast(plt_got.symbols.items.len));918 const index = @as(u32, @intCast(plt_got.symbols.items.len));
897 const symbol = elf_file.symbol(ref).?;919 const symbol = elf_file.symbol(ref).?;
898 symbol.flags.has_plt = true;920 symbol.flags.has_pltgot = true;
899 symbol.flags.has_got = true;
900 symbol.addExtra(.{ .plt_got = index }, elf_file);921 symbol.addExtra(.{ .plt_got = index }, elf_file);
901 try plt_got.symbols.append(gpa, ref);922 try plt_got.symbols.append(gpa, ref);
902 }923 }
...@@ -1054,6 +1075,9 @@ pub const CopyRelSection = struct {...@@ -1054,6 +1075,9 @@ pub const CopyRelSection = struct {
1054 const gpa = comp.gpa;1075 const gpa = comp.gpa;
1055 const cpu_arch = elf_file.getTarget().cpu.arch;1076 const cpu_arch = elf_file.getTarget().cpu.arch;
1056 try elf_file.rela_dyn.ensureUnusedCapacity(gpa, copy_rel.numRela());1077 try elf_file.rela_dyn.ensureUnusedCapacity(gpa, copy_rel.numRela());
1078
1079 relocs_log.debug(".copy.rel", .{});
1080
1057 for (copy_rel.symbols.items) |ref| {1081 for (copy_rel.symbols.items) |ref| {
1058 const sym = elf_file.symbol(ref).?;1082 const sym = elf_file.symbol(ref).?;
1059 assert(sym.flags.import and sym.flags.has_copy_rel);1083 assert(sym.flags.import and sym.flags.has_copy_rel);
...@@ -1526,6 +1550,7 @@ const elf = std.elf;...@@ -1526,6 +1550,7 @@ const elf = std.elf;
1526const math = std.math;1550const math = std.math;
1527const mem = std.mem;1551const mem = std.mem;
1528const log = std.log.scoped(.link);1552const log = std.log.scoped(.link);
1553const relocs_log = std.log.scoped(.link_relocs);
1529const relocation = @import("relocation.zig");1554const relocation = @import("relocation.zig");
1530const std = @import("std");1555const std = @import("std");
15311556