Skip to content

Commit 57889ca

Browse files
committed
posix: reduce the number of assumptions made by dl_iterate_phdr
Not yet fully compatible with the new linker, but still progress. Closes #25786
1 parent d33c00c commit 57889ca

File tree

8 files changed

+56
-65
lines changed

8 files changed

+56
-65
lines changed

lib/std/c.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3971,7 +3971,7 @@ pub const dl_phdr_info = switch (native_os) {
39713971
/// Module name.
39723972
name: ?[*:0]const u8,
39733973
/// Pointer to module's phdr.
3974-
phdr: [*]std.elf.Phdr,
3974+
phdr: [*]std.elf.ElfN.Phdr,
39753975
/// Number of entries in phdr.
39763976
phnum: u16,
39773977
/// Total number of loads.
@@ -3984,7 +3984,7 @@ pub const dl_phdr_info = switch (native_os) {
39843984
.illumos => extern struct {
39853985
addr: std.elf.Addr,
39863986
name: ?[*:0]const u8,
3987-
phdr: [*]std.elf.Phdr,
3987+
phdr: [*]std.elf.ElfN.Phdr,
39883988
phnum: std.elf.Half,
39893989
/// Incremented when a new object is mapped into the process.
39903990
adds: u64,
@@ -3995,7 +3995,7 @@ pub const dl_phdr_info = switch (native_os) {
39953995
.openbsd, .haiku, .dragonfly, .netbsd, .serenity => extern struct {
39963996
addr: usize,
39973997
name: ?[*:0]const u8,
3998-
phdr: [*]std.elf.Phdr,
3998+
phdr: [*]std.elf.ElfN.Phdr,
39993999
phnum: std.elf.Half,
40004000
},
40014001
else => void,

lib/std/debug/SelfInfo/Elf.zig

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -441,11 +441,11 @@ const DlIterContext = struct {
441441

442442
// Populate `build_id` and `gnu_eh_frame`
443443
for (info.phdr[0..info.phnum]) |phdr| {
444-
switch (phdr.p_type) {
445-
std.elf.PT_NOTE => {
444+
switch (phdr.type) {
445+
.NOTE => {
446446
// Look for .note.gnu.build-id
447-
const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.p_vaddr);
448-
var r: std.Io.Reader = .fixed(segment_ptr[0..phdr.p_memsz]);
447+
const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.vaddr);
448+
var r: std.Io.Reader = .fixed(segment_ptr[0..phdr.memsz]);
449449
const name_size = r.takeInt(u32, native_endian) catch continue;
450450
const desc_size = r.takeInt(u32, native_endian) catch continue;
451451
const note_type = r.takeInt(u32, native_endian) catch continue;
@@ -455,9 +455,9 @@ const DlIterContext = struct {
455455
const desc = r.take(desc_size) catch continue;
456456
build_id = desc;
457457
},
458-
std.elf.PT_GNU_EH_FRAME => {
459-
const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.p_vaddr);
460-
gnu_eh_frame = segment_ptr[0..phdr.p_memsz];
458+
std.elf.PT.GNU_EH_FRAME => {
459+
const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.vaddr);
460+
gnu_eh_frame = segment_ptr[0..phdr.memsz];
461461
},
462462
else => {},
463463
}
@@ -478,11 +478,11 @@ const DlIterContext = struct {
478478
});
479479

480480
for (info.phdr[0..info.phnum]) |phdr| {
481-
if (phdr.p_type != std.elf.PT_LOAD) continue;
481+
if (phdr.type != .LOAD) continue;
482482
try context.si.ranges.append(gpa, .{
483483
// Overflowing addition handles VSDOs having p_vaddr = 0xffffffffff700000
484-
.start = info.addr +% phdr.p_vaddr,
485-
.len = phdr.p_memsz,
484+
.start = info.addr +% phdr.vaddr,
485+
.len = phdr.memsz,
486486
.module_index = module_index,
487487
});
488488
}

lib/std/dynamic_library.zig

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@ pub fn get_DYNAMIC() ?[*]const elf.Dyn {
9292
});
9393
}
9494

95-
pub fn linkmap_iterator(phdrs: []const elf.Phdr) error{InvalidExe}!LinkMap.Iterator {
96-
_ = phdrs;
95+
pub fn linkmap_iterator() error{InvalidExe}!LinkMap.Iterator {
9796
const _DYNAMIC = get_DYNAMIC() orelse {
9897
// No PT_DYNAMIC means this is a statically-linked non-PIE program.
9998
return .{ .current = null };

lib/std/elf.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub const AT_L2_CACHESIZE = 44;
5050
pub const AT_L2_CACHEGEOMETRY = 45;
5151
pub const AT_L3_CACHESIZE = 46;
5252
pub const AT_L3_CACHEGEOMETRY = 47;
53+
pub const AT_MINSIGSTKSZ = 51;
5354

5455
pub const DT_NULL = 0;
5556
pub const DT_NEEDED = 1;

lib/std/os/linux.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6101,7 +6101,7 @@ pub const dirent64 = extern struct {
61016101
pub const dl_phdr_info = extern struct {
61026102
addr: usize,
61036103
name: ?[*:0]const u8,
6104-
phdr: [*]std.elf.Phdr,
6104+
phdr: [*]std.elf.ElfN.Phdr,
61056105
phnum: u16,
61066106
};
61076107

lib/std/posix.zig

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5048,6 +5048,13 @@ pub fn nanosleep(seconds: u64, nanoseconds: u64) void {
50485048
}
50495049
}
50505050

5051+
pub fn getSelfPhdrs() []std.elf.ElfN.Phdr {
5052+
const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval;
5053+
assert(getauxval(std.elf.AT_PHENT) == @sizeOf(std.elf.ElfN.Phdr));
5054+
const phdrs: [*]std.elf.ElfN.Phdr = @ptrFromInt(getauxval(std.elf.AT_PHDR));
5055+
return phdrs[0..getauxval(std.elf.AT_PHNUM)];
5056+
}
5057+
50515058
pub fn dl_iterate_phdr(
50525059
context: anytype,
50535060
comptime Error: type,
@@ -5075,59 +5082,43 @@ pub fn dl_iterate_phdr(
50755082
}
50765083
}
50775084

5078-
const elf_base = std.process.getBaseAddress();
5079-
const ehdr: *elf.Ehdr = @ptrFromInt(elf_base);
5080-
// Make sure the base address points to an ELF image.
5081-
assert(mem.eql(u8, ehdr.e_ident[0..4], elf.MAGIC));
5082-
const n_phdr = ehdr.e_phnum;
5083-
const phdrs = (@as([*]elf.Phdr, @ptrFromInt(elf_base + ehdr.e_phoff)))[0..n_phdr];
5084-
5085-
var it = dl.linkmap_iterator(phdrs) catch unreachable;
5085+
var it = dl.linkmap_iterator() catch unreachable;
50865086

50875087
// The executable has no dynamic link segment, create a single entry for
50885088
// the whole ELF image.
50895089
if (it.end()) {
5090-
// Find the base address for the ELF image, if this is a PIE the value
5091-
// is non-zero.
5092-
const base_address = for (phdrs) |*phdr| {
5093-
if (phdr.p_type == elf.PT_PHDR) {
5094-
break @intFromPtr(phdrs.ptr) - phdr.p_vaddr;
5095-
// We could try computing the difference between _DYNAMIC and
5096-
// the p_vaddr of the PT_DYNAMIC section, but using the phdr is
5097-
// good enough (Is it?).
5098-
}
5099-
} else unreachable;
5100-
5101-
var info = dl_phdr_info{
5102-
.addr = base_address,
5103-
.name = "/proc/self/exe",
5090+
const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval;
5091+
const phdrs = getSelfPhdrs();
5092+
var info: dl_phdr_info = .{
5093+
.addr = for (phdrs) |phdr| switch (phdr.type) {
5094+
.PHDR => break @intFromPtr(phdrs.ptr) - phdr.vaddr,
5095+
else => {},
5096+
} else unreachable,
5097+
.name = switch (getauxval(std.elf.AT_EXECFN)) {
5098+
0 => "/proc/self/exe",
5099+
else => |name| @ptrFromInt(name),
5100+
},
51045101
.phdr = phdrs.ptr,
5105-
.phnum = ehdr.e_phnum,
5102+
.phnum = @intCast(phdrs.len),
51065103
};
51075104

51085105
return callback(&info, @sizeOf(dl_phdr_info), context);
51095106
}
51105107

51115108
// Last return value from the callback function.
51125109
while (it.next()) |entry| {
5113-
var phdr: [*]elf.Phdr = undefined;
5114-
var phnum: u16 = undefined;
5115-
5116-
if (entry.l_addr != 0) {
5117-
const elf_header: *elf.Ehdr = @ptrFromInt(entry.l_addr);
5118-
phdr = @ptrFromInt(entry.l_addr + elf_header.e_phoff);
5119-
phnum = elf_header.e_phnum;
5120-
} else {
5121-
// This is the running ELF image
5122-
phdr = @ptrFromInt(elf_base + ehdr.e_phoff);
5123-
phnum = ehdr.e_phnum;
5124-
}
5125-
5126-
var info = dl_phdr_info{
5110+
const phdrs: []elf.ElfN.Phdr = if (entry.l_addr != 0) phdrs: {
5111+
const ehdr: *elf.ElfN.Ehdr = @ptrFromInt(entry.l_addr);
5112+
assert(mem.eql(u8, ehdr.ident[0..4], elf.MAGIC));
5113+
const phdrs: [*]elf.ElfN.Phdr = @ptrFromInt(entry.l_addr + ehdr.phoff);
5114+
break :phdrs phdrs[0..ehdr.phnum];
5115+
} else getSelfPhdrs();
5116+
5117+
var info: dl_phdr_info = .{
51275118
.addr = entry.l_addr,
51285119
.name = entry.l_name,
5129-
.phdr = phdr,
5130-
.phnum = phnum,
5120+
.phdr = phdrs.ptr,
5121+
.phnum = @intCast(phdrs.len),
51315122
};
51325123

51335124
try callback(&info, @sizeOf(dl_phdr_info), context);

lib/std/posix/test.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,11 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {
257257
while (i < info.phnum) : (i += 1) {
258258
const phdr = info.phdr[i];
259259

260-
if (phdr.p_type != elf.PT_LOAD) continue;
260+
if (phdr.type != .LOAD) continue;
261261

262-
const reloc_addr = info.addr + phdr.p_vaddr;
262+
const reloc_addr = info.addr + phdr.vaddr;
263263
// Find the ELF header
264-
const elf_header = @as(*elf.Ehdr, @ptrFromInt(reloc_addr - phdr.p_offset));
264+
const elf_header = @as(*elf.Ehdr, @ptrFromInt(reloc_addr - phdr.offset));
265265
// Validate the magic
266266
if (!mem.eql(u8, elf_header.e_ident[0..4], elf.MAGIC)) return error.BadElfMagic;
267267
// Consistency check

lib/std/process.zig

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,13 +1658,13 @@ fn posixGetUserInfoPasswdStream(name: []const u8, reader: *std.Io.Reader) !UserI
16581658
pub fn getBaseAddress() usize {
16591659
switch (native_os) {
16601660
.linux => {
1661-
const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval;
1662-
const base = getauxval(std.elf.AT_BASE);
1663-
if (base != 0) {
1664-
return base;
1665-
}
1666-
const phdr = getauxval(std.elf.AT_PHDR);
1667-
return phdr - @sizeOf(std.elf.Ehdr);
1661+
const phdrs = std.posix.getSelfPhdrs();
1662+
var base: usize = 0;
1663+
for (phdrs) |phdr| switch (phdr.type) {
1664+
.LOAD => return base + phdr.vaddr,
1665+
.PHDR => base = @intFromPtr(phdrs.ptr) - phdr.vaddr,
1666+
else => {},
1667+
} else unreachable;
16681668
},
16691669
.driverkit, .ios, .macos, .tvos, .visionos, .watchos => {
16701670
return @intFromPtr(&std.c._mh_execute_header);

0 commit comments

Comments
 (0)