| ... | @@ -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(); |
| 1050 | | 1050 | |
| | 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 | } |
| 3731 | | 3732 | |
| 3732 | /// Calculates how many segments (PT_LOAD progam headers) are required | 3733 | fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void { |
| 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; | | |
| 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 | } |
| 3749 | | 3743 | |
| 3750 | /// Allocates PHDR table in virtual memory and in file. | 3744 | /// Allocates PHDR table in virtual memory and in file. |
| 3751 | fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { | 3745 | fn 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.?]; |
| 3755 | | 3748 | |
| ... | @@ -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); |
| 3766 | | 3759 | |
| 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 { |
| 3904 | | 3897 | |
| 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 | }); | | |
| 3916 | | 3908 | |
| 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 | } |
| 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 | type: u32 = 0, | 4756 | type: u32 = 0, |
| 4752 | flags: u32 = 0, | 4757 | flags: u32 = 0, |
| 4753 | @"align": u64 = 0, | 4758 | @"align": u64 = 0, |