version 1.121, 2016/02/28 15:55:58 |
version 1.122, 2016/03/06 20:25:27 |
|
|
#undef SYSVSHM |
#undef SYSVSHM |
#undef ACCOUNTING |
#undef ACCOUNTING |
|
|
struct emulation { |
|
char *name; /* Emulation name */ |
|
char **sysnames; /* Array of system call names */ |
|
int nsysnames; /* Number of */ |
|
}; |
|
|
|
static struct emulation emulations[] = { |
|
{ "native", syscallnames, SYS_MAXSYSCALL }, |
|
{ NULL, NULL, 0 } |
|
}; |
|
|
|
static struct emulation *current; |
|
static struct emulation *def_emul; |
|
|
|
struct pid_emul { |
|
struct emulation *e; |
|
pid_t p; |
|
}; |
|
|
|
static struct pid_emul *pe_table; |
|
static size_t pe_size; |
|
|
|
|
|
static char *ptrace_ops[] = { |
static char *ptrace_ops[] = { |
"PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U", |
"PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U", |
"PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE", |
"PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE", |
|
|
"PT_GET_THREAD_FIRST", "PT_GET_THREAD_NEXT", |
"PT_GET_THREAD_FIRST", "PT_GET_THREAD_NEXT", |
}; |
}; |
|
|
static void mappidtoemul(pid_t, struct emulation *); |
|
static struct emulation * findemul(pid_t); |
|
static int fread_tail(void *, size_t, size_t); |
static int fread_tail(void *, size_t, size_t); |
static void dumpheader(struct ktr_header *); |
static void dumpheader(struct ktr_header *); |
static void ktremul(char *, size_t); |
|
static void ktrgenio(struct ktr_genio *, size_t); |
static void ktrgenio(struct ktr_genio *, size_t); |
static void ktrnamei(const char *, size_t); |
static void ktrnamei(const char *, size_t); |
static void ktrpsig(struct ktr_psig *); |
static void ktrpsig(struct ktr_psig *); |
|
|
static void ktruser(struct ktr_user *, size_t); |
static void ktruser(struct ktr_user *, size_t); |
static void ktrexec(const char*, size_t); |
static void ktrexec(const char*, size_t); |
static void ktrpledge(struct ktr_pledge *, size_t); |
static void ktrpledge(struct ktr_pledge *, size_t); |
static void setemul(const char *); |
|
static void usage(void); |
static void usage(void); |
static void ioctldecode(int); |
static void ioctldecode(int); |
static void ptracedecode(int); |
static void ptracedecode(int); |
|
|
const char *errstr; |
const char *errstr; |
void *m; |
void *m; |
|
|
def_emul = current = &emulations[0]; /* native */ |
|
|
|
if (screenwidth == 0) { |
if (screenwidth == 0) { |
struct winsize ws; |
struct winsize ws; |
|
|
|
|
screenwidth = 80; |
screenwidth = 80; |
} |
} |
|
|
while ((ch = getopt(argc, argv, "e:f:dHlm:nRp:Tt:xX")) != -1) |
while ((ch = getopt(argc, argv, "f:dHlm:np:RTt:xX")) != -1) |
switch (ch) { |
switch (ch) { |
case 'e': |
|
setemul(optarg); |
|
def_emul = current; |
|
break; |
|
case 'f': |
case 'f': |
tracefile = optarg; |
tracefile = optarg; |
break; |
break; |
|
|
errx(1, "%s: not a dump", tracefile); |
errx(1, "%s: not a dump", tracefile); |
while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { |
while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { |
silent = 0; |
silent = 0; |
if (pe_size == 0) |
|
mappidtoemul(ktr_header.ktr_pid, current); |
|
if (pid_opt != -1 && pid_opt != ktr_header.ktr_pid) |
if (pid_opt != -1 && pid_opt != ktr_header.ktr_pid) |
silent = 1; |
silent = 1; |
if (silent == 0 && trpoints & (1<<ktr_header.ktr_type)) |
if (silent == 0 && trpoints & (1<<ktr_header.ktr_type)) |
|
|
continue; |
continue; |
if ((trpoints & (1<<ktr_header.ktr_type)) == 0) |
if ((trpoints & (1<<ktr_header.ktr_type)) == 0) |
continue; |
continue; |
current = findemul(ktr_header.ktr_pid); |
|
switch (ktr_header.ktr_type) { |
switch (ktr_header.ktr_type) { |
case KTR_SYSCALL: |
case KTR_SYSCALL: |
ktrsyscall((struct ktr_syscall *)m, ktrlen); |
ktrsyscall((struct ktr_syscall *)m, ktrlen); |
|
|
case KTR_PSIG: |
case KTR_PSIG: |
ktrpsig((struct ktr_psig *)m); |
ktrpsig((struct ktr_psig *)m); |
break; |
break; |
case KTR_EMUL: |
|
ktremul(m, ktrlen); |
|
mappidtoemul(ktr_header.ktr_pid, current); |
|
break; |
|
case KTR_STRUCT: |
case KTR_STRUCT: |
ktrstruct(m, ktrlen); |
ktrstruct(m, ktrlen); |
break; |
break; |
|
|
exit(0); |
exit(0); |
} |
} |
|
|
static void |
|
mappidtoemul(pid_t pid, struct emulation *emul) |
|
{ |
|
size_t i; |
|
struct pid_emul *tmp; |
|
|
|
for (i = 0; i < pe_size; i++) { |
|
if (pe_table[i].p == pid) { |
|
pe_table[i].e = emul; |
|
return; |
|
} |
|
} |
|
tmp = reallocarray(pe_table, pe_size + 1, sizeof(*pe_table)); |
|
if (tmp == NULL) |
|
err(1, NULL); |
|
pe_table = tmp; |
|
pe_table[pe_size].p = pid; |
|
pe_table[pe_size].e = emul; |
|
pe_size++; |
|
} |
|
|
|
static struct emulation* |
|
findemul(pid_t pid) |
|
{ |
|
size_t i; |
|
|
|
for (i = 0; i < pe_size; i++) |
|
if (pe_table[i].p == pid) |
|
return pe_table[i].e; |
|
return def_emul; |
|
} |
|
|
|
static int |
static int |
fread_tail(void *buf, size_t size, size_t num) |
fread_tail(void *buf, size_t size, size_t num) |
{ |
{ |
|
|
case KTR_PSIG: |
case KTR_PSIG: |
type = "PSIG"; |
type = "PSIG"; |
break; |
break; |
case KTR_EMUL: |
|
type = "EMUL"; |
|
break; |
|
case KTR_STRUCT: |
case KTR_STRUCT: |
type = "STRU"; |
type = "STRU"; |
break; |
break; |
|
|
type = "PLDG"; |
type = "PLDG"; |
break; |
break; |
default: |
default: |
(void)snprintf(unknown, sizeof unknown, "UNKNOWN(%d)", |
(void)snprintf(unknown, sizeof unknown, "UNKNOWN(%u)", |
kth->ktr_type); |
kth->ktr_type); |
type = unknown; |
type = unknown; |
} |
} |
|
|
[SYS_lseek] = { Pfd, PAD, Poff_t, Whencename }, |
[SYS_lseek] = { Pfd, PAD, Poff_t, Whencename }, |
[SYS_truncate] = { Ppath, PAD, Poff_t }, |
[SYS_truncate] = { Ppath, PAD, Poff_t }, |
[SYS_ftruncate] = { Pfd, PAD, Poff_t }, |
[SYS_ftruncate] = { Pfd, PAD, Poff_t }, |
/* [SYS_sysctl] = { }, Magic */ |
[SYS_sysctl] = { Pptr, Pcount, Pptr, Pptr, Pptr, Psize }, |
[SYS_mlock] = { Pptr, Pbigsize }, |
[SYS_mlock] = { Pptr, Pbigsize }, |
[SYS_munlock] = { Pptr, Pbigsize }, |
[SYS_munlock] = { Pptr, Pbigsize }, |
[SYS_getpgid] = { Ppid_t }, |
[SYS_getpgid] = { Ppid_t }, |
|
|
narg = ktr->ktr_argsize / sizeof(register_t); |
narg = ktr->ktr_argsize / sizeof(register_t); |
sep = '\0'; |
sep = '\0'; |
|
|
if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0) |
if (ktr->ktr_code >= SYS_MAXSYSCALL || ktr->ktr_code < 0) |
(void)printf("[%d]", ktr->ktr_code); |
(void)printf("[%d]", ktr->ktr_code); |
else |
else |
(void)printf("%s", current->sysnames[ktr->ktr_code]); |
(void)printf("%s", syscallnames[ktr->ktr_code]); |
ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall)); |
ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall)); |
(void)putchar('('); |
(void)putchar('('); |
|
|
if (current != &emulations[0]) |
if (ktr->ktr_code == SYS_sysctl && fancy) { |
goto nonnative; |
|
|
|
if (ktr->ktr_code == SYS_sysctl) { |
|
const char *s; |
const char *s; |
int n, i, *top; |
int n, i, *top; |
|
|
if (!fancy) |
|
goto nonnative; |
|
n = ap[1]; |
n = ap[1]; |
if (n > CTL_MAXNAME) |
if (n > CTL_MAXNAME) |
n = CTL_MAXNAME; |
n = CTL_MAXNAME; |
|
|
} |
} |
} |
} |
|
|
nonnative: |
|
while (narg > 0) { |
while (narg > 0) { |
if (sep) |
if (sep) |
putchar(sep); |
putchar(sep); |
|
|
errx(1, "sysret bogus length %zu", ktrlen); |
errx(1, "sysret bogus length %zu", ktrlen); |
} |
} |
|
|
if (code >= current->nsysnames || code < 0) |
if (code >= SYS_MAXSYSCALL || code < 0) |
(void)printf("[%d] ", code); |
(void)printf("[%d] ", code); |
else { |
else |
(void)printf("%s ", current->sysnames[code]); |
(void)printf("%s ", syscallnames[code]); |
if (error == 0 && ret > 0 && |
|
(strcmp(current->sysnames[code], "fork") == 0 || |
|
strcmp(current->sysnames[code], "vfork") == 0 || |
|
strcmp(current->sysnames[code], "__tfork") == 0 || |
|
strcmp(current->sysnames[code], "clone") == 0)) |
|
mappidtoemul(ret, current); |
|
} |
|
|
|
if (error == 0) { |
if (error == 0) { |
if (fancy) { |
if (fancy) { |
switch (current == &emulations[0] ? code : -1) { |
switch (code) { |
case SYS_lseek: |
case SYS_lseek: |
(void)printf("%lld", retll); |
(void)printf("%lld", retll); |
if (retll < 0 || retll > 9) |
if (retll < 0 || retll > 9) |
|
|
case SYS_getegid: |
case SYS_getegid: |
gidname(ret); |
gidname(ret); |
break; |
break; |
case -1: /* non-default emulation */ |
|
default: |
default: |
(void)printf("%ld", (long)ret); |
(void)printf("%ld", (long)ret); |
if (ret < 0 || ret > 9) |
if (ret < 0 || ret > 9) |
|
|
(void)printf("\"%.*s\"\n", (int)len, cp); |
(void)printf("\"%.*s\"\n", (int)len, cp); |
} |
} |
|
|
static void |
|
ktremul(char *cp, size_t len) |
|
{ |
|
char name[1024]; |
|
|
|
if (len >= sizeof(name)) |
|
errx(1, "Emulation name too long"); |
|
|
|
strncpy(name, cp, len); |
|
name[len] = '\0'; |
|
(void)printf("\"%s\"\n", name); |
|
|
|
setemul(name); |
|
} |
|
|
|
void |
void |
showbufc(int col, unsigned char *dp, size_t datalen) |
showbufc(int col, unsigned char *dp, size_t datalen) |
{ |
{ |
|
|
if (len < sizeof(struct ktr_pledge)) |
if (len < sizeof(struct ktr_pledge)) |
errx(1, "invalid ktr pledge length %zu", len); |
errx(1, "invalid ktr pledge length %zu", len); |
|
|
if (pledge->syscall >= current->nsysnames || pledge->syscall < 0) |
if (pledge->syscall >= SYS_MAXSYSCALL || pledge->syscall < 0) |
(void)printf("[%d]", pledge->syscall); |
(void)printf("[%d]", pledge->syscall); |
else |
else |
(void)printf("%s", current->sysnames[pledge->syscall]); |
(void)printf("%s", syscallnames[pledge->syscall]); |
printf(", "); |
printf(", "); |
for (i = 0; pledge->code && pledgenames[i].bits != 0; i++) { |
for (i = 0; pledge->code && pledgenames[i].bits != 0; i++) { |
if (pledgenames[i].bits & pledge->code) { |
if (pledgenames[i].bits & pledge->code) { |
|
|
|
|
extern char *__progname; |
extern char *__progname; |
fprintf(stderr, "usage: %s " |
fprintf(stderr, "usage: %s " |
"[-dHlnRTXx] [-e emulation] [-f file] [-m maxdata] [-p pid]\n" |
"[-dHlnRTXx] [-f file] [-m maxdata] [-p pid]\n" |
"%*s[-t [ceinstuxX+]]\n", |
"%*s[-t [cinstuxX+]]\n", |
__progname, (int)(sizeof("usage: ") + strlen(__progname)), ""); |
__progname, (int)(sizeof("usage: ") + strlen(__progname)), ""); |
exit(1); |
exit(1); |
} |
} |
|
|
static void |
|
setemul(const char *name) |
|
{ |
|
int i; |
|
|
|
for (i = 0; emulations[i].name != NULL; i++) |
|
if (strcmp(emulations[i].name, name) == 0) { |
|
current = &emulations[i]; |
|
return; |
|
} |
|
warnx("Emulation `%s' unknown", name); |
|
} |
|
|
|
/* |
/* |
* FORMATTERS |
* FORMATTERS |