diff --git a/lib/std/c.zig b/lib/std/c.zig index 0a1337c16e..0bf9f40bb1 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -3971,7 +3971,7 @@ pub const dl_phdr_info = switch (native_os) { /// Module name. name: ?[*:0]const u8, /// Pointer to module's phdr. - phdr: [*]std.elf.Phdr, + phdr: [*]std.elf.ElfN.Phdr, /// Number of entries in phdr. phnum: u16, /// Total number of loads. @@ -3984,7 +3984,7 @@ pub const dl_phdr_info = switch (native_os) { .illumos => extern struct { addr: std.elf.Addr, name: ?[*:0]const u8, - phdr: [*]std.elf.Phdr, + phdr: [*]std.elf.ElfN.Phdr, phnum: std.elf.Half, /// Incremented when a new object is mapped into the process. adds: u64, @@ -3995,7 +3995,7 @@ pub const dl_phdr_info = switch (native_os) { .openbsd, .haiku, .dragonfly, .netbsd, .serenity => extern struct { addr: usize, name: ?[*:0]const u8, - phdr: [*]std.elf.Phdr, + phdr: [*]std.elf.ElfN.Phdr, phnum: std.elf.Half, }, else => void, diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index 21319b01d4..5036d40197 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -441,11 +441,11 @@ const DlIterContext = struct { // Populate `build_id` and `gnu_eh_frame` for (info.phdr[0..info.phnum]) |phdr| { - switch (phdr.p_type) { - std.elf.PT_NOTE => { + switch (phdr.type) { + .NOTE => { // Look for .note.gnu.build-id - const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.p_vaddr); - var r: std.Io.Reader = .fixed(segment_ptr[0..phdr.p_memsz]); + const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.vaddr); + var r: std.Io.Reader = .fixed(segment_ptr[0..phdr.memsz]); const name_size = r.takeInt(u32, native_endian) catch continue; const desc_size = r.takeInt(u32, native_endian) catch continue; const note_type = r.takeInt(u32, native_endian) catch continue; @@ -455,9 +455,9 @@ const DlIterContext = struct { const desc = r.take(desc_size) catch continue; build_id = desc; }, - std.elf.PT_GNU_EH_FRAME => { - const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.p_vaddr); - gnu_eh_frame = segment_ptr[0..phdr.p_memsz]; + std.elf.PT.GNU_EH_FRAME => { + const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.vaddr); + gnu_eh_frame = segment_ptr[0..phdr.memsz]; }, else => {}, } @@ -478,11 +478,11 @@ const DlIterContext = struct { }); for (info.phdr[0..info.phnum]) |phdr| { - if (phdr.p_type != std.elf.PT_LOAD) continue; + if (phdr.type != .LOAD) continue; try context.si.ranges.append(gpa, .{ // Overflowing addition handles VSDOs having p_vaddr = 0xffffffffff700000 - .start = info.addr +% phdr.p_vaddr, - .len = phdr.p_memsz, + .start = info.addr +% phdr.vaddr, + .len = phdr.memsz, .module_index = module_index, }); } diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index 90f655b95b..b889f5116e 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -92,8 +92,7 @@ pub fn get_DYNAMIC() ?[*]const elf.Dyn { }); } -pub fn linkmap_iterator(phdrs: []const elf.Phdr) error{InvalidExe}!LinkMap.Iterator { - _ = phdrs; +pub fn linkmap_iterator() error{InvalidExe}!LinkMap.Iterator { const _DYNAMIC = get_DYNAMIC() orelse { // No PT_DYNAMIC means this is a statically-linked non-PIE program. return .{ .current = null }; diff --git a/lib/std/elf.zig b/lib/std/elf.zig index db96b8b03a..163bbf283c 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -50,6 +50,7 @@ pub const AT_L2_CACHESIZE = 44; pub const AT_L2_CACHEGEOMETRY = 45; pub const AT_L3_CACHESIZE = 46; pub const AT_L3_CACHEGEOMETRY = 47; +pub const AT_MINSIGSTKSZ = 51; pub const DT_NULL = 0; pub const DT_NEEDED = 1; diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 882de1f458..acb588bcae 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -6101,7 +6101,7 @@ pub const dirent64 = extern struct { pub const dl_phdr_info = extern struct { addr: usize, name: ?[*:0]const u8, - phdr: [*]std.elf.Phdr, + phdr: [*]std.elf.ElfN.Phdr, phnum: u16, }; diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 40dfe64154..97c5c1b204 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -5048,6 +5048,13 @@ pub fn nanosleep(seconds: u64, nanoseconds: u64) void { } } +pub fn getSelfPhdrs() []std.elf.ElfN.Phdr { + const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval; + assert(getauxval(std.elf.AT_PHENT) == @sizeOf(std.elf.ElfN.Phdr)); + const phdrs: [*]std.elf.ElfN.Phdr = @ptrFromInt(getauxval(std.elf.AT_PHDR)); + return phdrs[0..getauxval(std.elf.AT_PHNUM)]; +} + pub fn dl_iterate_phdr( context: anytype, comptime Error: type, @@ -5075,34 +5082,24 @@ pub fn dl_iterate_phdr( } } - const elf_base = std.process.getBaseAddress(); - const ehdr: *elf.Ehdr = @ptrFromInt(elf_base); - // Make sure the base address points to an ELF image. - assert(mem.eql(u8, ehdr.e_ident[0..4], elf.MAGIC)); - const n_phdr = ehdr.e_phnum; - const phdrs = (@as([*]elf.Phdr, @ptrFromInt(elf_base + ehdr.e_phoff)))[0..n_phdr]; - - var it = dl.linkmap_iterator(phdrs) catch unreachable; + var it = dl.linkmap_iterator() catch unreachable; // The executable has no dynamic link segment, create a single entry for // the whole ELF image. if (it.end()) { - // Find the base address for the ELF image, if this is a PIE the value - // is non-zero. - const base_address = for (phdrs) |*phdr| { - if (phdr.p_type == elf.PT_PHDR) { - break @intFromPtr(phdrs.ptr) - phdr.p_vaddr; - // We could try computing the difference between _DYNAMIC and - // the p_vaddr of the PT_DYNAMIC section, but using the phdr is - // good enough (Is it?). - } - } else unreachable; - - var info = dl_phdr_info{ - .addr = base_address, - .name = "/proc/self/exe", + const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval; + const phdrs = getSelfPhdrs(); + var info: dl_phdr_info = .{ + .addr = for (phdrs) |phdr| switch (phdr.type) { + .PHDR => break @intFromPtr(phdrs.ptr) - phdr.vaddr, + else => {}, + } else unreachable, + .name = switch (getauxval(std.elf.AT_EXECFN)) { + 0 => "/proc/self/exe", + else => |name| @ptrFromInt(name), + }, .phdr = phdrs.ptr, - .phnum = ehdr.e_phnum, + .phnum = @intCast(phdrs.len), }; return callback(&info, @sizeOf(dl_phdr_info), context); @@ -5110,24 +5107,18 @@ pub fn dl_iterate_phdr( // Last return value from the callback function. while (it.next()) |entry| { - var phdr: [*]elf.Phdr = undefined; - var phnum: u16 = undefined; + const phdrs: []elf.ElfN.Phdr = if (entry.l_addr != 0) phdrs: { + const ehdr: *elf.ElfN.Ehdr = @ptrFromInt(entry.l_addr); + assert(mem.eql(u8, ehdr.ident[0..4], elf.MAGIC)); + const phdrs: [*]elf.ElfN.Phdr = @ptrFromInt(entry.l_addr + ehdr.phoff); + break :phdrs phdrs[0..ehdr.phnum]; + } else getSelfPhdrs(); - if (entry.l_addr != 0) { - const elf_header: *elf.Ehdr = @ptrFromInt(entry.l_addr); - phdr = @ptrFromInt(entry.l_addr + elf_header.e_phoff); - phnum = elf_header.e_phnum; - } else { - // This is the running ELF image - phdr = @ptrFromInt(elf_base + ehdr.e_phoff); - phnum = ehdr.e_phnum; - } - - var info = dl_phdr_info{ + var info: dl_phdr_info = .{ .addr = entry.l_addr, .name = entry.l_name, - .phdr = phdr, - .phnum = phnum, + .phdr = phdrs.ptr, + .phnum = @intCast(phdrs.len), }; try callback(&info, @sizeOf(dl_phdr_info), context); diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig index d58bf30677..b1daf11730 100644 --- a/lib/std/posix/test.zig +++ b/lib/std/posix/test.zig @@ -257,11 +257,11 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void { while (i < info.phnum) : (i += 1) { const phdr = info.phdr[i]; - if (phdr.p_type != elf.PT_LOAD) continue; + if (phdr.type != .LOAD) continue; - const reloc_addr = info.addr + phdr.p_vaddr; + const reloc_addr = info.addr + phdr.vaddr; // Find the ELF header - const elf_header = @as(*elf.Ehdr, @ptrFromInt(reloc_addr - phdr.p_offset)); + const elf_header = @as(*elf.Ehdr, @ptrFromInt(reloc_addr - phdr.offset)); // Validate the magic if (!mem.eql(u8, elf_header.e_ident[0..4], elf.MAGIC)) return error.BadElfMagic; // Consistency check diff --git a/lib/std/process.zig b/lib/std/process.zig index eb748e3b3e..ee81bdad26 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -1658,13 +1658,13 @@ fn posixGetUserInfoPasswdStream(name: []const u8, reader: *std.Io.Reader) !UserI pub fn getBaseAddress() usize { switch (native_os) { .linux => { - const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval; - const base = getauxval(std.elf.AT_BASE); - if (base != 0) { - return base; - } - const phdr = getauxval(std.elf.AT_PHDR); - return phdr - @sizeOf(std.elf.Ehdr); + const phdrs = std.posix.getSelfPhdrs(); + var base: usize = 0; + for (phdrs) |phdr| switch (phdr.type) { + .LOAD => return base + phdr.vaddr, + .PHDR => base = @intFromPtr(phdrs.ptr) - phdr.vaddr, + else => {}, + } else unreachable; }, .driverkit, .ios, .macos, .tvos, .visionos, .watchos => { return @intFromPtr(&std.c._mh_execute_header);