authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-11 07:27:24+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:05+02:00
log6a7a20520d02f958e1354636f99fcac53cc9c146
treee88a9db1e17020d8420e4d92aa932c954bf62bb0
parent5148e38751e5f9415e226a6bc7f8f8c0d104f818

elf: always write PHDR table, at least for now


2 files changed, 55 insertions(+), 97 deletions(-)

src/link/Dwarf.zig+1-1
...@@ -2642,7 +2642,7 @@ fn addDIFile(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !u28 {...@@ -2642,7 +2642,7 @@ fn addDIFile(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !u28 {
2642 switch (self.bin_file.tag) {2642 switch (self.bin_file.tag) {
2643 .elf => {2643 .elf => {
2644 const elf_file = self.bin_file.cast(File.Elf).?;2644 const elf_file = self.bin_file.cast(File.Elf).?;
2645 elf_file.markDirty(elf_file.debug_line_section_index.?, null);2645 elf_file.markDirty(elf_file.debug_line_section_index.?);
2646 },2646 },
2647 .macho => {2647 .macho => {
2648 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;2648 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;
src/link/Elf.zig+54-96
...@@ -32,11 +32,6 @@ output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom....@@ -32,11 +32,6 @@ output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.
32phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{},32phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{},
3333
34/// Tracked loadable segments during incremental linking.34/// Tracked loadable segments during incremental linking.
35/// 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,
37/// but incremental linking means we can't ensure they are consecutive.
38/// If this segment is not needed, it won't get emitted.
39phdr_table_load_index: ?u16 = null,
40/// The index into the program headers of a PT_LOAD program header with Read and Execute flags35/// The index into the program headers of a PT_LOAD program header with Read and Execute flags
41phdr_load_re_zig_index: ?u16 = null,36phdr_load_re_zig_index: ?u16 = null,
42/// The index into the program headers of the global offset table.37/// The index into the program headers of the global offset table.
...@@ -161,7 +156,6 @@ symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},...@@ -161,7 +156,6 @@ symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
161has_text_reloc: bool = false,156has_text_reloc: bool = false,
162num_ifunc_dynrelocs: usize = 0,157num_ifunc_dynrelocs: usize = 0,
163158
164phdr_table_dirty: bool = false,
165shdr_table_dirty: bool = false,159shdr_table_dirty: bool = false,
166160
167debug_strtab_dirty: bool = false,161debug_strtab_dirty: bool = false,
...@@ -291,14 +285,17 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -291,14 +285,17 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
291 .p32 => @alignOf(elf.Elf32_Phdr),285 .p32 => @alignOf(elf.Elf32_Phdr),
292 .p64 => @alignOf(elf.Elf64_Phdr),286 .p64 => @alignOf(elf.Elf64_Phdr),
293 };287 };
288 const offset: u64 = switch (self.ptr_width) {
289 .p32 => @sizeOf(elf.Elf32_Ehdr),
290 .p64 => @sizeOf(elf.Elf64_Ehdr),
291 };
294 self.phdr_table_index = try self.addPhdr(.{292 self.phdr_table_index = try self.addPhdr(.{
295 .type = elf.PT_PHDR,293 .type = elf.PT_PHDR,
296 .flags = elf.PF_R,294 .flags = elf.PF_R,
297 .@"align" = p_align,295 .@"align" = p_align,
298 .addr = self.calcImageBase() + @sizeOf(elf.Elf64_Ehdr),296 .addr = self.calcImageBase() + offset,
299 .offset = @sizeOf(elf.Elf64_Ehdr),297 .offset = offset,
300 });298 });
301 // self.phdr_table_dirty = true;
302 }299 }
303300
304 if (options.module != null and !options.use_llvm) {301 if (options.module != null and !options.use_llvm) {
...@@ -639,7 +636,6 @@ pub fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) error{OutOfMemory}...@@ -639,7 +636,6 @@ pub fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) error{OutOfMemory}
639 .p_align = opts.alignment,636 .p_align = opts.alignment,
640 .p_flags = opts.flags,637 .p_flags = opts.flags,
641 });638 });
642 self.phdr_table_dirty = true;
643 return index;639 return index;
644}640}
645641
...@@ -711,15 +707,6 @@ pub fn initMetadata(self: *Elf) !void {...@@ -711,15 +707,6 @@ pub fn initMetadata(self: *Elf) !void {
711 const ptr_size: u8 = self.ptrWidthBytes();707 const ptr_size: u8 = self.ptrWidthBytes();
712 const is_linux = self.base.options.target.os.tag == .linux;708 const is_linux = self.base.options.target.os.tag == .linux;
713709
714 if (self.phdr_table_load_index == null) {
715 self.phdr_table_load_index = try self.allocateSegment(.{
716 .addr = self.calcImageBase(),
717 .size = 0,
718 .alignment = self.page_size,
719 });
720 self.phdr_table_dirty = true;
721 }
722
723 if (self.phdr_load_re_zig_index == null) {710 if (self.phdr_load_re_zig_index == null) {
724 self.phdr_load_re_zig_index = try self.allocateSegment(.{711 self.phdr_load_re_zig_index = try self.allocateSegment(.{
725 .size = self.base.options.program_code_size_hint,712 .size = self.base.options.program_code_size_hint,
...@@ -926,7 +913,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {...@@ -926,7 +913,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
926913
927 phdr.p_memsz = needed_size;914 phdr.p_memsz = needed_size;
928915
929 self.markDirty(shdr_index, phdr_index);916 self.markDirty(shdr_index);
930}917}
931918
932fn growSegment(self: *Elf, shndx: u16, needed_size: u64) !void {919fn growSegment(self: *Elf, shndx: u16, needed_size: u64) !void {
...@@ -1021,16 +1008,12 @@ pub fn growNonAllocSection(...@@ -1021,16 +1008,12 @@ pub fn growNonAllocSection(
10211008
1022 shdr.sh_size = needed_size; // anticipating adding the global symbols later1009 shdr.sh_size = needed_size; // anticipating adding the global symbols later
10231010
1024 self.markDirty(shdr_index, null);1011 self.markDirty(shdr_index);
1025}1012}
10261013
1027pub fn markDirty(self: *Elf, shdr_index: u16, phdr_index: ?u16) void {1014pub fn markDirty(self: *Elf, shdr_index: u16) void {
1028 self.shdr_table_dirty = true; // TODO look into only writing one section1015 self.shdr_table_dirty = true; // TODO look into only writing one section
10291016
1030 if (phdr_index) |_| {
1031 self.phdr_table_dirty = true; // TODO look into making only the one program header dirty
1032 }
1033
1034 if (self.dwarf) |_| {1017 if (self.dwarf) |_| {
1035 if (self.debug_info_section_index.? == shdr_index) {1018 if (self.debug_info_section_index.? == shdr_index) {
1036 self.debug_info_header_dirty = true;1019 self.debug_info_header_dirty = true;
...@@ -1722,68 +1705,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1722,68 +1705,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1722 }1705 }
1723 }1706 }
17241707
1725 // if (self.phdr_table_dirty) {
1726 // const phsize: u64 = switch (self.ptr_width) {
1727 // .p32 => @sizeOf(elf.Elf32_Phdr),
1728 // .p64 => @sizeOf(elf.Elf64_Phdr),
1729 // };
1730
1731 // const phdr_table_index = self.phdr_table_index.?;
1732 // const phdr_table = &self.phdrs.items[phdr_table_index];
1733 // const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?];
1734
1735 // const allocated_size = self.allocatedSize(phdr_table.p_offset);
1736 // const needed_size = self.phdrs.items.len * phsize;
1737
1738 // if (needed_size > allocated_size) {
1739 // phdr_table.p_offset = 0; // free the space
1740 // phdr_table.p_offset = self.findFreeSpace(needed_size, @as(u32, @intCast(phdr_table.p_align)));
1741 // }
1742
1743 // phdr_table_load.p_offset = mem.alignBackward(u64, phdr_table.p_offset, phdr_table_load.p_align);
1744 // const load_align_offset = phdr_table.p_offset - phdr_table_load.p_offset;
1745 // phdr_table_load.p_filesz = load_align_offset + needed_size;
1746 // phdr_table_load.p_memsz = load_align_offset + needed_size;
1747
1748 // phdr_table.p_filesz = needed_size;
1749 // phdr_table.p_vaddr = phdr_table_load.p_vaddr + load_align_offset;
1750 // phdr_table.p_paddr = phdr_table_load.p_paddr + load_align_offset;
1751 // phdr_table.p_memsz = needed_size;
1752
1753 // switch (self.ptr_width) {
1754 // .p32 => {
1755 // const buf = try gpa.alloc(elf.Elf32_Phdr, self.phdrs.items.len);
1756 // defer gpa.free(buf);
1757
1758 // for (buf, 0..) |*phdr, i| {
1759 // phdr.* = phdrTo32(self.phdrs.items[i]);
1760 // if (foreign_endian) {
1761 // mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);
1762 // }
1763 // }
1764 // try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1765 // },
1766 // .p64 => {
1767 // const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);
1768 // defer gpa.free(buf);
1769
1770 // for (buf, 0..) |*phdr, i| {
1771 // phdr.* = self.phdrs.items[i];
1772 // if (foreign_endian) {
1773 // mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);
1774 // }
1775 // }
1776 // try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1777 // },
1778 // }
1779
1780 // // We don't actually care if the phdr load section overlaps, only the phdr section matters.
1781 // phdr_table_load.p_offset = 0;
1782 // phdr_table_load.p_filesz = 0;
1783
1784 // self.phdr_table_dirty = false;
1785 // }
1786
1787 if (self.shdr_table_dirty) {1708 if (self.shdr_table_dirty) {
1788 const shsize: u64 = switch (self.ptr_width) {1709 const shsize: u64 = switch (self.ptr_width) {
1789 .p32 => @sizeOf(elf.Elf32_Shdr),1710 .p32 => @sizeOf(elf.Elf32_Shdr),
...@@ -1834,7 +1755,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1834,7 +1755,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1834 self.shdr_table_dirty = false;1755 self.shdr_table_dirty = false;
1835 }1756 }
18361757
1837 try self.writePhdrs();1758 try self.writePhdrTable();
1838 try self.writeAtoms();1759 try self.writeAtoms();
1839 try self.writeSyntheticSections();1760 try self.writeSyntheticSections();
18401761
...@@ -1859,7 +1780,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1859,7 +1780,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1859 // such as debug_line_header_dirty and debug_info_header_dirty.1780 // such as debug_line_header_dirty and debug_info_header_dirty.
1860 assert(!self.debug_abbrev_section_dirty);1781 assert(!self.debug_abbrev_section_dirty);
1861 assert(!self.debug_aranges_section_dirty);1782 assert(!self.debug_aranges_section_dirty);
1862 assert(!self.phdr_table_dirty);
1863 assert(!self.shdr_table_dirty);1783 assert(!self.shdr_table_dirty);
1864 assert(!self.debug_strtab_dirty);1784 assert(!self.debug_strtab_dirty);
1865}1785}
...@@ -2923,11 +2843,50 @@ fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64)...@@ -2923,11 +2843,50 @@ fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64)
2923 }2843 }
2924}2844}
29252845
2926fn writePhdrs(self: *Elf) !void {2846fn writePhdrTable(self: *Elf) !void {
2927 const phoff = @sizeOf(elf.Elf64_Ehdr);2847 const gpa = self.base.allocator;
2928 const phdrs_size = self.phdrs.items.len * @sizeOf(elf.Elf64_Phdr);2848 const target_endian = self.base.options.target.cpu.arch.endian();
2929 log.debug("writing program headers from 0x{x} to 0x{x}", .{ phoff, phoff + phdrs_size });2849 const foreign_endian = target_endian != builtin.cpu.arch.endian();
2930 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.phdrs.items), phoff);2850 const phsize: u64 = switch (self.ptr_width) {
2851 .p32 => @sizeOf(elf.Elf32_Phdr),
2852 .p64 => @sizeOf(elf.Elf64_Phdr),
2853 };
2854 const phdr_table = &self.phdrs.items[self.phdr_table_index.?];
2855 const needed_size = self.phdrs.items.len * phsize;
2856 phdr_table.p_filesz = needed_size;
2857 phdr_table.p_memsz = needed_size;
2858
2859 log.debug("writing program headers from 0x{x} to 0x{x}", .{
2860 phdr_table.p_offset,
2861 phdr_table.p_offset + needed_size,
2862 });
2863
2864 switch (self.ptr_width) {
2865 .p32 => {
2866 const buf = try gpa.alloc(elf.Elf32_Phdr, self.phdrs.items.len);
2867 defer gpa.free(buf);
2868
2869 for (buf, 0..) |*phdr, i| {
2870 phdr.* = phdrTo32(self.phdrs.items[i]);
2871 if (foreign_endian) {
2872 mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);
2873 }
2874 }
2875 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
2876 },
2877 .p64 => {
2878 const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);
2879 defer gpa.free(buf);
2880
2881 for (buf, 0..) |*phdr, i| {
2882 phdr.* = self.phdrs.items[i];
2883 if (foreign_endian) {
2884 mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);
2885 }
2886 }
2887 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
2888 },
2889 }
2931}2890}
29322891
2933fn writeHeader(self: *Elf) !void {2892fn writeHeader(self: *Elf) !void {
...@@ -4065,7 +4024,6 @@ fn initSpecialPhdrs(self: *Elf) !void {...@@ -4065,7 +4024,6 @@ fn initSpecialPhdrs(self: *Elf) !void {
4065 .memsz = self.base.options.stack_size_override orelse 0,4024 .memsz = self.base.options.stack_size_override orelse 0,
4066 .@"align" = 1,4025 .@"align" = 1,
4067 });4026 });
4068 // self.phdr_table_dirty = true;
4069}4027}
40704028
4071/// We need to sort constructors/destuctors in the following sections:4029/// We need to sort constructors/destuctors in the following sections: