diff options
-rw-r--r-- | common.h | 2 | ||||
-rw-r--r-- | linux/os.h | 4 | ||||
-rw-r--r-- | memory.c | 32 | ||||
-rw-r--r-- | print.c | 4 | ||||
-rw-r--r-- | sctrace.1 | 13 | ||||
-rw-r--r-- | sctrace.c | 22 |
6 files changed, 66 insertions, 11 deletions
@@ -115,10 +115,12 @@ const char *get_errno_name(int err); const char *get_signum_name(int sig); /* memory.c */ +extern size_t abbreviate_memory; char *get_string(pid_t pid, unsigned long int addr, size_t *lenp, const char **errorp); int get_struct(pid_t pid, unsigned long int addr, void *out, size_t size, const char **errorp); char *get_memory(pid_t pid, unsigned long int addr, size_t n, const char **errorp); char *escape_memory(const char *str, size_t m); +char *escape_string(const char *str, size_t m); char *get_escaped_string(pid_t pid, unsigned long int addr, size_t *lenp, const char **errorp); char *get_escaped_memory(pid_t pid, unsigned long int addr, size_t n, const char **errorp); @@ -37,6 +37,10 @@ # define REGARGS(a, b) a, b #endif +#if defined(__arm__) || defined(__thumb__) +# define USE_PTRACE_SET_SYSCALL +#endif + #ifndef KEY_SPEC_THREAD_KEYRING # define KEY_SPEC_THREAD_KEYRING -1 @@ -2,6 +2,9 @@ #include "common.h" +size_t abbreviate_memory = SIZE_MAX; + + char * get_string(pid_t pid, unsigned long int addr, size_t *lenp, const char **errorp) { @@ -133,8 +136,8 @@ istrigraphfinal(char c) } -char * -escape_memory(const char *str, size_t m) +static char * +escape(const char *str, size_t m, size_t max) { char *ret = NULL; const char *s, *end; @@ -149,8 +152,10 @@ escape_memory(const char *str, size_t m) eprintf("strdup:"); return ret; } + if (max > m) + max = m; add_char(&ret, &size, &len, '"'); - for (s = str, end = &str[m]; s != end; s++) { + for (s = str, end = &str[max]; s != end; s++) { if (n) { add_char(&ret, &size, &len, *s); n -= 1; @@ -209,12 +214,31 @@ escape_memory(const char *str, size_t m) need_new_string_hex = 0; } add_char(&ret, &size, &len, '"'); + if (m > max) { + add_char(&ret, &size, &len, '.'); + add_char(&ret, &size, &len, '.'); + add_char(&ret, &size, &len, '.'); + } add_char(&ret, &size, &len, '\0'); return ret; } char * +escape_memory(const char *str, size_t m) +{ + return escape(str, m, abbreviate_memory); +} + + +char * +escape_string(const char *str, size_t m) +{ + return escape(str, m, SIZE_MAX); +} + + +char * get_escaped_string(pid_t pid, unsigned long int addr, size_t *lenp, const char **errorp) { char *r, *ret; @@ -223,7 +247,7 @@ get_escaped_string(pid_t pid, unsigned long int addr, size_t *lenp, const char * return NULL; } r = get_string(pid, addr, lenp, errorp); - ret = escape_memory(r, *lenp); + ret = escape_string(r, *lenp); free(r); return ret; } @@ -764,9 +764,9 @@ print_sockaddr(struct process *proc, const struct sockaddr *addr, socklen_t len) sun = (const struct sockaddr_un *)addr; slen = (size_t)len - offsetof(struct sockaddr_un, sun_path); if (!slen || !sun->sun_path[0] || !memchr(sun->sun_path, 0, slen)) - str = escape_memory(sun->sun_path, slen); + str = escape_string(sun->sun_path, slen); else - str = escape_memory(sun->sun_path, strlen(sun->sun_path)); + str = escape_string(sun->sun_path, strlen(sun->sun_path)); tprintf(proc, "{.sun_family = AF_UNIX, .sun_path = %s}", str); free(str); return; @@ -3,6 +3,8 @@ sctrace - Trace system calls .SH SYNOPSIS .B sctrace +.RB [ -a +.IR byte-count ] .RB [ -o .IR trace-output-file ] .RB [ -ft ] @@ -48,12 +50,21 @@ argument rather than the .I command argument. .TP +.BR -a " "\fIbyte-count\fP +Limit the displayed number of bytes in any region +of uninterpreted memory (this excludes strings +and structures but includes file I/O) to +.I byte-count +bytes. The string +.B inf +is interpreted to remove previously applied limit. +.TP .B -f Recursively trace all new children and threads. This option implies .BR -t . .TP -.BR -o " "\fItrace-output-file\fI +.BR -o " "\fItrace-output-file\fP Write trace outputs to the file specified in the .I trace-output-file argument. @@ -9,7 +9,8 @@ static unsigned long int trace_options = PTRACE_O_EXITKILL | PTRACE_O_TRACESYSGO _Noreturn static void usage(void) { - fprintf(stderr, "usage: %s [-o trace-output-file] [-ft] (command | -0 command argv0) [argument] ...\n", argv0); + fprintf(stderr, "usage: %s [-a byte-count] [-o trace-output-file] [-ft]" + " (command | -0 command argv0) [argument] ...\n", argv0); exit(1); } @@ -123,7 +124,7 @@ handle_event(struct process *proc, int status) proc->state = trace_event == PTRACE_EVENT_CLONE ? CloneParent : ForkParent; handle_syscall(proc); } - tprintf(proc2, "\nTracing new process\n"); + tprintf(proc2, "\nTracing new process with parent %ju\n", (uintmax_t)proc->pid); proc2->state = trace_event == PTRACE_EVENT_FORK ? ForkChild : trace_event == PTRACE_EVENT_VFORK ? VforkChild : CloneChild; handle_syscall(proc2); @@ -180,17 +181,29 @@ main(int argc, char **argv) char *outfile = NULL; FILE *outfp = stderr; int status, exit_code = 0, with_argv0 = 0, multiprocess = 0, i; + char *arg; struct process *proc, *proc2; struct sigaction sa; sigset_t sm; /* TODO add option to trace signals with siginfo (-s) */ - /* TODO add option to truncate long syscall arguments and outputs (-a) - * This should be useful if your program does a lot of I/O */ ARGBEGIN { case '0': with_argv0 = 1; break; + case 'a': + arg = EARGF(usage()); + if (!strcmp(arg, "inf")) { + abbreviate_memory = SIZE_MAX; + break; + } + if (!isdigit(arg[0])) + usage(); + errno = 0; + abbreviate_memory = (size_t)strtoul(arg, &arg, 10); + if ((errno && errno != ERANGE) || *arg) + usage(); + break; case 'o': if (outfile) usage(); @@ -286,6 +299,7 @@ main(int argc, char **argv) if (outfp != stderr) fclose(outfp); + weprintf("Copying exit from %s\n", multiprocess ? "original tracee" : "tracee"); if (WIFSIGNALED(exit_code)) { exit_code = WTERMSIG(exit_code); raise(exit_code); |