commit 4e45362529e05ba1be44fab48bc3469f5bb6492d (tree)
parent 1123741fd5fc6545daf10e2bcdcad74ec148f61b
Author: mlugg <mlugg@mlugg.co.uk>
Date: Wed, 10 Sep 2025 16:41:10 +0100
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>
Diffstat:
2 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig
@@ -95,8 +95,7 @@ pub fn get_DYNAMIC() ?[*]const elf.Dyn {
pub fn linkmap_iterator(phdrs: []const elf.Phdr) error{InvalidExe}!LinkMap.Iterator {
_ = phdrs;
const _DYNAMIC = get_DYNAMIC() orelse {
- // No PT_DYNAMIC means this is either a statically-linked program or a
- // badly corrupted dynamically-linked one.
+ // No PT_DYNAMIC means this is a statically-linked non-PIE program.
return .{ .current = null };
};
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
@@ -1884,6 +1884,16 @@ fn initSyntheticSections(self: *Elf) !void {
const ptr_size = self.ptrWidthBytes();
const shared_objects = self.shared_objects.values();
+ const is_exe_or_dyn_lib = switch (comp.config.output_mode) {
+ .Exe => true,
+ .Lib => comp.config.link_mode == .dynamic,
+ .Obj => false,
+ };
+ const have_dynamic_linker = comp.config.link_mode == .dynamic and is_exe_or_dyn_lib and !target.dynamic_linker.eql(.none);
+
+ const needs_interp = have_dynamic_linker and
+ (comp.config.link_libc or comp.root_mod.resolved_target.is_explicit_dynamic_linker);
+
const needs_eh_frame = blk: {
if (self.zigObjectPtr()) |zo|
if (zo.eh_frame_index != null) break :blk true;
@@ -1891,6 +1901,7 @@ fn initSyntheticSections(self: *Elf) !void {
if (self.file(index).?.object.cies.items.len > 0) break true;
} else false;
};
+
if (needs_eh_frame) {
if (self.section_indexes.eh_frame == null) {
self.section_indexes.eh_frame = self.sectionByName(".eh_frame") orelse try self.addSection(.{
@@ -1922,13 +1933,17 @@ fn initSyntheticSections(self: *Elf) !void {
});
}
- if (self.section_indexes.got_plt == null) {
- self.section_indexes.got_plt = try self.addSection(.{
- .name = try self.insertShString(".got.plt"),
- .type = elf.SHT_PROGBITS,
- .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
- .addralign = @alignOf(u64),
- });
+ if (have_dynamic_linker) {
+ if (self.section_indexes.got_plt == null) {
+ self.section_indexes.got_plt = try self.addSection(.{
+ .name = try self.insertShString(".got.plt"),
+ .type = elf.SHT_PROGBITS,
+ .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
+ .addralign = @alignOf(u64),
+ });
+ }
+ } else {
+ assert(self.plt.symbols.items.len == 0);
}
const needs_rela_dyn = blk: {
@@ -1989,16 +2004,6 @@ fn initSyntheticSections(self: *Elf) !void {
});
}
- const is_exe_or_dyn_lib = switch (comp.config.output_mode) {
- .Exe => true,
- .Lib => comp.config.link_mode == .dynamic,
- .Obj => false,
- };
- const have_dynamic_linker = comp.config.link_mode == .dynamic and is_exe_or_dyn_lib and !target.dynamic_linker.eql(.none);
-
- const needs_interp = have_dynamic_linker and
- (comp.config.link_libc or comp.root_mod.resolved_target.is_explicit_dynamic_linker);
-
if (needs_interp and self.section_indexes.interp == null) {
self.section_indexes.interp = try self.addSection(.{
.name = try self.insertShString(".interp"),