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