Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

truss: decode compat32/compat64 arguments #692

Merged
merged 9 commits into from
Jun 25, 2021
25 changes: 12 additions & 13 deletions sys/sys/cdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1094,26 +1094,25 @@
#define __static_assert_power_of_two(val)
#endif

/* Allow use of __builtin_is_aligned/align_up/align_down unconditionally */
/* Alignment builtins for better type checking and improved code generation. */
/* Provide fallback versions for other compilers (GCC/Clang < 10): */
#if !__has_builtin(__builtin_is_aligned)
#define __builtin_is_aligned(addr, align) \
({ __static_assert_power_of_two(align); \
(((vaddr_t)addr & ((vaddr_t)(align) - 1)) == 0); })
#define __builtin_is_aligned(x, align) \
(((__uintptr_t)x & ((align) - 1)) == 0)
#endif
#if !__has_builtin(__builtin_align_up)
#define __builtin_align_up(addr, align) \
({ __static_assert_power_of_two(align); \
vaddr_t unaligned_bits = (vaddr_t)addr & ((align) - 1); \
unaligned_bits == 0 ? addr : \
(__typeof__(addr))((uintptr_t)addr + ((align) - unaligned_bits)); })
#define __builtin_align_up(x, align) \
((__typeof__(x))(((__uintptr_t)(x)+((align)-1))&(~((align)-1))))
#endif
#if !__has_builtin(__builtin_align_down)
#define __builtin_align_down(addr, align) ({ \
__static_assert_power_of_two(align); \
vaddr_t unaligned_bits = (vaddr_t)addr & ((align) - 1); \
(__typeof__(addr))((uintptr_t)addr - unaligned_bits); })
#define __builtin_align_down(x, align) \
((__typeof__(x))((x)&(~((align)-1))))
#endif

#define __align_up(x, y) __builtin_align_up(x, y)
#define __align_down(x, y) __builtin_align_down(x, y)
#define __is_aligned(x, y) __builtin_is_aligned(x, y)

#endif /* !_SYS_CDEFS_H_ */
// CHERI CHANGES START
// {
Expand Down
4 changes: 2 additions & 2 deletions sys/sys/param.h
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,9 @@
#define nitems(x) (sizeof((x)) / sizeof((x)[0]))
#define is_aligned(x, y) __builtin_is_aligned(x, y)
#define rounddown(x, y) (((x)/(y))*(y))
#define rounddown2(x, y) __builtin_align_down((x), (y))
#define rounddown2(x, y) __align_down(x, y) /* if y is power of two */
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
#define roundup2(x, y) __builtin_align_up((x), (y))
#define roundup2(x, y) __align_up(x, y) /* if y is powers of two */
#define powerof2(x) ((((x)-1)&(x))==0)

/* Macros for min/max. */
Expand Down
6 changes: 3 additions & 3 deletions usr.bin/truss/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$");
#include "extern.h"
#include "syscall.h"

