| ... | @@ -32,11 +32,6 @@ output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom. | ... | @@ -32,11 +32,6 @@ output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom. |
| 32 | phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{}, | 32 | phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{}, |
| 33 | | 33 | |
| 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. | | |
| 39 | phdr_table_load_index: ?u16 = null, | | |
| 40 | /// The index into the program headers of a PT_LOAD program header with Read and Execute flags | 35 | /// The index into the program headers of a PT_LOAD program header with Read and Execute flags |
| 41 | phdr_load_re_zig_index: ?u16 = null, | 36 | phdr_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) = .{}, |
| 161 | has_text_reloc: bool = false, | 156 | has_text_reloc: bool = false, |
| 162 | num_ifunc_dynrelocs: usize = 0, | 157 | num_ifunc_dynrelocs: usize = 0, |
| 163 | | 158 | |
| 164 | phdr_table_dirty: bool = false, | | |
| 165 | shdr_table_dirty: bool = false, | 159 | shdr_table_dirty: bool = false, |
| 166 | | 160 | |
| 167 | debug_strtab_dirty: bool = false, | 161 | debug_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 | } |
| 303 | | 300 | |
| 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 | } |
| 645 | | 641 | |
| ... | @@ -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; |
| 713 | | 709 | |
| 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 { |
| 926 | | 913 | |
| 927 | phdr.p_memsz = needed_size; | 914 | phdr.p_memsz = needed_size; |
| 928 | | 915 | |
| 929 | self.markDirty(shdr_index, phdr_index); | 916 | self.markDirty(shdr_index); |
| 930 | } | 917 | } |
| 931 | | 918 | |
| 932 | fn growSegment(self: *Elf, shndx: u16, needed_size: u64) !void { | 919 | fn growSegment(self: *Elf, shndx: u16, needed_size: u64) !void { |
| ... | @@ -1021,16 +1008,12 @@ pub fn growNonAllocSection( | ... | @@ -1021,16 +1008,12 @@ pub fn growNonAllocSection( |
| 1021 | | 1008 | |
| 1022 | shdr.sh_size = needed_size; // anticipating adding the global symbols later | 1009 | shdr.sh_size = needed_size; // anticipating adding the global symbols later |
| 1023 | | 1010 | |
| 1024 | self.markDirty(shdr_index, null); | 1011 | self.markDirty(shdr_index); |
| 1025 | } | 1012 | } |
| 1026 | | 1013 | |
| 1027 | pub fn markDirty(self: *Elf, shdr_index: u16, phdr_index: ?u16) void { | 1014 | pub fn markDirty(self: *Elf, shdr_index: u16) void { |
| 1028 | self.shdr_table_dirty = true; // TODO look into only writing one section | 1015 | self.shdr_table_dirty = true; // TODO look into only writing one section |
| 1029 | | 1016 | |
| 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 | } |
| 1724 | | 1707 | |
| 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 | } |
| 1836 | | 1757 | |
| 1837 | try self.writePhdrs(); | 1758 | try self.writePhdrTable(); |
| 1838 | try self.writeAtoms(); | 1759 | try self.writeAtoms(); |
| 1839 | try self.writeSyntheticSections(); | 1760 | try self.writeSyntheticSections(); |
| 1840 | | 1761 | |
| ... | @@ -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 | } |
| 2925 | | 2845 | |
| 2926 | fn writePhdrs(self: *Elf) !void { | 2846 | fn 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 | } |
| 2932 | | 2891 | |
| 2933 | fn writeHeader(self: *Elf) !void { | 2892 | fn 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 | } |
| 4070 | | 4028 | |
| 4071 | /// We need to sort constructors/destuctors in the following sections: | 4029 | /// We need to sort constructors/destuctors in the following sections: |