diff --git a/usr.bin/truss/main.c b/usr.bin/truss/main.c --- a/usr.bin/truss/main.c +++ b/usr.bin/truss/main.c @@ -55,7 +55,7 @@ #include "extern.h" #include "syscall.h" -static void +static __dead2 void usage(void) { fprintf(stderr, "%s\n%s\n", @@ -118,7 +118,8 @@ fname = optarg; break; case 's': /* Specified string size */ - trussinfo->strsize = strtonum(optarg, 0, INT_MAX, &errstr); + trussinfo->strsize = (int)strtonum(optarg, 0, INT_MAX, + &errstr); if (errstr) errx(1, "maximum string size is %s: %s", errstr, optarg); break; 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 @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -863,18 +864,17 @@ if (xlat->val == val) return (xlat->str); switch (base) { - case 8: - sprintf(tmp, "0%o", val); - break; - case 16: - sprintf(tmp, "0x%x", val); - break; - case 10: - sprintf(tmp, "%u", val); - break; - default: - errx(1,"Unknown lookup base"); - break; + case 8: + sprintf(tmp, "0%o", val); + break; + case 16: + sprintf(tmp, "0x%x", val); + break; + case 10: + sprintf(tmp, "%u", val); + break; + default: + errx(1, "Unknown lookup base"); } return (tmp); } @@ -1116,12 +1116,12 @@ * Copy a fixed amount of bytes from the process. */ static int -get_struct(pid_t pid, uintptr_t offset, void *buf, int len) +get_struct(pid_t pid, psaddr_t offset, void *buf, size_t len) { struct ptrace_io_desc iorequest; iorequest.piod_op = PIOD_READ_D; - iorequest.piod_offs = (void *)offset; + iorequest.piod_offs = (void *)(uintptr_t)offset; iorequest.piod_addr = buf; iorequest.piod_len = len; if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) @@ -1137,7 +1137,7 @@ * only get that much. */ static char * -get_string(pid_t pid, uintptr_t addr, int max) +get_string(pid_t pid, psaddr_t addr, int max) { struct ptrace_io_desc iorequest; char *buf, *nbuf; @@ -1148,7 +1148,7 @@ size = max + 1; else { /* Read up to the end of the current page. */ - size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE); + size = PAGE_SIZE - (addr % PAGE_SIZE); if (size > MAXSIZE) size = MAXSIZE; } @@ -1158,7 +1158,7 @@ return (NULL); for (;;) { iorequest.piod_op = PIOD_READ_D; - iorequest.piod_offs = (void *)(addr + offset); + iorequest.piod_offs = (void *)((uintptr_t)addr + offset); iorequest.piod_addr = buf + offset; iorequest.piod_len = size; if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) { @@ -1718,6 +1718,20 @@ fprintf(fp, "%s", name); } +/* + * Convert a 32-bit user-space pointer to psaddr_t. Currently, this + * sign-extends on MIPS and zero-extends on all other architectures. + */ +static psaddr_t +user_ptr32_to_psaddr(int32_t user_pointer) +{ +#if defined(__mips__) + return ((psaddr_t)(intptr_t)user_pointer); +#else + return ((psaddr_t)(uintptr_t)user_pointer); +#endif +} + /* * Converts a syscall argument into a string. Said string is * allocated via malloc(), so needs to be free()'d. sc is @@ -1769,7 +1783,7 @@ break; case ShmName: /* Handle special SHM_ANON value. */ - if ((char *)args[sc->offset] == SHM_ANON) { + if ((char *)(uintptr_t)args[sc->offset] == SHM_ANON) { fprintf(fp, "SHM_ANON"); break; } @@ -1829,7 +1843,7 @@ case ExecArgs: case ExecEnv: case StringArray: { - uintptr_t addr; + psaddr_t addr; union { int32_t strarray32[PAGE_SIZE / sizeof(int32_t)]; int64_t strarray64[PAGE_SIZE / sizeof(int64_t)]; @@ -1859,7 +1873,7 @@ * a partial page. */ addr = args[sc->offset]; - if (addr % pointer_size != 0) { + if (!__is_aligned(addr, pointer_size)) { print_pointer(fp, args[sc->offset]); break; } @@ -1875,20 +1889,19 @@ first = 1; i = 0; for (;;) { - uintptr_t straddr; + psaddr_t straddr; if (pointer_size == 4) { - if (u.strarray32[i] == 0) - break; - /* sign-extend 32-bit pointers */ - straddr = (intptr_t)u.strarray32[i]; + straddr = user_ptr32_to_psaddr(u.strarray32[i]); } else if (pointer_size == 8) { - if (u.strarray64[i] == 0) - break; - straddr = (intptr_t)u.strarray64[i]; + straddr = (psaddr_t)u.strarray64[i]; } else { errx(1, "Unsupported pointer size: %zu", pointer_size); } + + /* Stop once we read the first NULL pointer. */ + if (straddr == 0) + break; string = get_string(pid, straddr, 0); fprintf(fp, "%s \"%s\"", first ? "" : ",", string); free(string);