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,...@@ -35,7 +35,10 @@ phdr_table_index: ?u16 = null,
35/// The index into the program headers of the PT_LOAD program header containing the phdr35/// The index into the program headers of the PT_LOAD program header containing the phdr
36/// Most linkers would merge this with phdr_load_ro_index,36/// Most linkers would merge this with phdr_load_ro_index,
37/// but incremental linking means we can't ensure they are consecutive.37/// but incremental linking means we can't ensure they are consecutive.
38/// If this segment is not needed, it won't get emitted.
38phdr_table_load_index: ?u16 = null,39phdr_table_load_index: ?u16 = null,
40/// The index into the program headers of the PT_TLS program header.
41phdr_tls_index: ?u16 = null,
39/// The index into the program headers of a PT_LOAD program header with Read and Execute flags42/// The index into the program headers of a PT_LOAD program header with Read and Execute flags
40phdr_load_re_zig_index: ?u16 = null,43phdr_load_re_zig_index: ?u16 = null,
41/// The index into the program headers of the global offset table.44/// The index into the program headers of the global offset table.
...@@ -47,8 +50,6 @@ phdr_load_ro_zig_index: ?u16 = null,...@@ -47,8 +50,6 @@ phdr_load_ro_zig_index: ?u16 = null,
47phdr_load_rw_zig_index: ?u16 = null,50phdr_load_rw_zig_index: ?u16 = null,
48/// The index into the program headers of a PT_LOAD program header with zerofill data.51/// The index into the program headers of a PT_LOAD program header with zerofill data.
49phdr_load_zerofill_zig_index: ?u16 = null,52phdr_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
53entry_index: ?Symbol.Index = null,54entry_index: ?Symbol.Index = null,
54page_size: u32,55page_size: u32,
...@@ -264,7 +265,29 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -264,7 +265,29 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
264 // Append null byte to string tables265 // Append null byte to string tables
265 try self.shstrtab.buffer.append(allocator, 0);266 try self.shstrtab.buffer.append(allocator, 0);
266 try self.strtab.buffer.append(allocator, 0);267 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
269 if (options.module != null and !options.use_llvm) {292 if (options.module != null and !options.use_llvm) {
270 if (!options.strip) {293 if (!options.strip) {
...@@ -675,30 +698,10 @@ pub fn initMetadata(self: *Elf) !void {...@@ -675,30 +698,10 @@ pub fn initMetadata(self: *Elf) !void {
675 const gpa = self.base.allocator;698 const gpa = self.base.allocator;
676 const ptr_size: u8 = self.ptrWidthBytes();699 const ptr_size: u8 = self.ptrWidthBytes();
677 const is_linux = self.base.options.target.os.tag == .linux;700 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
699 if (self.phdr_table_load_index == null) {702 if (self.phdr_table_load_index == null) {
700 self.phdr_table_load_index = try self.allocateSegment(.{703 self.phdr_table_load_index = try self.allocateSegment(.{
701 .addr = image_base,704 .addr = self.calcImageBase(),
702 .size = 0,705 .size = 0,
703 .alignment = self.page_size,706 .alignment = self.page_size,
704 });707 });
...@@ -1705,67 +1708,67 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1705,67 +1708,67 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1705 }1708 }
1706 }1709 }
17071710
1708 if (self.phdr_table_dirty) {1711 // if (self.phdr_table_dirty) {
1709 const phsize: u64 = switch (self.ptr_width) {1712 // const phsize: u64 = switch (self.ptr_width) {
1710 .p32 => @sizeOf(elf.Elf32_Phdr),1713 // .p32 => @sizeOf(elf.Elf32_Phdr),
1711 .p64 => @sizeOf(elf.Elf64_Phdr),1714 // .p64 => @sizeOf(elf.Elf64_Phdr),
1712 };1715 // };
17131716
1714 const phdr_table_index = self.phdr_table_index.?;1717 // const phdr_table_index = self.phdr_table_index.?;
1715 const phdr_table = &self.phdrs.items[phdr_table_index];1718 // const phdr_table = &self.phdrs.items[phdr_table_index];
1716 const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?];1719 // const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?];
17171720
1718 const allocated_size = self.allocatedSize(phdr_table.p_offset);1721 // const allocated_size = self.allocatedSize(phdr_table.p_offset);
1719 const needed_size = self.phdrs.items.len * phsize;1722 // const needed_size = self.phdrs.items.len * phsize;
17201723
1721 if (needed_size > allocated_size) {1724 // if (needed_size > allocated_size) {
1722 phdr_table.p_offset = 0; // free the space1725 // phdr_table.p_offset = 0; // free the space
1723 phdr_table.p_offset = self.findFreeSpace(needed_size, @as(u32, @intCast(phdr_table.p_align)));1726 // phdr_table.p_offset = self.findFreeSpace(needed_size, @as(u32, @intCast(phdr_table.p_align)));
1724 }1727 // }
17251728
1726 phdr_table_load.p_offset = mem.alignBackward(u64, phdr_table.p_offset, phdr_table_load.p_align);1729 // 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;1730 // const load_align_offset = phdr_table.p_offset - phdr_table_load.p_offset;
1728 phdr_table_load.p_filesz = load_align_offset + needed_size;1731 // phdr_table_load.p_filesz = load_align_offset + needed_size;
1729 phdr_table_load.p_memsz = load_align_offset + needed_size;1732 // phdr_table_load.p_memsz = load_align_offset + needed_size;
17301733
1731 phdr_table.p_filesz = needed_size;1734 // phdr_table.p_filesz = needed_size;
1732 phdr_table.p_vaddr = phdr_table_load.p_vaddr + load_align_offset;1735 // 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;1736 // phdr_table.p_paddr = phdr_table_load.p_paddr + load_align_offset;
1734 phdr_table.p_memsz = needed_size;1737 // phdr_table.p_memsz = needed_size;
17351738
1736 switch (self.ptr_width) {1739 // switch (self.ptr_width) {
1737 .p32 => {1740 // .p32 => {
1738 const buf = try gpa.alloc(elf.Elf32_Phdr, self.phdrs.items.len);1741 // const buf = try gpa.alloc(elf.Elf32_Phdr, self.phdrs.items.len);
1739 defer gpa.free(buf);1742 // defer gpa.free(buf);
17401743
1741 for (buf, 0..) |*phdr, i| {1744 // for (buf, 0..) |*phdr, i| {
1742 phdr.* = phdrTo32(self.phdrs.items[i]);1745 // phdr.* = phdrTo32(self.phdrs.items[i]);
1743 if (foreign_endian) {1746 // if (foreign_endian) {
1744 mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);1747 // mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);
1745 }1748 // }
1746 }1749 // }
1747 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);1750 // try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1748 },1751 // },
1749 .p64 => {1752 // .p64 => {
1750 const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);1753 // const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);
1751 defer gpa.free(buf);1754 // defer gpa.free(buf);
17521755
1753 for (buf, 0..) |*phdr, i| {1756 // for (buf, 0..) |*phdr, i| {
1754 phdr.* = self.phdrs.items[i];1757 // phdr.* = self.phdrs.items[i];
1755 if (foreign_endian) {1758 // if (foreign_endian) {
1756 mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);1759 // mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);
1757 }1760 // }
1758 }1761 // }
1759 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);1762 // try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1760 },1763 // },
1761 }1764 // }
17621765
1763 // We don't actually care if the phdr load section overlaps, only the phdr section matters.1766 // // We don't actually care if the phdr load section overlaps, only the phdr section matters.
1764 phdr_table_load.p_offset = 0;1767 // phdr_table_load.p_offset = 0;
1765 phdr_table_load.p_filesz = 0;1768 // phdr_table_load.p_filesz = 0;
17661769
1767 self.phdr_table_dirty = false;1770 // self.phdr_table_dirty = false;
1768 } else try self.writePhdrs();1771 // }
17691772
1770 if (self.shdr_table_dirty) {1773 if (self.shdr_table_dirty) {
1771 const shsize: u64 = switch (self.ptr_width) {1774 const shsize: u64 = switch (self.ptr_width) {
...@@ -1817,6 +1820,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1817,6 +1820,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1817 self.shdr_table_dirty = false;1820 self.shdr_table_dirty = false;
1818 }1821 }
18191822
1823 try self.writePhdrs();
1820 try self.writeAtoms();1824 try self.writeAtoms();
1821 try self.writeSyntheticSections();1825 try self.writeSyntheticSections();
18221826
...@@ -2963,12 +2967,7 @@ fn writeHeader(self: *Elf) !void {...@@ -2963,12 +2967,7 @@ fn writeHeader(self: *Elf) !void {
2963 index += 4;2967 index += 4;
29642968
2965 const e_entry = if (self.entry_index) |entry_index| self.symbol(entry_index).value else 0;2969 const e_entry = if (self.entry_index) |entry_index| self.symbol(entry_index).value else 0;
29662970 const phdr_table_offset = self.phdrs.items[self.phdr_table_index.?].p_offset;
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);
2972 switch (self.ptr_width) {2971 switch (self.ptr_width) {
2973 .p32 => {2972 .p32 => {
2974 mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(e_entry)), endian);2973 mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(e_entry)), endian);
...@@ -4417,16 +4416,17 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -4417,16 +4416,17 @@ fn updateSectionSizes(self: *Elf) !void {
4417 }4416 }
4418}4417}
44194418
4420fn initPhdrs(self: *Elf) !void {4419fn resetPhdrs(self: *Elf) !void {
4421 // Add PHDR phdr4420 const gpa = self.base.allocator;
4422 const phdr_index = try self.addPhdr(.{4421 const phdrs = try self.phdrs.toOwnedSlice(gpa);
4423 .type = elf.PT_PHDR,4422 try self.phdrs.ensureUnusedCapacity(gpa, phdrs.len);
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 });
44294423
4424 if (self.phdr_table_index) |phndx| {
4425 self.phdrs.appendAssumeCapacity(phdrs[phndx]);
4426 }
4427}
4428
4429fn initPhdrs(self: *Elf) !void {
4430 // Add INTERP phdr if required4430 // Add INTERP phdr if required
4431 if (self.interp_section_index) |index| {4431 if (self.interp_section_index) |index| {
4432 const shdr = self.shdrs.items[index];4432 const shdr = self.shdrs.items[index];
...@@ -4543,7 +4543,7 @@ fn initPhdrs(self: *Elf) !void {...@@ -4543,7 +4543,7 @@ fn initPhdrs(self: *Elf) !void {
45434543
4544 // Backpatch size of the PHDR phdr4544 // Backpatch size of the PHDR phdr
4545 {4545 {
4546 const phdr = &self.phdrs.items[phdr_index];4546 const phdr = &self.phdrs.items[self.phdr_table_index.?];
4547 const size = @sizeOf(elf.Elf64_Phdr) * self.phdrs.items.len;4547 const size = @sizeOf(elf.Elf64_Phdr) * self.phdrs.items.len;
4548 phdr.p_filesz = size;4548 phdr.p_filesz = size;
4549 phdr.p_memsz = size;4549 phdr.p_memsz = size;
...@@ -4588,7 +4588,7 @@ pub inline fn shdrIsTls(shdr: *const elf.Elf64_Shdr) bool {...@@ -4588,7 +4588,7 @@ pub inline fn shdrIsTls(shdr: *const elf.Elf64_Shdr) bool {
4588 return shdr.sh_flags & elf.SHF_TLS != 0;4588 return shdr.sh_flags & elf.SHF_TLS != 0;
4589}4589}
45904590
4591fn allocateSectionsInMemory(self: *Elf, base_offset: u64) !void {4591fn allocateSectionsInMemory(self: *Elf, base_offset: u64) void {
4592 // We use this struct to track maximum alignment of all TLS sections.4592 // We use this struct to track maximum alignment of all TLS sections.
4593 // According to https://github.com/rui314/mold/commit/bd46edf3f0fe9e1a787ea453c4657d535622e61f in mold,4593 // According to https://github.com/rui314/mold/commit/bd46edf3f0fe9e1a787ea453c4657d535622e61f in mold,
4594 // in-file offsets have to be aligned against the start of TLS program header.4594 // in-file offsets have to be aligned against the start of TLS program header.
...@@ -4713,9 +4713,9 @@ fn allocateSections(self: *Elf) !void {...@@ -4713,9 +4713,9 @@ fn allocateSections(self: *Elf) !void {
4713 while (true) {4713 while (true) {
4714 const nphdrs = self.phdrs.items.len;4714 const nphdrs = self.phdrs.items.len;
4715 const base_offset: u64 = @sizeOf(elf.Elf64_Ehdr) + nphdrs * @sizeOf(elf.Elf64_Phdr);4715 const base_offset: u64 = @sizeOf(elf.Elf64_Ehdr) + nphdrs * @sizeOf(elf.Elf64_Phdr);
4716 try self.allocateSectionsInMemory(base_offset);4716 self.allocateSectionsInMemory(base_offset);
4717 self.allocateSectionsInFile(base_offset);4717 self.allocateSectionsInFile(base_offset);
4718 self.phdrs.clearRetainingCapacity();4718 try self.resetPhdrs();
4719 try self.initPhdrs();4719 try self.initPhdrs();
4720 if (nphdrs == self.phdrs.items.len) break;4720 if (nphdrs == self.phdrs.items.len) break;
4721 }4721 }