diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-09-24 13:07:58 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-09-25 17:54:50 +0200 |
| commit | 10c68d05dbc2ff586045722c48dbf6b892587673 (patch) | |
| tree | b98535b147d8753a8176d1241195ca839f38201a /src | |
| parent | 992c6c3f68dba24c1ca92cd7e78716d2fd336495 (diff) | |
| download | zig-10c68d05dbc2ff586045722c48dbf6b892587673.tar.gz zig-10c68d05dbc2ff586045722c48dbf6b892587673.zip | |
elf: change how we create new program headers
We do not want to create additional ones per update that are duplicates
of existing ones.
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 62d6a521e6..14da54d0f0 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1048,6 +1048,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod try self.updateMergeSectionSizes(); try self.updateSectionSizes(); + try self.addLoadPhdrs(); try self.allocatePhdrTable(); try self.allocateAllocSections(); try self.sortPhdrs(); @@ -3729,27 +3730,19 @@ fn getMaxNumberOfPhdrs() u64 { return num; } -/// Calculates how many segments (PT_LOAD progam headers) are required -/// to cover the set of sections. -/// We permit a maximum of 3**2 number of segments. -fn calcNumberOfSegments(self: *Elf) usize { - var covers: [9]bool = [_]bool{false} ** 9; +fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void { for (self.sections.items(.shdr)) |shdr| { if (shdr.sh_type == elf.SHT_NULL) continue; if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; const flags = shdrToPhdrFlags(shdr.sh_flags); - covers[flags - 1] = true; - } - var count: usize = 0; - for (covers) |cover| { - if (cover) count += 1; + if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == null) { + _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD }); + } } - return count; } /// Allocates PHDR table in virtual memory and in file. fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { - const new_load_segments = self.calcNumberOfSegments(); const phdr_table = &self.phdrs.items[self.phdr_table_index.?]; const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?]; @@ -3761,7 +3754,7 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { .p32 => @sizeOf(elf.Elf32_Phdr), .p64 => @sizeOf(elf.Elf64_Phdr), }; - const needed_size = (self.phdrs.items.len + new_load_segments) * phsize; + const needed_size = self.phdrs.items.len * phsize; const available_space = self.allocatedSize(phdr_table.p_offset); if (needed_size > available_space) { @@ -3904,15 +3897,14 @@ pub fn allocateAllocSections(self: *Elf) !void { const first = slice.items(.shdr)[cover.items[0]]; var new_offset = try self.findFreeSpace(filesz, @"align"); - const phndx = try self.addPhdr(.{ - .type = elf.PT_LOAD, - .offset = new_offset, - .addr = first.sh_addr, - .memsz = memsz, - .filesz = filesz, - .@"align" = @"align", - .flags = shdrToPhdrFlags(first.sh_flags), - }); + const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).?; + const phdr = &self.phdrs.items[phndx]; + phdr.p_offset = new_offset; + phdr.p_vaddr = first.sh_addr; + phdr.p_paddr = first.sh_addr; + phdr.p_memsz = memsz; + phdr.p_filesz = filesz; + phdr.p_align = @"align"; for (cover.items) |shndx| { const shdr = &slice.items(.shdr)[shndx]; @@ -4747,7 +4739,20 @@ pub fn isEffectivelyDynLib(self: Elf) bool { }; } -pub fn addPhdr(self: *Elf, opts: struct { +fn getPhdr(self: *Elf, opts: struct { + type: u32 = 0, + flags: u32 = 0, +}) ?u16 { + for (self.phdrs.items, 0..) |phdr, phndx| { + if (self.phdr_table_load_index) |index| { + if (phndx == index) continue; + } + if (phdr.p_type == opts.type and phdr.p_flags == opts.flags) return @intCast(phndx); + } + return null; +} + +fn addPhdr(self: *Elf, opts: struct { type: u32 = 0, flags: u32 = 0, @"align": u64 = 0, |
