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>
This commit is contained in:
mlugg 2025-09-10 16:41:10 +01:00
parent 1123741fd5
commit 4e45362529
No known key found for this signature in database
GPG key ID: 3F5B7DCCBF4AF02E
2 changed files with 23 additions and 19 deletions

View file

@ -95,8 +95,7 @@ pub fn get_DYNAMIC() ?[*]const elf.Dyn {
pub fn linkmap_iterator(phdrs: []const elf.Phdr) error{InvalidExe}!LinkMap.Iterator { pub fn linkmap_iterator(phdrs: []const elf.Phdr) error{InvalidExe}!LinkMap.Iterator {
_ = phdrs; _ = phdrs;
const _DYNAMIC = get_DYNAMIC() orelse { const _DYNAMIC = get_DYNAMIC() orelse {
// No PT_DYNAMIC means this is either a statically-linked program or a // No PT_DYNAMIC means this is a statically-linked non-PIE program.
// badly corrupted dynamically-linked one.
return .{ .current = null }; return .{ .current = null };
}; };

View file

@ -1884,6 +1884,16 @@ fn initSyntheticSections(self: *Elf) !void {
const ptr_size = self.ptrWidthBytes(); const ptr_size = self.ptrWidthBytes();
const shared_objects = self.shared_objects.values(); 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: { const needs_eh_frame = blk: {
if (self.zigObjectPtr()) |zo| if (self.zigObjectPtr()) |zo|
if (zo.eh_frame_index != null) break :blk true; 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; if (self.file(index).?.object.cies.items.len > 0) break true;
} else false; } else false;
}; };
if (needs_eh_frame) { if (needs_eh_frame) {
if (self.section_indexes.eh_frame == null) { if (self.section_indexes.eh_frame == null) {
self.section_indexes.eh_frame = self.sectionByName(".eh_frame") orelse try self.addSection(.{ self.section_indexes.eh_frame = self.sectionByName(".eh_frame") orelse try self.addSection(.{
@ -1922,6 +1933,7 @@ fn initSyntheticSections(self: *Elf) !void {
}); });
} }
if (have_dynamic_linker) {
if (self.section_indexes.got_plt == null) { if (self.section_indexes.got_plt == null) {
self.section_indexes.got_plt = try self.addSection(.{ self.section_indexes.got_plt = try self.addSection(.{
.name = try self.insertShString(".got.plt"), .name = try self.insertShString(".got.plt"),
@ -1930,6 +1942,9 @@ fn initSyntheticSections(self: *Elf) !void {
.addralign = @alignOf(u64), .addralign = @alignOf(u64),
}); });
} }
} else {
assert(self.plt.symbols.items.len == 0);
}
const needs_rela_dyn = blk: { const needs_rela_dyn = blk: {
if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or self.copy_rel.symbols.items.len > 0) if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or self.copy_rel.symbols.items.len > 0)
@ -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) { if (needs_interp and self.section_indexes.interp == null) {
self.section_indexes.interp = try self.addSection(.{ self.section_indexes.interp = try self.addSection(.{
.name = try self.insertShString(".interp"), .name = try self.insertShString(".interp"),