mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
posix: reduce the number of assumptions made by dl_iterate_phdr
Not yet fully compatible with the new linker, but still progress. Closes #25786
This commit is contained in:
parent
d33c00cad0
commit
57889cae80
@ -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,
|
||||
|
||||
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
@ -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 };
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user