From 17cb69cebcb05bbc9d9f7cf01c41a97b71f8a499 Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Sat, 8 Sep 2018 03:14:30 +0000 Subject: [PATCH] fix elf auxv handling Auxillery vectors are not guaranteed to be in any order, this just happens to work on x86_64. --- std/elf.zig | 5 +++++ std/os/index.zig | 11 ++++++++--- std/os/linux/arm64.zig | 6 ++---- std/os/linux/vdso.zig | 2 +- std/special/bootstrap.zig | 7 ++----- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/std/elf.zig b/std/elf.zig index a3a72dc728..bc07bffb45 100644 --- a/std/elf.zig +++ b/std/elf.zig @@ -859,6 +859,11 @@ pub const Elf_MIPS_ABIFlags_v0 = extern struct { flags2: Elf32_Word, }; +pub const Auxv = switch (@sizeOf(usize)) { + 4 => Elf32_auxv_t, + 8 => Elf64_auxv_t, + else => @compileError("expected pointer size of 32 or 64"), +}; pub const Ehdr = switch (@sizeOf(usize)) { 4 => Elf32_Ehdr, 8 => Elf64_Ehdr, diff --git a/std/os/index.zig b/std/os/index.zig index c67fa9249c..7635386fbb 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -633,16 +633,21 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError { }; } -pub var linux_aux_raw = []usize{0} ** 38; +pub var linux_elf_aux_maybe: ?[*]std.elf.Auxv = undefined; pub var posix_environ_raw: [][*]u8 = undefined; /// See std.elf for the constants. pub fn linuxGetAuxVal(index: usize) usize { if (builtin.link_libc) { return usize(std.c.getauxval(index)); - } else { - return linux_aux_raw[index]; + } else if (linux_elf_aux_maybe) |auxv| { + var i: usize = 0; + while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) { + if (auxv[i].a_type == index) + return auxv[i].a_un.a_val; + } } + return 0; } pub fn getBaseAddress() usize { diff --git a/std/os/linux/arm64.zig b/std/os/linux/arm64.zig index 9e99c196f5..95095bad4d 100644 --- a/std/os/linux/arm64.zig +++ b/std/os/linux/arm64.zig @@ -282,10 +282,8 @@ pub const SYS_io_pgetevents = 292; pub const SYS_syscalls = 293; pub const VDSO_USEFUL = true; -pub const VDSO_CGT_SYM = "__vdso_clock_gettime"; -pub const VDSO_CGT_VER = "LINUX_2.6"; -pub const VDSO_GETCPU_SYM = "__vdso_getcpu"; -pub const VDSO_GETCPU_VER = "LINUX_2.6"; +pub const VDSO_CGT_SYM = "__kernel_clock_gettime"; +pub const VDSO_CGT_VER = "LINUX_2.6.39"; pub fn syscall0(number: usize) usize { return asm volatile ("svc #0" diff --git a/std/os/linux/vdso.zig b/std/os/linux/vdso.zig index a78e3370e6..f0e0e6eb6c 100644 --- a/std/os/linux/vdso.zig +++ b/std/os/linux/vdso.zig @@ -5,7 +5,7 @@ const cstr = std.cstr; const mem = std.mem; pub fn lookup(vername: []const u8, name: []const u8) usize { - const vdso_addr = std.os.linux_aux_raw[std.elf.AT_SYSINFO_EHDR]; + const vdso_addr = std.os.linuxGetAuxVal(std.elf.AT_SYSINFO_EHDR); if (vdso_addr == 0) return 0; const eh = @intToPtr(*elf.Ehdr, vdso_addr); diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig index 6619b2dc2f..feaa04332b 100644 --- a/std/special/bootstrap.zig +++ b/std/special/bootstrap.zig @@ -59,11 +59,8 @@ fn posixCallMainAndExit() noreturn { const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count]; if (builtin.os == builtin.Os.linux) { const auxv = @ptrCast([*]usize, envp.ptr + envp_count + 1); - var i: usize = 0; - while (auxv[i] != 0) : (i += 2) { - if (auxv[i] < std.os.linux_aux_raw.len) std.os.linux_aux_raw[auxv[i]] = auxv[i + 1]; - } - std.debug.assert(std.os.linux_aux_raw[std.elf.AT_PAGESZ] == std.os.page_size); + std.os.linux_elf_aux_maybe = @ptrCast([*]std.elf.Auxv, auxv); + std.debug.assert(std.os.linuxGetAuxVal(std.elf.AT_PAGESZ) == std.os.page_size); } std.os.posix.exit(callMainWithArgs(argc, argv, envp));