| ... | @@ -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 phdr | 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, | 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. |
| 38 | phdr_table_load_index: ?u16 = null, | 39 | phdr_table_load_index: ?u16 = null, |
| | 40 | /// The index into the program headers of the PT_TLS program header. |
| | 41 | phdr_tls_index: ?u16 = null, |
| 39 | /// The index into the program headers of a PT_LOAD program header with Read and Execute flags | 42 | /// The index into the program headers of a PT_LOAD program header with Read and Execute flags |
| 40 | phdr_load_re_zig_index: ?u16 = null, | 43 | phdr_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, |
| 47 | phdr_load_rw_zig_index: ?u16 = null, | 50 | phdr_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. |
| 49 | phdr_load_zerofill_zig_index: ?u16 = null, | 52 | phdr_load_zerofill_zig_index: ?u16 = null, |
| 50 | /// The index into the program headers of the PT_TLS program header. | | |
| 51 | phdr_tls_index: ?u16 = null, | | |
| 52 | | 53 | |
| 53 | entry_index: ?Symbol.Index = null, | 54 | entry_index: ?Symbol.Index = null, |
| 54 | page_size: u32, | 55 | page_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 tables | 265 | // 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 | } |
| 268 | | 291 | |
| 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 | } | | |
| 698 | | 701 | |
| 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 | } |
| 1707 | | 1710 | |
| 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 | // }; |
| 1713 | | 1716 | |
| 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.?]; |
| 1717 | | 1720 | |
| 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; |
| 1720 | | 1723 | |
| 1721 | if (needed_size > allocated_size) { | 1724 | // if (needed_size > allocated_size) { |
| 1722 | phdr_table.p_offset = 0; // free the space | 1725 | // 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 | // } |
| 1725 | | 1728 | |
| 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; |
| 1730 | | 1733 | |
| 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; |
| 1735 | | 1738 | |
| 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); |
| 1740 | | 1743 | |
| 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); |
| 1752 | | 1755 | |
| 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 | // } |
| 1762 | | 1765 | |
| 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; |
| 1766 | | 1769 | |
| 1767 | self.phdr_table_dirty = false; | 1770 | // self.phdr_table_dirty = false; |
| 1768 | } else try self.writePhdrs(); | 1771 | // } |
| 1769 | | 1772 | |
| 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 | } |
| 1819 | | 1822 | |
| | 1823 | try self.writePhdrs(); |
| 1820 | try self.writeAtoms(); | 1824 | try self.writeAtoms(); |
| 1821 | try self.writeSyntheticSections(); | 1825 | try self.writeSyntheticSections(); |
| 1822 | | 1826 | |
| ... | @@ -2963,12 +2967,7 @@ fn writeHeader(self: *Elf) !void { | ... | @@ -2963,12 +2967,7 @@ fn writeHeader(self: *Elf) !void { |
| 2963 | index += 4; | 2967 | index += 4; |
| 2964 | | 2968 | |
| 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; |
| 2966 | | 2970 | 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 | } |
| 4419 | | 4418 | |
| 4420 | fn initPhdrs(self: *Elf) !void { | 4419 | fn resetPhdrs(self: *Elf) !void { |
| 4421 | // Add PHDR phdr | 4420 | 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 | }); | | |
| 4429 | | 4423 | |
| | 4424 | if (self.phdr_table_index) |phndx| { |
| | 4425 | self.phdrs.appendAssumeCapacity(phdrs[phndx]); |
| | 4426 | } |
| | 4427 | } |
| | 4428 | |
| | 4429 | fn initPhdrs(self: *Elf) !void { |
| 4430 | // Add INTERP phdr if required | 4430 | // 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 { |
| 4543 | | 4543 | |
| 4544 | // Backpatch size of the PHDR phdr | 4544 | // 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 | } |
| 4590 | | 4590 | |
| 4591 | fn allocateSectionsInMemory(self: *Elf, base_offset: u64) !void { | 4591 | fn 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 | } |