diff --git a/usr.bin/truss/setup.c b/usr.bin/truss/setup.c --- a/usr.bin/truss/setup.c +++ b/usr.bin/truss/setup.c @@ -74,59 +74,72 @@ static struct procabi cloudabi32 = { - "CloudABI32", - SYSDECODE_ABI_CLOUDABI32, - STAILQ_HEAD_INITIALIZER(cloudabi32.extra_syscalls), - { NULL } + .type = "CloudABI32", + .abi = SYSDECODE_ABI_CLOUDABI32, + .pointer_size = sizeof(uint32_t), + .extra_syscalls = STAILQ_HEAD_INITIALIZER(cloudabi32.extra_syscalls), + .syscalls = { NULL } }; static struct procabi cloudabi64 = { - "CloudABI64", - SYSDECODE_ABI_CLOUDABI64, - STAILQ_HEAD_INITIALIZER(cloudabi64.extra_syscalls), - { NULL } + .type = "CloudABI64", + .abi = SYSDECODE_ABI_CLOUDABI64, + .pointer_size = sizeof(uint64_t), + .extra_syscalls = STAILQ_HEAD_INITIALIZER(cloudabi64.extra_syscalls), + .syscalls = { NULL } }; static struct procabi freebsd = { - "FreeBSD", - SYSDECODE_ABI_FREEBSD, - STAILQ_HEAD_INITIALIZER(freebsd.extra_syscalls), - { NULL } + .type = "FreeBSD", + .abi = SYSDECODE_ABI_FREEBSD, + .pointer_size = sizeof(void *), + .extra_syscalls = STAILQ_HEAD_INITIALIZER(freebsd.extra_syscalls), + .syscalls = { NULL } }; -#ifdef __LP64__ +#if !defined(__SIZEOF_POINTER__) +#error "Use a modern compiler." +#endif + +#if __SIZEOF_POINTER__ > 4 static struct procabi freebsd32 = { - "FreeBSD32", - SYSDECODE_ABI_FREEBSD32, - STAILQ_HEAD_INITIALIZER(freebsd32.extra_syscalls), - { NULL } + .type = "FreeBSD32", + .abi = SYSDECODE_ABI_FREEBSD32, + .pointer_size = sizeof(uint32_t), + .compat_prefix = "freebsd32", + .extra_syscalls = STAILQ_HEAD_INITIALIZER(freebsd32.extra_syscalls), + .syscalls = { NULL } }; #endif static struct procabi linux = { - "Linux", - SYSDECODE_ABI_LINUX, - STAILQ_HEAD_INITIALIZER(linux.extra_syscalls), - { NULL } + .type = "Linux", + .abi = SYSDECODE_ABI_LINUX, + .pointer_size = sizeof(void *), + .extra_syscalls = STAILQ_HEAD_INITIALIZER(linux.extra_syscalls), + .syscalls = { NULL } }; -#ifdef __LP64__ +#if __SIZEOF_POINTER__ > 4 static struct procabi linux32 = { - "Linux32", - SYSDECODE_ABI_LINUX32, - STAILQ_HEAD_INITIALIZER(linux32.extra_syscalls), - { NULL } + .type = "Linux32", + .abi = SYSDECODE_ABI_LINUX32, + .pointer_size = sizeof(uint32_t), + .extra_syscalls = STAILQ_HEAD_INITIALIZER(linux32.extra_syscalls), + .syscalls = { NULL } }; #endif static struct procabi_table abis[] = { { "CloudABI ELF32", &cloudabi32 }, { "CloudABI ELF64", &cloudabi64 }, -#ifdef __LP64__ +#if __SIZEOF_POINTER__ == 4 + { "FreeBSD ELF32", &freebsd }, +#elif __SIZEOF_POINTER__ == 8 { "FreeBSD ELF64", &freebsd }, { "FreeBSD ELF32", &freebsd32 }, #else - { "FreeBSD ELF32", &freebsd }, +#error "Unsupported pointer size" #endif #if defined(__powerpc64__) { "FreeBSD ELF64 V2", &freebsd }, @@ -137,7 +150,7 @@ #if defined(__i386__) { "FreeBSD a.out", &freebsd }, #endif -#ifdef __LP64__ +#if __SIZEOF_POINTER__ >= 8 { "Linux ELF64", &linux }, { "Linux ELF32", &linux32 }, #else diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c --- a/usr.bin/truss/syscalls.c +++ b/usr.bin/truss/syscalls.c @@ -963,7 +963,6 @@ fprintf(fp, "|0x%x", rem); } -#ifndef __LP64__ /* * Add argument padding to subsequent system calls after Quad * syscall arguments as needed. This used to be done by hand in the @@ -1008,7 +1007,6 @@ } } } -#endif static struct syscall * find_syscall(struct procabi *abi, u_int number) @@ -1029,10 +1027,13 @@ { struct extra_syscall *es; -#ifndef __LP64__ - /* FIXME: should be based on syscall ABI not truss ABI */ - quad_fixup(&sc->decode); -#endif + /* + * quad_fixup() is currently needed for all 32-bit ABIs. + * TODO: This should probably be a function pointer inside struct + * procabi instead. + */ + if (abi->pointer_size == 4) + quad_fixup(&sc->decode); if (number < nitems(abi->syscalls)) { assert(abi->syscalls[number] == NULL); @@ -1055,16 +1056,19 @@ get_syscall(struct threadinfo *t, u_int number, u_int nargs) { struct syscall *sc; + struct procabi *procabi; const char *sysdecode_name; + const char *lookup_name; const char *name; u_int i; - sc = find_syscall(t->proc->abi, number); + procabi = t->proc->abi; + sc = find_syscall(procabi, number); if (sc != NULL) return (sc); /* Memory is not explicitly deallocated, it's released on exit(). */ - sysdecode_name = sysdecode_syscallname(t->proc->abi->abi, number); + sysdecode_name = sysdecode_syscallname(procabi->abi, number); if (sysdecode_name == NULL) asprintf(__DECONST(char **, &name), "#%d", number); else @@ -1073,8 +1077,14 @@ sc = calloc(1, sizeof(*sc)); sc->name = name; + /* Also decode compat syscalls arguments by stripping the prefix. */ + lookup_name = name; + if (procabi->compat_prefix != NULL && strncmp(procabi->compat_prefix, + name, strlen(procabi->compat_prefix)) == 0) + lookup_name += strlen(procabi->compat_prefix); + for (i = 0; i < nitems(decoded_syscalls); i++) { - if (strcmp(name, decoded_syscalls[i].name) == 0) { + if (strcmp(lookup_name, decoded_syscalls[i].name) == 0) { sc->decode = decoded_syscalls[i]; add_syscall(t->proc->abi, number, sc); return (sc); @@ -1817,12 +1827,15 @@ case StringArray: { uintptr_t addr; union { - char *strarray[0]; + int32_t strarray32[PAGE_SIZE / sizeof(int32_t)]; + int64_t strarray64[PAGE_SIZE / sizeof(int64_t)]; char buf[PAGE_SIZE]; } u; char *string; size_t len; u_int first, i; + size_t pointer_size = + trussinfo->curthread->proc->abi->pointer_size; /* * Only parse argv[] and environment arrays from exec calls @@ -1842,7 +1855,7 @@ * a partial page. */ addr = args[sc->offset]; - if (addr % sizeof(char *) != 0) { + if (addr % pointer_size != 0) { print_pointer(fp, args[sc->offset]); break; } @@ -1852,22 +1865,36 @@ print_pointer(fp, args[sc->offset]); break; } + assert(len > 0); fputc('[', fp); first = 1; i = 0; - while (u.strarray[i] != NULL) { - string = get_string(pid, (uintptr_t)u.strarray[i], 0); + for (;;) { + uintptr_t straddr; + if (pointer_size == 4) { + if (u.strarray32[i] == 0) + break; + /* sign-extend 32-bit pointers */ + straddr = (intptr_t)u.strarray32[i]; + } else if (pointer_size == 8) { + if (u.strarray64[i] == 0) + break; + straddr = (intptr_t)u.strarray64[i]; + } else { + errx(1, "Unsupported pointer size: %zu", + pointer_size); + } + string = get_string(pid, straddr, 0); fprintf(fp, "%s \"%s\"", first ? "" : ",", string); free(string); first = 0; i++; - if (i == len / sizeof(char *)) { + if (i == len / pointer_size) { addr += len; len = PAGE_SIZE; - if (get_struct(pid, addr, u.buf, len) == - -1) { + if (get_struct(pid, addr, u.buf, len) == -1) { fprintf(fp, ", "); break; } diff --git a/usr.bin/truss/truss.h b/usr.bin/truss/truss.h --- a/usr.bin/truss/truss.h +++ b/usr.bin/truss/truss.h @@ -58,6 +58,8 @@ struct procabi { const char *type; enum sysdecode_abi abi; + size_t pointer_size; + const char *compat_prefix; STAILQ_HEAD(, extra_syscall) extra_syscalls; struct syscall *syscalls[SYSCALL_NORMAL_COUNT]; };