authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-24 13:07:58+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-25 17:54:50+02:00
log10c68d05dbc2ff586045722c48dbf6b892587673
treeb98535b147d8753a8176d1241195ca839f38201a
parent992c6c3f68dba24c1ca92cd7e78716d2fd336495

elf: change how we create new program headers

We do not want to create additional ones per update that are duplicates of existing ones.

1 files changed, 28 insertions(+), 23 deletions(-)

src/link/Elf.zig+28-23
...@@ -1048,6 +1048,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -1048,6 +1048,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
1048 try self.updateMergeSectionSizes();1048 try self.updateMergeSectionSizes();
1049 try self.updateSectionSizes();1049 try self.updateSectionSizes();
10501050
1051 try self.addLoadPhdrs();
1051 try self.allocatePhdrTable();1052 try self.allocatePhdrTable();
1052 try self.allocateAllocSections();1053 try self.allocateAllocSections();
1053 try self.sortPhdrs();1054 try self.sortPhdrs();
...@@ -3729,27 +3730,19 @@ fn getMaxNumberOfPhdrs() u64 {...@@ -3729,27 +3730,19 @@ fn getMaxNumberOfPhdrs() u64 {
3729 return num;3730 return num;
3730}3731}
37313732
3732/// Calculates how many segments (PT_LOAD progam headers) are required3733fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {
3733/// to cover the set of sections.
3734/// We permit a maximum of 3**2 number of segments.
3735fn calcNumberOfSegments(self: *Elf) usize {
3736 var covers: [9]bool = [_]bool{false} ** 9;
3737 for (self.sections.items(.shdr)) |shdr| {3734 for (self.sections.items(.shdr)) |shdr| {
3738 if (shdr.sh_type == elf.SHT_NULL) continue;3735 if (shdr.sh_type == elf.SHT_NULL) continue;
3739 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;3736 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
3740 const flags = shdrToPhdrFlags(shdr.sh_flags);3737 const flags = shdrToPhdrFlags(shdr.sh_flags);
3741 covers[flags - 1] = true;3738 if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == null) {
3742 }3739 _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD });
3743 var count: usize = 0;3740 }
3744 for (covers) |cover| {
3745 if (cover) count += 1;
3746 }3741 }
3747 return count;
3748}3742}
37493743
3750/// Allocates PHDR table in virtual memory and in file.3744/// Allocates PHDR table in virtual memory and in file.
3751fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {3745fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {
3752 const new_load_segments = self.calcNumberOfSegments();
3753 const phdr_table = &self.phdrs.items[self.phdr_table_index.?];3746 const phdr_table = &self.phdrs.items[self.phdr_table_index.?];
3754 const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?];3747 const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?];
37553748
...@@ -3761,7 +3754,7 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {...@@ -3761,7 +3754,7 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {
3761 .p32 => @sizeOf(elf.Elf32_Phdr),3754 .p32 => @sizeOf(elf.Elf32_Phdr),
3762 .p64 => @sizeOf(elf.Elf64_Phdr),3755 .p64 => @sizeOf(elf.Elf64_Phdr),
3763 };3756 };
3764 const needed_size = (self.phdrs.items.len + new_load_segments) * phsize;3757 const needed_size = self.phdrs.items.len * phsize;
3765 const available_space = self.allocatedSize(phdr_table.p_offset);3758 const available_space = self.allocatedSize(phdr_table.p_offset);
37663759
3767 if (needed_size > available_space) {3760 if (needed_size > available_space) {
...@@ -3904,15 +3897,14 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -3904,15 +3897,14 @@ pub fn allocateAllocSections(self: *Elf) !void {
39043897
3905 const first = slice.items(.shdr)[cover.items[0]];3898 const first = slice.items(.shdr)[cover.items[0]];
3906 var new_offset = try self.findFreeSpace(filesz, @"align");3899 var new_offset = try self.findFreeSpace(filesz, @"align");
3907 const phndx = try self.addPhdr(.{3900 const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).?;
3908 .type = elf.PT_LOAD,3901 const phdr = &self.phdrs.items[phndx];
3909 .offset = new_offset,3902 phdr.p_offset = new_offset;
3910 .addr = first.sh_addr,3903 phdr.p_vaddr = first.sh_addr;
3911 .memsz = memsz,3904 phdr.p_paddr = first.sh_addr;
3912 .filesz = filesz,3905 phdr.p_memsz = memsz;
3913 .@"align" = @"align",3906 phdr.p_filesz = filesz;
3914 .flags = shdrToPhdrFlags(first.sh_flags),3907 phdr.p_align = @"align";
3915 });
39163908
3917 for (cover.items) |shndx| {3909 for (cover.items) |shndx| {
3918 const shdr = &slice.items(.shdr)[shndx];3910 const shdr = &slice.items(.shdr)[shndx];
...@@ -4747,7 +4739,20 @@ pub fn isEffectivelyDynLib(self: Elf) bool {...@@ -4747,7 +4739,20 @@ pub fn isEffectivelyDynLib(self: Elf) bool {
4747 };4739 };
4748}4740}
47494741
4750pub fn addPhdr(self: *Elf, opts: struct {4742fn getPhdr(self: *Elf, opts: struct {
4743 type: u32 = 0,
4744 flags: u32 = 0,
4745}) ?u16 {
4746 for (self.phdrs.items, 0..) |phdr, phndx| {
4747 if (self.phdr_table_load_index) |index| {
4748 if (phndx == index) continue;
4749 }
4750 if (phdr.p_type == opts.type and phdr.p_flags == opts.flags) return @intCast(phndx);
4751 }
4752 return null;
4753}
4754
4755fn addPhdr(self: *Elf, opts: struct {
4751 type: u32 = 0,4756 type: u32 = 0,
4752 flags: u32 = 0,4757 flags: u32 = 0,
4753 @"align": u64 = 0,4758 @"align": u64 = 0,