static void
static __dead2 void
usage(void)
{
fprintf(stderr, "%s\n%s\n",
Expand Down Expand Up @@ -87,7 +87,6 @@ main(int ac, char **av)
trussinfo->strsize = 32;
trussinfo->curthread = NULL;
LIST_INIT(&trussinfo->proclist);
init_syscalls();
while ((c = getopt(ac, av, "p:o:facedDs:SH")) != -1) {
switch (c) {
case 'p': /* specified pid */
Expand Down Expand Up @@ -119,7 +118,8 @@ main(int ac, char **av)
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;
Expand Down
124 changes: 66 additions & 58 deletions usr.bin/truss/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,97 +74,104 @@ static void new_proc(struct trussinfo *, pid_t, lwpid_t);


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 * __capability),
.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

#ifdef __CHERI_PURE_CAPABILITY__
#if __has_feature(capabilities)
arichardson marked this conversation as resolved.
Show resolved Hide resolved
_Static_assert(sizeof(ptraddr_t) == 8, "Missing 64-bit capability support");
static struct procabi freebsd64 = {
"FreeBSD64",
SYSDECODE_ABI_FREEBSD64,
STAILQ_HEAD_INITIALIZER(freebsd64.extra_syscalls),
{ NULL }
.type = "FreeBSD64",
.abi = SYSDECODE_ABI_FREEBSD64,
.pointer_size = sizeof(uint64_t),
.compat_prefix = "freebsd64_",
.extra_syscalls = STAILQ_HEAD_INITIALIZER(freebsd64.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(ptraddr_t),
.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 __CHERI_PURE_CAPABILITY__
{ "FreeBSD ELF64C", &freebsd },
#elif defined(__LP64__)
/* This permits hybrid truss to trace CheriABI. */
#if __has_feature(capabilities)
{ "FreeBSD ELF64C", &freebsd },
{ "FreeBSD ELF64", &freebsd64 },
arichardson marked this conversation as resolved.
Show resolved Hide resolved
{ "FreeBSD ELF32", &freebsd32 },
#elif __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 },
#endif
#ifdef __CHERI_PURE_CAPABILITY__
{ "FreeBSD ELF64", &freebsd64 },
#endif
#ifdef __LP64__
{ "FreeBSD ELF32", &freebsd32 },
#endif
#if defined(__amd64__)
{ "FreeBSD a.out", &freebsd32 },
#endif
#if defined(__i386__)
{ "FreeBSD a.out", &freebsd },
#endif
#ifdef __LP64__
#if __SIZEOF_POINTER__ >= 8
{ "Linux ELF64", &linux },
{ "Linux ELF32", &linux32 },
#else
{ "Linux ELF", &linux },
{ "Linux ELF32", &linux },
#endif
/*
* XXX: Temporary hack for COMPAT_CHERIABI.
*/
{ "CheriABI ELF64", &freebsd },
};

/*
Expand Down Expand Up @@ -485,8 +492,8 @@ enter_syscall(struct trussinfo *info, struct threadinfo *t,
fprintf(info->outfile, "-- UNKNOWN %s SYSCALL %d --\n",
t->proc->abi->type, t->cs.number);

t->cs.nargs = sc->nargs;
assert(sc->nargs <= nitems(t->cs.s_args));
t->cs.nargs = sc->decode.nargs;
assert(sc->decode.nargs <= nitems(t->cs.s_args));

t->cs.sc = sc;

Expand All @@ -502,11 +509,12 @@ enter_syscall(struct trussinfo *info, struct threadinfo *t,
#endif
for (i = 0; i < t->cs.nargs; i++) {
#if DEBUG
fprintf(stderr, "0x%lx%s", t->cs.args[sc->args[i].offset],
fprintf(stderr, "0x%lx%s",
t->cs.args[sc->decode.args[i].offset],
i < (t->cs.nargs - 1) ? "," : "");
#endif
if (!(sc->args[i].type & OUT)) {
t->cs.s_args[i] = print_arg(&sc->args[i],
if (!(sc->decode.args[i].type & OUT)) {
t->cs.s_args[i] = print_arg(&sc->decode.args[i],
t->cs.args, NULL, info);
}
}
Expand Down Expand Up @@ -564,19 +572,19 @@ exit_syscall(struct trussinfo *info, struct ptrace_lwpinfo *pl)
* Here, we only look for arguments that have OUT masked in --
* otherwise, they were handled in enter_syscall().
*/
for (i = 0; i < sc->nargs; i++) {
for (i = 0; i < sc->decode.nargs; i++) {
char *temp;

if (sc->args[i].type & OUT) {
if (sc->decode.args[i].type & OUT) {
/*
* If an error occurred, then don't bother
* getting the data; it may not be valid.
*/
if (psr.sr_error != 0) {
asprintf(&temp, "0x%lx",
(unsigned long)t->cs.args[sc->args[i].offset]);
asprintf(&temp, "0x%jx",
(intmax_t)t->cs.args[sc->decode.args[i].offset]);
} else {
temp = print_arg(&sc->args[i],
temp = print_arg(&sc->decode.args[i],
t->cs.args, psr.sr_retval, info);
}
t->cs.s_args[i] = temp;
Expand Down
25 changes: 17 additions & 8 deletions usr.bin/truss/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,26 +210,36 @@ enum Argtype {
_Static_assert(ARG_MASK > MAX_ARG_TYPE,
"ARG_MASK overlaps with Argtype values");

struct syscall_args {
struct syscall_arg {
enum Argtype type;
int offset;
};

struct syscall_decode {
const char *name; /* Name for calling convention lookup. */
/*
* Syscall return type:
* 0: no return value (e.g. exit)
* 1: normal return value (a single int/long/pointer)
* 2: off_t return value (two values for 32-bit ABIs)
*/
u_int ret_type;
u_int nargs; /* number of meaningful arguments */
struct syscall_arg args[10]; /* Hopefully no syscalls with > 10 args */
};

struct syscall {
STAILQ_ENTRY(syscall) entries;
const char *name;
u_int ret_type; /* 0, 1, or 2 return values */
u_int nargs; /* actual number of meaningful arguments */
/* Hopefully, no syscalls with > 10 args */
struct syscall_args args[10];
const char *name; /* Name to be displayed, might be malloc()'d */
struct syscall_decode decode;
struct timespec time; /* Time spent for this call */
int ncalls; /* Number of calls */
int nerror; /* Number of calls that returned with error */
bool unknown; /* Unknown system call */
};

struct syscall *get_syscall(struct threadinfo *, u_int, u_int);
char *print_arg(struct syscall_args *, syscallarg_t *, syscallarg_t *,
char *print_arg(struct syscall_arg *, syscallarg_t *, syscallarg_t *,
struct trussinfo *);

/*
Expand Down Expand Up @@ -272,7 +282,6 @@ struct linux_socketcall_args {
char args_l_[PADL_(l_ulong)]; l_ulong args; char args_r_[PADR_(l_ulong)];
};

void init_syscalls(void);
void print_syscall(struct trussinfo *);
void print_syscall_ret(struct trussinfo *, int, syscallarg_t *);
void print_summary(struct trussinfo *trussinfo);
Loading