Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/kdump/kdump.c
Show First 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | |||||
#include <casper/cap_grp.h> | #include <casper/cap_grp.h> | ||||
#include <casper/cap_pwd.h> | #include <casper/cap_pwd.h> | ||||
#endif | #endif | ||||
int fetchprocinfo(struct ktr_header *, u_int *); | int fetchprocinfo(struct ktr_header *, u_int *); | ||||
u_int findabi(struct ktr_header *); | u_int findabi(struct ktr_header *); | ||||
int fread_tail(void *, int, int); | int fread_tail(void *, int, int); | ||||
void dumpheader(struct ktr_header *, u_int); | void dumpheader(struct ktr_header *, u_int); | ||||
void dumptimeval(struct ktr_header_v0 *kth); | |||||
void dumptimespec(struct ktr_header *kth); | |||||
void ktrsyscall(struct ktr_syscall *, u_int); | void ktrsyscall(struct ktr_syscall *, u_int); | ||||
void ktrsysret(struct ktr_sysret *, u_int); | void ktrsysret(struct ktr_sysret *, u_int); | ||||
void ktrnamei(char *, int); | void ktrnamei(char *, int); | ||||
void hexdump(char *, int, int); | void hexdump(char *, int, int); | ||||
void visdump(char *, int, int); | void visdump(char *, int, int); | ||||
void ktrgenio(struct ktr_genio *, int); | void ktrgenio(struct ktr_genio *, int); | ||||
void ktrpsig(struct ktr_psig *); | void ktrpsig(struct ktr_psig *); | ||||
void ktrcsw(struct ktr_csw *); | void ktrcsw(struct ktr_csw *); | ||||
Show All 15 Lines | |||||
void usage(void); | void usage(void); | ||||
#define TIMESTAMP_NONE 0x0 | #define TIMESTAMP_NONE 0x0 | ||||
#define TIMESTAMP_ABSOLUTE 0x1 | #define TIMESTAMP_ABSOLUTE 0x1 | ||||
#define TIMESTAMP_ELAPSED 0x2 | #define TIMESTAMP_ELAPSED 0x2 | ||||
#define TIMESTAMP_RELATIVE 0x4 | #define TIMESTAMP_RELATIVE 0x4 | ||||
bool decimal, fancy = true, resolv; | bool decimal, fancy = true, resolv; | ||||
static bool abiflag, suppressdata, syscallno, tail, threads; | static bool abiflag, suppressdata, syscallno, tail, threads, cpuflag; | ||||
static int timestamp, maxdata; | static int timestamp, maxdata; | ||||
static const char *tracefile = DEF_TRACEFILE; | static const char *tracefile = DEF_TRACEFILE; | ||||
static struct ktr_header ktr_header; | static struct ktr_header ktr_header; | ||||
static short version; | |||||
#define TIME_FORMAT "%b %e %T %Y" | #define TIME_FORMAT "%b %e %T %Y" | ||||
#define eqs(s1, s2) (strcmp((s1), (s2)) == 0) | #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) | ||||
struct proc_info | struct proc_info | ||||
{ | { | ||||
TAILQ_ENTRY(proc_info) info; | TAILQ_ENTRY(proc_info) info; | ||||
u_int sv_flags; | u_int sv_flags; | ||||
▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | main(int argc, char *argv[]) | ||||
int drop_logged; | int drop_logged; | ||||
pid_t pid = 0; | pid_t pid = 0; | ||||
u_int sv_flags; | u_int sv_flags; | ||||
setlocale(LC_CTYPE, ""); | setlocale(LC_CTYPE, ""); | ||||
timestamp = TIMESTAMP_NONE; | timestamp = TIMESTAMP_NONE; | ||||
while ((ch = getopt(argc,argv,"f:dElm:np:AHRrSsTt:")) != -1) | while ((ch = getopt(argc,argv,"f:cdElm:np:AHRrSsTt:")) != -1) | ||||
switch (ch) { | switch (ch) { | ||||
case 'A': | case 'A': | ||||
abiflag = true; | abiflag = true; | ||||
break; | break; | ||||
case 'f': | case 'f': | ||||
tracefile = optarg; | tracefile = optarg; | ||||
break; | break; | ||||
case 'c': | |||||
cpuflag = true; | |||||
break; | |||||
case 'd': | case 'd': | ||||
decimal = true; | decimal = true; | ||||
break; | break; | ||||
case 'l': | case 'l': | ||||
tail = true; | tail = true; | ||||
break; | break; | ||||
case 'm': | case 'm': | ||||
maxdata = atoi(optarg); | maxdata = atoi(optarg); | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | #else | ||||
} | } | ||||
#endif | #endif | ||||
if (caph_limit_stdio() == -1) | if (caph_limit_stdio() == -1) | ||||
err(1, "unable to limit stdio"); | err(1, "unable to limit stdio"); | ||||
TAILQ_INIT(&trace_procs); | TAILQ_INIT(&trace_procs); | ||||
drop_logged = 0; | drop_logged = 0; | ||||
while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { | while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { | ||||
if (ktr_header.ktr_type & KTR_NEW) { | |||||
ktr_header.ktr_type &= ~KTR_NEW; | |||||
version = ktr_header.ktr_version; | |||||
} else | |||||
version = 0; | |||||
rpokala: Wouldn't this be better as `version = KTR_VERSION0`? | |||||
if (ktr_header.ktr_type & KTR_DROP) { | if (ktr_header.ktr_type & KTR_DROP) { | ||||
ktr_header.ktr_type &= ~KTR_DROP; | ktr_header.ktr_type &= ~KTR_DROP; | ||||
if (!drop_logged && threads) { | if (!drop_logged && threads) { | ||||
printf( | printf( | ||||
"%6jd %6jd %-8.*s Events dropped.\n", | "%6jd %6jd %-8.*s Events dropped.\n", | ||||
(intmax_t)ktr_header.ktr_pid, | (intmax_t)ktr_header.ktr_pid, | ||||
ktr_header.ktr_tid > 0 ? | ktr_header.ktr_tid > 0 ? | ||||
(intmax_t)ktr_header.ktr_tid : 0, | (intmax_t)ktr_header.ktr_tid : 0, | ||||
Show All 9 Lines | while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { | ||||
if ((ktrlen = ktr_header.ktr_len) < 0) | if ((ktrlen = ktr_header.ktr_len) < 0) | ||||
errx(1, "bogus length 0x%x", ktrlen); | errx(1, "bogus length 0x%x", ktrlen); | ||||
if (ktrlen > size) { | if (ktrlen > size) { | ||||
m = realloc(m, ktrlen+1); | m = realloc(m, ktrlen+1); | ||||
if (m == NULL) | if (m == NULL) | ||||
errx(1, "%s", strerror(ENOMEM)); | errx(1, "%s", strerror(ENOMEM)); | ||||
size = ktrlen; | size = ktrlen; | ||||
} | } | ||||
if (version == KTR_VERSION0 && | |||||
fseek(stdin, KTR_OFFSET_V0, SEEK_CUR) < 0) | |||||
errx(1, "%s", strerror(errno)); | |||||
if (ktrlen && fread_tail(m, ktrlen, 1) == 0) | if (ktrlen && fread_tail(m, ktrlen, 1) == 0) | ||||
errx(1, "data too short"); | errx(1, "data too short"); | ||||
if (fetchprocinfo(&ktr_header, (u_int *)m) != 0) | if (fetchprocinfo(&ktr_header, (u_int *)m) != 0) | ||||
continue; | continue; | ||||
if (pid && ktr_header.ktr_pid != pid && | if (pid && ktr_header.ktr_pid != pid && | ||||
ktr_header.ktr_tid != pid) | ktr_header.ktr_tid != pid) | ||||
continue; | continue; | ||||
if ((trpoints & (1<<ktr_header.ktr_type)) == 0) | if ((trpoints & (1<<ktr_header.ktr_type)) == 0) | ||||
▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | TAILQ_FOREACH(pi, &trace_procs, info) { | ||||
if (pi->pid == kth->ktr_pid) { | if (pi->pid == kth->ktr_pid) { | ||||
return (pi->sv_flags); | return (pi->sv_flags); | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
void | void | ||||
dumpheader(struct ktr_header *kth, u_int sv_flags) | dumptimeval(struct ktr_header_v0 *kth) | ||||
{ | { | ||||
static char unknown[64]; | |||||
static struct timeval prevtime, prevtime_e; | static struct timeval prevtime, prevtime_e; | ||||
struct timeval temp; | struct timeval temp; | ||||
const char *sign; | |||||
if (timestamp & TIMESTAMP_ABSOLUTE) { | |||||
printf("%jd.%06ld ", (intmax_t)kth->ktr_time.tv_sec, | |||||
kth->ktr_time.tv_usec); | |||||
} | |||||
if (timestamp & TIMESTAMP_ELAPSED) { | |||||
if (prevtime_e.tv_sec == 0) | |||||
prevtime_e = kth->ktr_time; | |||||
timersub(&kth->ktr_time, &prevtime_e, &temp); | |||||
printf("%jd.%06ld ", (intmax_t)temp.tv_sec, | |||||
temp.tv_usec); | |||||
} | |||||
if (timestamp & TIMESTAMP_RELATIVE) { | |||||
if (prevtime.tv_sec == 0) | |||||
prevtime = kth->ktr_time; | |||||
if (timercmp(&kth->ktr_time, &prevtime, <)) { | |||||
timersub(&prevtime, &kth->ktr_time, &temp); | |||||
sign = "-"; | |||||
} else { | |||||
timersub(&kth->ktr_time, &prevtime, &temp); | |||||
sign = ""; | |||||
} | |||||
prevtime = kth->ktr_time; | |||||
printf("%s%jd.%06ld ", sign, (intmax_t)temp.tv_sec, | |||||
temp.tv_usec); | |||||
} | |||||
} | |||||
void | |||||
dumptimespec(struct ktr_header *kth) | |||||
{ | |||||
static struct timespec prevtime, prevtime_e; | |||||
struct timespec temp; | |||||
const char *sign; | |||||
if (timestamp & TIMESTAMP_ABSOLUTE) { | |||||
printf("%jd.%09ld ", (intmax_t)kth->ktr_time.tv_sec, | |||||
kth->ktr_time.tv_nsec); | |||||
} | |||||
if (timestamp & TIMESTAMP_ELAPSED) { | |||||
if (prevtime_e.tv_sec == 0) | |||||
prevtime_e = kth->ktr_time; | |||||
timespecsub(&kth->ktr_time, &prevtime_e, &temp); | |||||
printf("%jd.%09ld ", (intmax_t)temp.tv_sec, | |||||
temp.tv_nsec); | |||||
} | |||||
if (timestamp & TIMESTAMP_RELATIVE) { | |||||
if (prevtime.tv_sec == 0) | |||||
prevtime = kth->ktr_time; | |||||
if (timespeccmp(&kth->ktr_time, &prevtime, <)) { | |||||
timespecsub(&prevtime, &kth->ktr_time, &temp); | |||||
sign = "-"; | |||||
} else { | |||||
timespecsub(&kth->ktr_time, &prevtime, &temp); | |||||
sign = ""; | |||||
} | |||||
prevtime = kth->ktr_time; | |||||
printf("%s%jd.%09ld ", sign, (intmax_t)temp.tv_sec, | |||||
temp.tv_nsec); | |||||
} | |||||
} | |||||
void | |||||
dumpheader(struct ktr_header *kth, u_int sv_flags) | |||||
{ | |||||
static char unknown[64]; | |||||
const char *abi; | const char *abi; | ||||
const char *arch; | const char *arch; | ||||
const char *type; | const char *type; | ||||
const char *sign; | |||||
switch (kth->ktr_type) { | switch (kth->ktr_type) { | ||||
case KTR_SYSCALL: | case KTR_SYSCALL: | ||||
type = "CALL"; | type = "CALL"; | ||||
break; | break; | ||||
case KTR_SYSRET: | case KTR_SYSRET: | ||||
type = "RET "; | type = "RET "; | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | dumpheader(struct ktr_header *kth, u_int sv_flags) | ||||
if (threads) | if (threads) | ||||
printf("%6jd %6jd %-8.*s ", (intmax_t)kth->ktr_pid, | printf("%6jd %6jd %-8.*s ", (intmax_t)kth->ktr_pid, | ||||
kth->ktr_tid > 0 ? (intmax_t)kth->ktr_tid : 0, | kth->ktr_tid > 0 ? (intmax_t)kth->ktr_tid : 0, | ||||
MAXCOMLEN, kth->ktr_comm); | MAXCOMLEN, kth->ktr_comm); | ||||
else | else | ||||
printf("%6jd %-8.*s ", (intmax_t)kth->ktr_pid, MAXCOMLEN, | printf("%6jd %-8.*s ", (intmax_t)kth->ktr_pid, MAXCOMLEN, | ||||
kth->ktr_comm); | kth->ktr_comm); | ||||
if (timestamp) { | if (timestamp) { | ||||
if (timestamp & TIMESTAMP_ABSOLUTE) { | if (version == KTR_VERSION0) | ||||
printf("%jd.%06ld ", (intmax_t)kth->ktr_time.tv_sec, | dumptimeval((struct ktr_header_v0 *)kth); | ||||
kth->ktr_time.tv_usec); | else | ||||
dumptimespec(kth); | |||||
} | } | ||||
if (timestamp & TIMESTAMP_ELAPSED) { | if (cpuflag && version > KTR_VERSION0) | ||||
if (prevtime_e.tv_sec == 0) | printf("%3d ", kth->ktr_cpu); | ||||
prevtime_e = kth->ktr_time; | |||||
timersub(&kth->ktr_time, &prevtime_e, &temp); | |||||
printf("%jd.%06ld ", (intmax_t)temp.tv_sec, | |||||
temp.tv_usec); | |||||
} | |||||
if (timestamp & TIMESTAMP_RELATIVE) { | |||||
if (prevtime.tv_sec == 0) | |||||
prevtime = kth->ktr_time; | |||||
if (timercmp(&kth->ktr_time, &prevtime, <)) { | |||||
timersub(&prevtime, &kth->ktr_time, &temp); | |||||
sign = "-"; | |||||
} else { | |||||
timersub(&kth->ktr_time, &prevtime, &temp); | |||||
sign = ""; | |||||
} | |||||
prevtime = kth->ktr_time; | |||||
printf("%s%jd.%06ld ", sign, (intmax_t)temp.tv_sec, | |||||
temp.tv_usec); | |||||
} | |||||
} | |||||
printf("%s ", type); | printf("%s ", type); | ||||
if (abiflag != 0) { | if (abiflag != 0) { | ||||
switch (sv_flags & SV_ABI_MASK) { | switch (sv_flags & SV_ABI_MASK) { | ||||
case SV_ABI_LINUX: | case SV_ABI_LINUX: | ||||
abi = "L"; | abi = "L"; | ||||
break; | break; | ||||
case SV_ABI_FREEBSD: | case SV_ABI_FREEBSD: | ||||
abi = "F"; | abi = "F"; | ||||
▲ Show 20 Lines • Show All 1,584 Lines • Show Last 20 Lines |
Wouldn't this be better as version = KTR_VERSION0?