There is quite a lot of stuff here.
The problem is that setproctitle and kern.ps_strings were using the Valgrind host auxv
rather than the guest. The proposed patch would have just ignored those memory ranges.
I've gone a fair bit further than that
1. refactored the initimg code for building the client auxv. Previously we were
simply ignoring any non-scalar entries. Now we copy most of thse as well.
That means that 'strtab' built on the client stack no longet only contains
strings, at can also now contain binary structures. Note I was a bit
concerned that there may be some alignment issues, but I haven't seen any
problems so far.
2. Added intercepts to sysctl and sysctlbyname for kern.ps_strings, then find
AT_PS_STRINGS from the client auxv that is now usable from step 1.
3. Some refactoring of sysctl and sysctlbyname syscall wrappers. More to do
there!
4. Added a setproctitle testcase (that also tests the sysctls).
5. Updated the auxv testcase now that more AT_* entries are handled.
/memcheck/tests/freebsd/scalar_13_plus
/memcheck/tests/freebsd/452275
/memcheck/tests/freebsd/errno_aligned_allocs
+/memcheck/tests/freebsd/setproctitle
# /memcheck/tests/amd64-freebsd
/memcheck/tests/amd64-freebsd/*.stderr.diff
453055 shared_timed_mutex drd test fails with "Lock shared failed" message
453602 Missing command line option to enable/disable debuginfod
452802 Handle lld 9+ split RW PT_LOAD segments correctly
+456171 [PATCH] FreeBSD: Don't record address errors when accessing the 'kern.ps_strings' sysctl struct
n-i-bz Implement vgdb invoker on FreeBSD
To see details of a given bug, visit
return orig;
}
+/* Add byte onto the string table, and return its address */
+static HChar *copy_bytes(HChar **tab, const HChar *src, SizeT size)
+{
+ HChar *cp = *tab;
+ /*VG_ROUNDUP(cp, sizeof(Word));*/
+ HChar *orig = cp;
+
+ VG_(memcpy)(cp, src, size);
+
+ *tab = cp+size;
+
+ return orig;
+}
/* ----------------------------------------------------------------
higher address +-----------------+ <- clstack_end
| |
- : string table :
- | |
- +-----------------+
- | AT_NULL |
- - -
- | auxv |
- +-----------------+
- | NULL |
- - -
- | envp |
- +-----------------+
- | NULL |
- - -
- | argv |
- +-----------------+
- | argc |
+ : string table :
+ | |
+ +-----------------+
+ | AT_NULL |
+ - -
+ | auxv |
+ +-----------------+
+ | NULL |
+ - -
+ | envp |
+ +-----------------+
+ | NULL |
+ - -
+ | argv |
+ +-----------------+
+ | argc |
lower address +-----------------+ <- sp
| undefined |
- : :
+ : :
Allocate and create the initial client stack. It is allocated down
from clstack_end, which was previously determined by the address
---------------------------------------------------------------- */
-struct auxv {
- Word a_type;
- union {
- void *a_ptr;
- Word a_val;
- } u;
-};
-
static
struct auxv *find_auxv(UWord* sp)
{
Addr clstack_start;
Int i;
Bool have_exename;
+ Word client_argv;
vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
vg_assert( VG_(args_for_client) );
stringsize += VG_(strlen)(*cpp) + 1;
}
+ Int canarylen = -1;
+ Int pagesizeslen = -1;
+
/* now, how big is the auxv? */
auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
auxsize += sizeof(*cauxv);
+ switch(cauxv->a_type) {
+ case AT_EXECPATH:
+ stringsize += VG_(strlen)(cauxv->u.a_ptr) + 1;
+ break;
+ case AT_CANARYLEN:
+ canarylen = cauxv->u.a_val;
+ /*VG_ROUNDUP(stringsize, sizeof(Word));*/
+ stringsize += canarylen;
+ break;
+ case AT_PAGESIZESLEN:
+ pagesizeslen = cauxv->u.a_val;
+ /*VG_ROUNDUP(stringsize, sizeof(Word));*/
+ stringsize += pagesizeslen;
+ break;
+#if 0
+ case AT_TIMEKEEP:
+ /*VG_ROUNDUP(stringsize, sizeof(Word));*/
+ stringsize += sizeof(struct vki_vdso_timehands);
+ break;
+#endif
+#if (FREEBSD_VERS >= FREEBSD_13_0)
+ case AT_PS_STRINGS:
+ stringsize += sizeof(struct vki_ps_strings);
+ break;
+#endif
+#if (FREEBSD_VERS >= FREEBSD_13_1)
+ // case AT_FXRNG:
+ // case AT_KPRELOAD:
+#endif
+ default:
+ break;
+ }
}
/* OK, now we know how big the client stack is */
*ptr++ = argc + (have_exename ? 1 : 0);
/* --- client argv --- */
+ client_argv = (Word)ptr;
if (info->interp_name)
*ptr++ = (Addr)copy_str(&strtab, info->interp_name);
if (info->interp_args)
/* --- auxv --- */
auxv = (struct auxv *)ptr;
*client_auxv = (UInt *)auxv;
-#if defined(VGP_x86_freebsd) && (VGO_freebsd <= FREEBSD_13_0)
- int* pagesizes = NULL;
-#endif
-
- /*
- * The PAGESIZES hack - PJF
- *
- * Normally a standalone application has a full auxv which, among
- * many other things contains a vector of integers (PAGESIZES)
- * of a platform dependent length (PAGESIZESLEN). On x86 the
- * length is 2, on amd64 the length is 3 (there are other lengths
- * for architectures not supported on Valgrind).
- *
- * When the dynamic loader executes it will run a routine
- * static void init_pagesizes(Elf_Auxinfo **aux_info)
- * (see /usr/src/libexec/rtld-elf/rltd.c). If the PAGESIZES info is in
- * auxv, init_pagesizes will use that. However, normally this loop
- * does not copy 'pointered' elements (because that would generate
- * 'Invalid reads' in the guest). This means that the auxv that
- * Valgrind provides to ldrt *doesn't* normally contain
- * PAGESIZES.
- *
- * So init_pagesizes falls back to using sysctlnametomib/sysctl
- * to read "hw.pagesizes". Unfortunately there seems to be a bug
- * in this for an x86 executable compiled and running on an amd64
- * kernel.
- *
- * The application sees MAXPAGESLEN as 3 (from the amd64 headers)
- * but the x86 kernel sees MAXPAGESLEN as 2. The routine that
- * copies out the data for a sysctl sees this discrepancy and
- * sets an ENOMEM error. So guest execution doesn't even get past
- * executing the dynamic linker.
- *
- * This was fixed in the kernel in May 2020, see
- * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=246215
- *
- * That means this workaround is not needed for
- * FreeBSD 13 or later, any version
- * FreeBSD 12 1201515 and later
- * FreeBSD 11 1104501 and later
- *
- * Because this is rather complicated I've just disabled the hack
- * for 13 and later
- */
+ VG_(client_auxv) = (UWord *)*client_auxv;
for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
case AT_STACKPROT:
case AT_NCPUS:
case AT_OSRELDATE:
+ case AT_PAGESIZESLEN:
+ case AT_CANARYLEN:
+
#if (FREEBSD_VERS >= FREEBSD_11)
// FreeBSD 11+ also have HWCAP and HWCAP2
case AT_EHDRFLAGS:
/* All these are pointerless, so we don't need to do
anything about them. */
break;
- // case AT_CANARYLEN:
- // case AT_EXECPATH:
- // case AT_CANARY:
-#if defined(VGP_x86_freebsd) && (VGO_freebsd <= FREEBSD_13_0)
- case AT_PAGESIZESLEN:
- if (!VG_(is32on64)()) {
- VG_(debugLog)(2, "initimg",
- "stomping auxv entry %llu\n",
- (ULong)auxv->a_type);
+
+ case AT_EXECPATH:
+ auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
+ break;
+ case AT_CANARY:
+ if (canarylen >= 1)
+ auxv->u.a_ptr = copy_bytes(&strtab, orig_auxv->u.a_ptr, canarylen);
+ else
auxv->a_type = AT_IGNORE;
- }
break;
case AT_PAGESIZES:
- if (VG_(is32on64)()) {
- pagesizes = VG_(malloc)("initimg-freebsd.cpauxv.1", 2*sizeof(int));
- pagesizes[0] = ((int*)auxv->u.a_ptr)[0];
- pagesizes[1] = ((int*)auxv->u.a_ptr)[1];
- } else {
- VG_(debugLog)(2, "initimg",
- "stomping auxv entry %llu\n",
- (ULong)auxv->a_type);
+ if (pagesizeslen >= 1)
+ auxv->u.a_ptr = copy_bytes(&strtab, orig_auxv->u.a_ptr, pagesizeslen);
+ else
auxv->a_type = AT_IGNORE;
- }
break;
-#endif
- // case AT_TIMEKEEP:
+#if 0
+ /*
+ * @todo PJF this crashes intermittently
+ */
+ case AT_TIMEKEEP:
+ auxv->u.a_ptr = copy_bytes(&strtab, orig_auxv->u.a_ptr, sizeof(struct vki_vdso_timehands));
break;
+#endif
#if (FREEBSD_VERS >= FREEBSD_13_0)
case AT_BSDFLAGS:
case AT_ARGC:
- // case AT_ARGV:
case AT_ENVC:
- // case AT_ENVV:
- // case AT_PS_STRINGS:
+ break;
+ case AT_PS_STRINGS:
+ auxv->u.a_ptr = copy_bytes(&strtab, orig_auxv->u.a_ptr, sizeof(struct vki_ps_strings));
+ ((struct vki_ps_strings*)auxv->u.a_ptr)->ps_envstr = (char**)VG_(client_envp);
+ ((struct vki_ps_strings*)auxv->u.a_ptr)->ps_argvstr = (char**)client_argv;
+ break;
+ case AT_ARGV:
+ auxv->u.a_val = client_argv;
+ break;
+ case AT_ENVV:
+ auxv->u.a_val = (Word)VG_(client_envp);
+ break;
#endif
#if (FREEBSD_VERS >= FREEBSD_13_1)
// to 12.2 leaving these 4 marked as UNIMPL in 12.2
DECL_TEMPLATE(freebsd, sys_shm_open2) // 571
// unimpl __NR_shm_rename 572
-// unimpl __NR_sigfastblock 573
+DECL_TEMPLATE(freebsd, sys_sigfastblock) // 573
DECL_TEMPLATE(freebsd, sys___realpathat) // 574
#endif
// freebsd6_ftruncate 201 FREEBSD_VERS <= 10
// x86/amd64
+static Bool sysctl_kern_ps_strings(SizeT* out, SizeT* outlen)
+{
+ Word tmp = -1;
+ const struct auxv *cauxv;
+
+ for (cauxv = (struct auxv*)VG_(client_auxv); cauxv->a_type != VKI_AT_NULL; cauxv++) {
+ if (cauxv->a_type == VKI_AT_PS_STRINGS) {
+ tmp = (Word)cauxv->u.a_ptr;
+
+ *out = tmp;
+ *outlen = sizeof(size_t);
+ return True;
+ }
+ }
+ return False;
+}
+
// SYS___sysctl 202
/* int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen); */
/* ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 */
size_t* out = (size_t*)ARG3;
size_t* outlen = (size_t*)ARG4;
*out = tmp;
- *outlen = sizeof(size_t);
+ *outlen = sizeof(ULong);
SET_STATUS_Success(0);
}
}
+ /*
+ * 2. kern.ps_strings
+ */
+ if (SARG2 >= 2 && ML_(safe_to_deref)(name, 2*sizeof(int))) {
+ if (name[0] == 1 && name[1] == 32) {
+ if (sysctl_kern_ps_strings((SizeT*)ARG3, (SizeT*)ARG4)) {
+ SET_STATUS_Success(0);
+ }
+ }
+ }
PRE_REG_READ6(int, "__sysctl", int *, name, vki_u_int32_t, namelen, void *, oldp,
vki_size_t *, oldlenp, void *, newp, vki_size_t, newlen);
PRE_REG_READ6(int, "__sysctlbyname", const char *, name, vki_size_t, namelen,
void *, oldp, vki_size_t *, oldlenp,
void *, newp, vki_size_t, newlen);
+
+
+ const char* name = (const char*)ARG1;
+ if (ML_(safe_to_deref)(name, sizeof("kern.ps_strings")) &&
+ VG_(strcmp)(name, "kern.ps_strings") == 0) {
+ if (sysctl_kern_ps_strings((SizeT*)ARG3, (SizeT*)ARG4)) {
+ SET_STATUS_Success(0);
+ }
+ }
+
// read number of ints specified in ARG2 from mem pointed to by ARG1
PRE_MEM_READ("__sysctlbyname(name)", (Addr)ARG1, ARG2 * sizeof(int));
if (ML_(safe_to_deref)((void*)(Addr)ARG4, sizeof(vki_size_t))) {
PRE_MEM_WRITE("__sysctlbyname(oldp)", (Addr)ARG3, *(vki_size_t *)ARG4);
} else {
- VG_(dmsg)("Warning: Bad oldlenp address %p in sysctl\n",
+ VG_(dmsg)("Warning: Bad oldlenp address %p in sysctlbyname\n",
(void *)(Addr)ARG4);
SET_STATUS_Failure ( VKI_EFAULT );
}
}
}
+// SYS_sigfastblock
+// int sigfastblock(int cmd, void *ptr);
+PRE(sys_sigfastblock)
+{
+ PRINT("sys_sigfastblock ( %" FMT_REGWORD "d, %#" FMT_REGWORD "x )", SARG1, ARG2);
+ PRE_REG_READ2(int, "sigfasblock", int, cmd, void*, ptr);
+}
+
// SYS___realpathat 574
// from syscalls.master
// int __realpathat(int fd,
#if (FREEBSD_VERS >= FREEBSD_13_0)
BSDXY(__NR_shm_open2, sys_shm_open2), // 571
// unimpl __NR_shm_rename 572
- // unimpl __NR_sigfastblock 573
+ BSDX_(__NR_sigfastblock, sys_sigfastblock), // 573
BSDXY( __NR___realpathat, sys___realpathat), // 574
#endif
// unimpl __NR_close_range 575
if (sr_isError(sres))
#endif
sres = VG_(open)(buf, VKI_O_RDONLY, 0);
+ //sres = VG_(open)("/usr/home/paulf/build/src/obj/usr/home/paulf/build/src/amd64.amd64/libexec/rtld-elf/ld-elf.so.1.full", VKI_O_RDONLY, 0);
if (sr_isError(sres)) {
VG_(printf)("valgrind: m_ume.c: can't open interpreter\n");
VG_(exit)(1);
extern Int VG_(sysctlbyname)(const HChar *name, void *oldp, SizeT *oldlenp, const void *newp, SizeT newlen);
extern Int VG_(getosreldate)(void);
extern Bool VG_(is32on64)(void);
+
+struct auxv {
+ Word a_type;
+ union {
+ void *a_ptr;
+ Word a_val;
+ } u;
+};
+
#endif
// icache invalidation
typedef struct vki_sigaction_base vki_sigaction_toK_t;
typedef struct vki_sigaction_base vki_sigaction_fromK_t;
+//----------------------------------------------------------------------
+// sys/vdso.h
+//----------------------------------------------------------------------
+#define VKI_VDSO_TIMEHANDS_MD \
+ vki_uint32_t th_x86_shift; \
+ vki_uint32_t th_x86_hpet_idx; \
+ vki_uint32_t th_res[6];
+
+struct vki_bintime {
+ vki_time_t sec;
+ vki_uint64_t frac;
+};
+
+struct vki_vdso_timehands {
+ vki_uint32_t th_algo;
+ vki_uint32_t th_gen;
+ vki_uint64_t th_scale;
+ vki_uint32_t th_offset_count;
+ vki_uint32_t th_counter_mask;
+ struct vki_bintime th_offset;
+ struct vki_bintime th_boottime;
+ VKI_VDSO_TIMEHANDS_MD
+};
+
+
#endif /* VKI_AMD64_FREEBSD_H */
struct in6_addr *ip6;
};
+//----------------------------------------------------------------------
+// From sys/exec.h
+//----------------------------------------------------------------------
+
+struct vki_ps_strings {
+ char** ps_argvstr;
+ unsigned int ps_nargvstr;
+
+ char** ps_envstr;
+ unsigned int ps_nenvstr;
+};
+
+//----------------------------------------------------------------------
+// From sys/elf_common.h
+//----------------------------------------------------------------------
+#define VKI_AT_NULL 0
+#define VKI_AT_PS_STRINGS 32
// See syswrap-freebsd.c PRE/POST(sys_ioctl)
#if 0
typedef struct vki_sigaction_base vki_sigaction_toK_t;
typedef struct vki_sigaction_base vki_sigaction_fromK_t;
+//----------------------------------------------------------------------
+// sys/vdso.h
+//----------------------------------------------------------------------
+#define VKI_VDSO_TIMEHANDS_MD \
+ vki_uint32_t th_x86_shift; \
+ vki_uint32_t th_x86_hpet_idx; \
+ vki_uint32_t th_res[6];
+
+struct vki_bintime32 {
+#if defined(__amd64__)
+ vki_uint32_t sec;
+#else
+ vki_uint64_t sec;
+#endif
+ vki_uint32_t frac[2];
+};
+
+struct vki_vdso_timehands {
+ vki_uint32_t th_algo;
+ vki_uint32_t th_gen;
+ vki_uint32_t th_scale[2];
+ vki_uint32_t th_offset_count;
+ vki_uint32_t th_counter_mask;
+ struct vki_bintime32 th_offset;
+ struct vki_bintime32 th_boottime;
+ VKI_VDSO_TIMEHANDS_MD
+};
+
+
+
#endif // VKI_X86_FREEBSD_H
/*--------------------------------------------------------------------*/
eventfd2.vgtest \
eventfd2.stderr.exp eventfd2.stdout.exp \
errno_aligned_allocs.vgtest \
- errno_aligned_allocs.stderr.exp
+ errno_aligned_allocs.stderr.exp \
+ setproctitle.vgtest \
+ setproctitle.stderr.exp \
+ setproctitle.stdout.exp
check_PROGRAMS = \
statfs pdfork_pdkill getfsstat inlinfo inlinfo_nested.so extattr \
sigwait chflags get_set_login revoke scalar capsicum getfh \
linkat scalar_fork scalar_thr_exit scalar_abort2 scalar_pdfork \
scalar_vfork stat file_locking_wait6 utimens access chmod_chown \
- misc get_set_context utimes static_allocs fexecve errno_aligned_allocs
+ misc get_set_context utimes static_allocs fexecve errno_aligned_allocs \
+ setproctitle
AM_CFLAGS += $(AM_FLAG_M3264_PRI)
AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-Warning: Bad oldlenp address 0x........ in sysctl
+Warning: Bad oldlenp address 0x........ in sysctlbyname
---------------------------------------------------------
570: SYS___sysctlbyname (putnew) 4s 2m
---------------------------------------------------------
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-Warning: Bad oldlenp address 0x........ in sysctl
+Warning: Bad oldlenp address 0x........ in sysctlbyname
---------------------------------------------------------
570: SYS___sysctlbyname (putnew) 4s 2m
---------------------------------------------------------
--- /dev/null
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/elf_common.h>
+#include <sys/auxv.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "../../../config.h"
+
+int main(void)
+{
+#if (FREEBSD_VERS >= FREEBSD_13_0)
+ unsigned long ul_ps_strings;
+ struct ps_strings* v1;
+ struct ps_strings* v2;
+ struct ps_strings* v3;
+ int name[] = {CTL_KERN, KERN_PS_STRINGS};
+
+ size_t struct_len = sizeof(ul_ps_strings);
+
+ if (sysctlbyname("kern.ps_strings", &ul_ps_strings, &struct_len, NULL, 0) < 0) {
+ perror("sysctlbyname failed:");
+ exit(-1);
+ }
+ v1 = (struct ps_strings*)ul_ps_strings;
+
+ (void)elf_aux_info(AT_PS_STRINGS, &v2, sizeof(v2));
+
+ if (sysctl(name, 2, &ul_ps_strings, &struct_len, NULL, 0) < 0) {
+ perror("sysctl failed:");
+ exit(-1);
+ }
+ v3 = (struct ps_strings*)ul_ps_strings;
+
+ if (v1 == v2 && v1 == v2) {
+ printf("OK\n");
+ } else {
+ printf("FAIL ps_strings different\n");
+ printf("v1 %p v2 %p v3 %p\n", v1, v2, v3);
+ }
+#else
+ printf("OK\n");
+#endif
+
+ setproctitle("foo %s %d", "bar", 42);
+}
+
--- /dev/null
+prog: setproctitle
+vgopts: -q
val: AT_ENTRY int: 09 ptr: 0x........
val: AT_BASE int: 07 ptr: 0x........
val: AT_EHDRFLAGS int: 24 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_EXECPATH int: 15 ptr: 0x........
val: AT_OSRELDATE int: 18 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_CANARY int: 16 ptr: 0x........
+val: AT_CANARYLEN int: 17 ptr: 0x........
val: AT_NCPUS int: 19 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_PAGESIZES int: 20 ptr: 0x........
+val: AT_PAGESIZESLEN int: 21 ptr: 0x........
val: AT_IGNORE int: 01 ptr: 0x........
val: AT_STACKPROT int: 23 ptr: 0x........
val: AT_ENTRY int: 09 ptr: 0x........
val: AT_BASE int: 07 ptr: 0x........
val: AT_EHDRFLAGS int: 24 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_EXECPATH int: 15 ptr: 0x........
val: AT_OSRELDATE int: 18 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_CANARY int: 16 ptr: 0x........
+val: AT_CANARYLEN int: 17 ptr: 0x........
val: AT_NCPUS int: 19 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_PAGESIZES int: 20 ptr: 0x........
+val: AT_PAGESIZESLEN int: 21 ptr: 0x........
val: AT_IGNORE int: 01 ptr: 0x........
val: AT_STACKPROT int: 23 ptr: 0x........
val: AT_BSDFLAGS int: 27 ptr: 0x........
val: AT_ARGC int: 28 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_ARGV int: 29 ptr: 0x........
val: AT_ENVC int: 30 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_ENVV int: 31 ptr: 0x........
+val: AT_PS_STRINGS int: 32 ptr: 0x........
val: AT_ENTRY int: 09 ptr: 0x........
val: AT_BASE int: 07 ptr: 0x........
val: AT_EHDRFLAGS int: 24 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_EXECPATH int: 15 ptr: 0x........
val: AT_OSRELDATE int: 18 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_CANARY int: 16 ptr: 0x........
+val: AT_CANARYLEN int: 17 ptr: 0x........
val: AT_NCPUS int: 19 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_PAGESIZES int: 20 ptr: 0x........
+val: AT_PAGESIZESLEN int: 21 ptr: 0x........
val: AT_IGNORE int: 01 ptr: 0x........
val: AT_STACKPROT int: 23 ptr: 0x........
val: AT_BSDFLAGS int: 27 ptr: 0x........
val: AT_ARGC int: 28 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_ARGV int: 29 ptr: 0x........
val: AT_ENVC int: 30 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
-val: AT_IGNORE int: 01 ptr: 0x........
+val: AT_ENVV int: 31 ptr: 0x........
+val: AT_PS_STRINGS int: 32 ptr: 0x........
val: AT_IGNORE int: 01 ptr: 0x........