authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-10 13:20:42+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:05+02:00
log59fcf16732b614c998088f1d4c8d59a46d460ed5
treefccbdb1f70668a6cee7925957b279c542f46192d
parente571208433ad4ec99e62d488aa9f244472e7ea6f

elf: move creation of PT_PHDR out of initPhdrs and initMetadata


1 files changed, 104 insertions(+), 104 deletions(-)

src/link/Elf.zig+104-104
......@@ -35,7 +35,10 @@ phdr_table_index: ?u16 = null,
3535/// The index into the program headers of the PT_LOAD program header containing the phdr
3636/// Most linkers would merge this with phdr_load_ro_index,
3737/// but incremental linking means we can't ensure they are consecutive.
38/// If this segment is not needed, it won't get emitted.
3839phdr_table_load_index: ?u16 = null,
40/// The index into the program headers of the PT_TLS program header.
41phdr_tls_index: ?u16 = null,
3942/// The index into the program headers of a PT_LOAD program header with Read and Execute flags
4043phdr_load_re_zig_index: ?u16 = null,
4144/// The index into the program headers of the global offset table.
......@@ -47,8 +50,6 @@ phdr_load_ro_zig_index: ?u16 = null,
4750phdr_load_rw_zig_index: ?u16 = null,
4851/// The index into the program headers of a PT_LOAD program header with zerofill data.
4952phdr_load_zerofill_zig_index: ?u16 = null,
50/// The index into the program headers of the PT_TLS program header.
51phdr_tls_index: ?u16 = null,
5253
5354entry_index: ?Symbol.Index = null,
5455page_size: u32,
......@@ -264,7 +265,29 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
264265 // Append null byte to string tables
265266 try self.shstrtab.buffer.append(allocator, 0);
266267 try self.strtab.buffer.append(allocator, 0);
267 try self.dynstrtab.buffer.append(allocator, 0);
268
269 const is_obj_or_ar = switch (options.output_mode) {
270 .Obj => true,
271 .Lib => options.link_mode == .Static,
272 else => false,
273 };
274 if (!is_obj_or_ar) {
275 try self.dynstrtab.buffer.append(allocator, 0);
276
277 // Initialize PT_PHDR program header
278 const p_align: u16 = switch (self.ptr_width) {
279 .p32 => @alignOf(elf.Elf32_Phdr),
280 .p64 => @alignOf(elf.Elf64_Phdr),
281 };
282 self.phdr_table_index = try self.addPhdr(.{
283 .type = elf.PT_PHDR,
284 .flags = elf.PF_R,
285 .@"align" = p_align,
286 .addr = self.calcImageBase() + @sizeOf(elf.Elf64_Ehdr),
287 .offset = @sizeOf(elf.Elf64_Ehdr),
288 });
289 // self.phdr_table_dirty = true;
290 }
268291
269292 if (options.module != null and !options.use_llvm) {
270293 if (!options.strip) {
......@@ -675,30 +698,10 @@ pub fn initMetadata(self: *Elf) !void {
675698 const gpa = self.base.allocator;
676699 const ptr_size: u8 = self.ptrWidthBytes();
677700 const is_linux = self.base.options.target.os.tag == .linux;
678 const image_base = self.calcImageBase();
679
680 if (self.phdr_table_index == null) {
681 self.phdr_table_index = @intCast(self.phdrs.items.len);
682 const p_align: u16 = switch (self.ptr_width) {
683 .p32 => @alignOf(elf.Elf32_Phdr),
684 .p64 => @alignOf(elf.Elf64_Phdr),
685 };
686 try self.phdrs.append(gpa, .{
687 .p_type = elf.PT_PHDR,
688 .p_offset = 0,
689 .p_filesz = 0,
690 .p_vaddr = image_base,
691 .p_paddr = image_base,
692 .p_memsz = 0,
693 .p_align = p_align,
694 .p_flags = elf.PF_R,
695 });
696 self.phdr_table_dirty = true;
697 }
698701
699702 if (self.phdr_table_load_index == null) {
700703 self.phdr_table_load_index = try self.allocateSegment(.{
701 .addr = image_base,
704 .addr = self.calcImageBase(),
702705 .size = 0,
703706 .alignment = self.page_size,
704707 });
......@@ -1705,67 +1708,67 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
17051708 }
17061709 }
17071710
1708 if (self.phdr_table_dirty) {
1709 const phsize: u64 = switch (self.ptr_width) {
1710 .p32 => @sizeOf(elf.Elf32_Phdr),
1711 .p64 => @sizeOf(elf.Elf64_Phdr),
1712 };
1713
1714 const phdr_table_index = self.phdr_table_index.?;
1715 const phdr_table = &self.phdrs.items[phdr_table_index];
1716 const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?];
1717
1718 const allocated_size = self.allocatedSize(phdr_table.p_offset);
1719 const needed_size = self.phdrs.items.len * phsize;
1720
1721 if (needed_size > allocated_size) {
1722 phdr_table.p_offset = 0; // free the space
1723 phdr_table.p_offset = self.findFreeSpace(needed_size, @as(u32, @intCast(phdr_table.p_align)));
1724 }
1725
1726 phdr_table_load.p_offset = mem.alignBackward(u64, phdr_table.p_offset, phdr_table_load.p_align);
1727 const load_align_offset = phdr_table.p_offset - phdr_table_load.p_offset;
1728 phdr_table_load.p_filesz = load_align_offset + needed_size;
1729 phdr_table_load.p_memsz = load_align_offset + needed_size;
1730
1731 phdr_table.p_filesz = needed_size;
1732 phdr_table.p_vaddr = phdr_table_load.p_vaddr + load_align_offset;
1733 phdr_table.p_paddr = phdr_table_load.p_paddr + load_align_offset;
1734 phdr_table.p_memsz = needed_size;
1735
1736 switch (self.ptr_width) {
1737 .p32 => {
1738 const buf = try gpa.alloc(elf.Elf32_Phdr, self.phdrs.items.len);
1739 defer gpa.free(buf);
1740
1741 for (buf, 0..) |*phdr, i| {
1742 phdr.* = phdrTo32(self.phdrs.items[i]);
1743 if (foreign_endian) {
1744 mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);
1745 }
1746 }
1747 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1748 },
1749 .p64 => {
1750 const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);
1751 defer gpa.free(buf);
1752
1753 for (buf, 0..) |*phdr, i| {
1754 phdr.* = self.phdrs.items[i];
1755 if (foreign_endian) {
1756 mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);
1757 }
1758 }
1759 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1760 },
1761 }
1762
1763 // We don't actually care if the phdr load section overlaps, only the phdr section matters.
1764 phdr_table_load.p_offset = 0;
1765 phdr_table_load.p_filesz = 0;
1766
1767 self.phdr_table_dirty = false;
1768 } else try self.writePhdrs();
1711 // if (self.phdr_table_dirty) {
1712 // const phsize: u64 = switch (self.ptr_width) {
1713 // .p32 => @sizeOf(elf.Elf32_Phdr),
1714 // .p64 => @sizeOf(elf.Elf64_Phdr),
1715 // };
1716
1717 // const phdr_table_index = self.phdr_table_index.?;
1718 // const phdr_table = &self.phdrs.items[phdr_table_index];
1719 // const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?];
1720
1721 // const allocated_size = self.allocatedSize(phdr_table.p_offset);
1722 // const needed_size = self.phdrs.items.len * phsize;
1723
1724 // if (needed_size > allocated_size) {
1725 // phdr_table.p_offset = 0; // free the space
1726 // phdr_table.p_offset = self.findFreeSpace(needed_size, @as(u32, @intCast(phdr_table.p_align)));
1727 // }
1728
1729 // phdr_table_load.p_offset = mem.alignBackward(u64, phdr_table.p_offset, phdr_table_load.p_align);
1730 // const load_align_offset = phdr_table.p_offset - phdr_table_load.p_offset;
1731 // phdr_table_load.p_filesz = load_align_offset + needed_size;
1732 // phdr_table_load.p_memsz = load_align_offset + needed_size;
1733
1734 // phdr_table.p_filesz = needed_size;
1735 // phdr_table.p_vaddr = phdr_table_load.p_vaddr + load_align_offset;
1736 // phdr_table.p_paddr = phdr_table_load.p_paddr + load_align_offset;
1737 // phdr_table.p_memsz = needed_size;
1738
1739 // switch (self.ptr_width) {
1740 // .p32 => {
1741 // const buf = try gpa.alloc(elf.Elf32_Phdr, self.phdrs.items.len);
1742 // defer gpa.free(buf);
1743
1744 // for (buf, 0..) |*phdr, i| {
1745 // phdr.* = phdrTo32(self.phdrs.items[i]);
1746 // if (foreign_endian) {
1747 // mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);
1748 // }
1749 // }
1750 // try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1751 // },
1752 // .p64 => {
1753 // const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);
1754 // defer gpa.free(buf);
1755
1756 // for (buf, 0..) |*phdr, i| {
1757 // phdr.* = self.phdrs.items[i];
1758 // if (foreign_endian) {
1759 // mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);
1760 // }
1761 // }
1762 // try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1763 // },
1764 // }
1765
1766 // // We don't actually care if the phdr load section overlaps, only the phdr section matters.
1767 // phdr_table_load.p_offset = 0;
1768 // phdr_table_load.p_filesz = 0;
1769
1770 // self.phdr_table_dirty = false;
1771 // }
17691772
17701773 if (self.shdr_table_dirty) {
17711774 const shsize: u64 = switch (self.ptr_width) {
......@@ -1817,6 +1820,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
18171820 self.shdr_table_dirty = false;
18181821 }
18191822
1823 try self.writePhdrs();
18201824 try self.writeAtoms();
18211825 try self.writeSyntheticSections();
18221826
......@@ -2963,12 +2967,7 @@ fn writeHeader(self: *Elf) !void {
29632967 index += 4;
29642968
29652969 const e_entry = if (self.entry_index) |entry_index| self.symbol(entry_index).value else 0;
2966
2967 // TODO
2968 const phdr_table_offset = if (self.phdr_table_index) |ind|
2969 self.phdrs.items[ind].p_offset
2970 else
2971 @sizeOf(elf.Elf64_Ehdr);
2970 const phdr_table_offset = self.phdrs.items[self.phdr_table_index.?].p_offset;
29722971 switch (self.ptr_width) {
29732972 .p32 => {
29742973 mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(e_entry)), endian);
......@@ -4417,16 +4416,17 @@ fn updateSectionSizes(self: *Elf) !void {
44174416 }
44184417}
44194418
4420fn initPhdrs(self: *Elf) !void {
4421 // Add PHDR phdr
4422 const phdr_index = try self.addPhdr(.{
4423 .type = elf.PT_PHDR,
4424 .flags = elf.PF_R,
4425 .@"align" = @alignOf(elf.Elf64_Phdr),
4426 .addr = self.calcImageBase() + @sizeOf(elf.Elf64_Ehdr),
4427 .offset = @sizeOf(elf.Elf64_Ehdr),
4428 });
4419fn resetPhdrs(self: *Elf) !void {
4420 const gpa = self.base.allocator;
4421 const phdrs = try self.phdrs.toOwnedSlice(gpa);
4422 try self.phdrs.ensureUnusedCapacity(gpa, phdrs.len);
44294423
4424 if (self.phdr_table_index) |phndx| {
4425 self.phdrs.appendAssumeCapacity(phdrs[phndx]);
4426 }
4427}
4428
4429fn initPhdrs(self: *Elf) !void {
44304430 // Add INTERP phdr if required
44314431 if (self.interp_section_index) |index| {
44324432 const shdr = self.shdrs.items[index];
......@@ -4543,7 +4543,7 @@ fn initPhdrs(self: *Elf) !void {
45434543
45444544 // Backpatch size of the PHDR phdr
45454545 {
4546 const phdr = &self.phdrs.items[phdr_index];
4546 const phdr = &self.phdrs.items[self.phdr_table_index.?];
45474547 const size = @sizeOf(elf.Elf64_Phdr) * self.phdrs.items.len;
45484548 phdr.p_filesz = size;
45494549 phdr.p_memsz = size;
......@@ -4588,7 +4588,7 @@ pub inline fn shdrIsTls(shdr: *const elf.Elf64_Shdr) bool {
45884588 return shdr.sh_flags & elf.SHF_TLS != 0;
45894589}
45904590
4591fn allocateSectionsInMemory(self: *Elf, base_offset: u64) !void {
4591fn allocateSectionsInMemory(self: *Elf, base_offset: u64) void {
45924592 // We use this struct to track maximum alignment of all TLS sections.
45934593 // According to https://github.com/rui314/mold/commit/bd46edf3f0fe9e1a787ea453c4657d535622e61f in mold,
45944594 // in-file offsets have to be aligned against the start of TLS program header.
......@@ -4713,9 +4713,9 @@ fn allocateSections(self: *Elf) !void {
47134713 while (true) {
47144714 const nphdrs = self.phdrs.items.len;
47154715 const base_offset: u64 = @sizeOf(elf.Elf64_Ehdr) + nphdrs * @sizeOf(elf.Elf64_Phdr);
4716 try self.allocateSectionsInMemory(base_offset);
4716 self.allocateSectionsInMemory(base_offset);
47174717 self.allocateSectionsInFile(base_offset);
4718 self.phdrs.clearRetainingCapacity();
4718 try self.resetPhdrs();
47194719 try self.initPhdrs();
47204720 if (nphdrs == self.phdrs.items.len) break;
47214721 }