authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-09-10 16:41:10+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-09-30 13:44:53+01:00
log4e45362529e05ba1be44fab48bc3469f5bb6492d
treeb8d161294f8519ed8471b7cdb84ff2aa037e4368
parent1123741fd5fc6545daf10e2bcdcad74ec148f61b
signaturelock-open Commit is signed but in an unrecognized format.

link.Elf: fix static PIE

We mustn't emit the DT_PLTGOT entry in `.dynamic` in a statically-linked PIE, because there's no dl to relocate it (and `std.pie.relocate`, or the PIE relocator in libc, won't touch it). In that case, there cannot be any PLT entries, so there's no point emitting the `.got.plt` section at all. If we just don't create that section, `link.Elf` already knows not to add the DT_PLTGOT entry to `.dynamic`. Co-authored-by: Jacob Young <jacobly0@users.noreply.github.com>

2 files changed, 23 insertions(+), 19 deletions(-)

lib/std/dynamic_library.zig+1-2
......@@ -95,8 +95,7 @@ pub fn get_DYNAMIC() ?[*]const elf.Dyn {
9595pub fn linkmap_iterator(phdrs: []const elf.Phdr) error{InvalidExe}!LinkMap.Iterator {
9696 _ = phdrs;
9797 const _DYNAMIC = get_DYNAMIC() orelse {
98 // No PT_DYNAMIC means this is either a statically-linked program or a
99 // badly corrupted dynamically-linked one.
98 // No PT_DYNAMIC means this is a statically-linked non-PIE program.
10099 return .{ .current = null };
101100 };
102101
src/link/Elf.zig+22-17
......@@ -1884,6 +1884,16 @@ fn initSyntheticSections(self: *Elf) !void {
18841884 const ptr_size = self.ptrWidthBytes();
18851885 const shared_objects = self.shared_objects.values();
18861886
1887 const is_exe_or_dyn_lib = switch (comp.config.output_mode) {
1888 .Exe => true,
1889 .Lib => comp.config.link_mode == .dynamic,
1890 .Obj => false,
1891 };
1892 const have_dynamic_linker = comp.config.link_mode == .dynamic and is_exe_or_dyn_lib and !target.dynamic_linker.eql(.none);
1893
1894 const needs_interp = have_dynamic_linker and
1895 (comp.config.link_libc or comp.root_mod.resolved_target.is_explicit_dynamic_linker);
1896
18871897 const needs_eh_frame = blk: {
18881898 if (self.zigObjectPtr()) |zo|
18891899 if (zo.eh_frame_index != null) break :blk true;
......@@ -1891,6 +1901,7 @@ fn initSyntheticSections(self: *Elf) !void {
18911901 if (self.file(index).?.object.cies.items.len > 0) break true;
18921902 } else false;
18931903 };
1904
18941905 if (needs_eh_frame) {
18951906 if (self.section_indexes.eh_frame == null) {
18961907 self.section_indexes.eh_frame = self.sectionByName(".eh_frame") orelse try self.addSection(.{
......@@ -1922,13 +1933,17 @@ fn initSyntheticSections(self: *Elf) !void {
19221933 });
19231934 }
19241935
1925 if (self.section_indexes.got_plt == null) {
1926 self.section_indexes.got_plt = try self.addSection(.{
1927 .name = try self.insertShString(".got.plt"),
1928 .type = elf.SHT_PROGBITS,
1929 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
1930 .addralign = @alignOf(u64),
1931 });
1936 if (have_dynamic_linker) {
1937 if (self.section_indexes.got_plt == null) {
1938 self.section_indexes.got_plt = try self.addSection(.{
1939 .name = try self.insertShString(".got.plt"),
1940 .type = elf.SHT_PROGBITS,
1941 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
1942 .addralign = @alignOf(u64),
1943 });
1944 }
1945 } else {
1946 assert(self.plt.symbols.items.len == 0);
19321947 }
19331948
19341949 const needs_rela_dyn = blk: {
......@@ -1989,16 +2004,6 @@ fn initSyntheticSections(self: *Elf) !void {
19892004 });
19902005 }
19912006
1992 const is_exe_or_dyn_lib = switch (comp.config.output_mode) {
1993 .Exe => true,
1994 .Lib => comp.config.link_mode == .dynamic,
1995 .Obj => false,
1996 };
1997 const have_dynamic_linker = comp.config.link_mode == .dynamic and is_exe_or_dyn_lib and !target.dynamic_linker.eql(.none);
1998
1999 const needs_interp = have_dynamic_linker and
2000 (comp.config.link_libc or comp.root_mod.resolved_target.is_explicit_dynamic_linker);
2001
20022007 if (needs_interp and self.section_indexes.interp == null) {
20032008 self.section_indexes.interp = try self.addSection(.{
20042009 .name = try self.insertShString(".interp"),