This is a proposal to facilitate more cleanly integrating a new backend, e.g. the previously proposed gdbserver backend
https://sourceforge.net/p/strace/mailman/message/35672632/ This is a proposed patch to add a dispatch table for a new backend. The idea is to add a dispatch table, a table of function pointers to those routines that a new backend needs to override. Changes fall into three categories 0. Add new dispatch table, "backend" to defs.h 1. The new backend will replace the default routine. The default case simply uses the existing routine. e.g. detach. All uses replaced by backend.foo 2. The new backend needs additional functionality. The default case will not use the entry. e.g. start_init, All uses guarded by null entry pointer check 3. The new backend will replace the default routine. The default case simply uses the existing routine but to account for having many callers a preprocessor macro is defined which uses the same name. e.g. umoven (Could alternately be replaced by #1) Any comments on using this approach to allow new backends to have a cleaner way to integrate with the existing frontend? Current patch diff --git a/defs.h b/defs.h index 5b81647..ec890ae 100644 --- a/defs.h +++ b/defs.h @@ -289,6 +289,28 @@ struct tcb { #define filtered(tcp) ((tcp)->flags & TCB_FILTERED) #define hide_log(tcp) ((tcp)->flags & TCB_HIDE_LOG) +/* BackendControl Block */ +struct backend { + bool (*trace) (void); + void (*detach) (struct tcb *tcp); + void (*startup_child) (char **argv); + void (*test_ptrace_seize) (void); + bool (*start_init) (void); + bool (*end_init) (void); + void (*startup_attach) (struct tcb *tcp); + void (*get_regs) (pid_t pid); + int (*get_scno) (struct tcb *tcp); + int (*getfdpath) (struct tcb *tcp, int fd, char *buf, unsigned bufsize); + int (*umoven_) (struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, + void *const our_addr); + int (*umovestr) (struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, char *laddr); + int (*upeek_) (int pid, unsigned long off, kernel_ulong_t *res); + int (*upoke_) (int pid, unsigned long off, kernel_ulong_t val); +} backend; + +#define umoven(tcp,addr,len,our_addr) backend.umoven_(tcp,addr,len,our_addr) +#define upeek(pid,off,res) backend.upeek_(int pid, unsigned long off, kernel_ulong_t *res) + #include "xlat.h" extern const struct xlat addrfams[]; @@ -445,8 +467,8 @@ static inline int set_tcb_priv_ulong(struct tcb *tcp, unsigned long val) return set_tcb_priv_data(tcp, (void *) val, 0); } -extern int -umoven(struct tcb *tcp, kernel_ulong_t addr, unsigned int len, void *laddr); +// extern int +// umoven(struct tcb *tcp, kernel_ulong_t addr, unsigned int len, void *laddr); #define umove(pid, addr, objp) \ umoven((pid), (addr), sizeof(*(objp)), (void *) (objp)) @@ -463,9 +485,17 @@ umoven_or_printaddr_ignore_syserror(struct tcb *tcp, kernel_ulong_t addr, extern int umovestr(struct tcb *tcp, kernel_ulong_t addr, unsigned int len, char *laddr); +#pragma push_macro("upeek") +#pragma push_macro("upoke") +#undef upeek +#undef upoke + extern int upeek(int pid, unsigned long, kernel_ulong_t *); extern int upoke(int pid, unsigned long, kernel_ulong_t); +#pragma pop_macro("upeek") +#pragma pop_macro("upoke") + extern bool print_array(struct tcb *tcp, kernel_ulong_t start_addr, diff --git a/pathtrace.c b/pathtrace.c index 90974f4..2d17d6e 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -58,7 +58,7 @@ upathmatch(struct tcb *const tcp, const kernel_ulong_t upath) { char path[PATH_MAX + 1]; - return umovestr(tcp, upath, sizeof path, path) > 0 && + return backend.umovestr(tcp, upath, sizeof path, path) > 0 && pathmatch(path); } @@ -69,7 +69,7 @@ static int fdmatch(struct tcb *tcp, int fd) { char path[PATH_MAX + 1]; - int n = getfdpath(tcp, fd, path, sizeof(path)); + int n = backend.getfdpath(tcp, fd, path, sizeof(path)); return n >= 0 && pathmatch(path); } diff --git a/strace.c b/strace.c index 4ee2d5d..1dd912f 100644 --- a/strace.c +++ b/strace.c @@ -157,7 +157,14 @@ unsigned os_release; /* generated from uname()'s u.release */ static void detach(struct tcb *tcp); static void cleanup(void); static void interrupt(int sig); +static bool trace (void); static sigset_t empty_set, blocked_set; +#pragma push_macro("umoven") +#undef umoven +int umoven(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, + void *const our_addr); +#pragma pop_macro("umoven") + #ifdef HAVE_SIG_ATOMIC_T static volatile sig_atomic_t interrupted; @@ -1132,6 +1139,11 @@ startup_attach(void) if (tcp->flags & TCB_ATTACHED) continue; /* no, we already attached it */ + if (backend.startup_attach) { + backend.startup_attach(tcp); + continue; + } + if (tcp->pid == parent_pid || tcp->pid == strace_tracer_pid) { errno = EPERM; perror_msg("attach: pid %d", tcp->pid); @@ -1567,6 +1579,7 @@ get_os_release(void) return rel; } + /* * Initialization part of main() was eating much stack (~0.5k), * which was unused after init. @@ -1783,6 +1796,9 @@ init(int argc, char *argv[]) tflag = 1; } + if (backend.start_init && backend.start_init() < 0) + error_msg_and_die("Cannot initialize backend on this target."); + #ifdef USE_LIBUNWIND if (stack_trace_enabled) { unsigned int tcbi; @@ -1817,9 +1833,23 @@ init(int argc, char *argv[]) ptrace_setoptions |= PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK; + backend.trace = trace; + backend.detach = detach; + backend.startup_child = startup_child; + backend.test_ptrace_seize = test_ptrace_seize; + backend.start_init = NULL; + backend.startup_attach = NULL; + backend.get_regs = NULL; + backend.get_scno = NULL; + backend.getfdpath = getfdpath; + backend.umoven_ = umoven; + backend.umovestr = umovestr; + backend.upeek_ = upeek; + backend.upoke_ = upoke; + if (debug_flag) error_msg("ptrace_setoptions = %#x", ptrace_setoptions); - test_ptrace_seize(); + backend.test_ptrace_seize(); /* * Is something weird with our stdin and/or stdout - @@ -1882,7 +1912,7 @@ init(int argc, char *argv[]) * in the startup_child() mode we kill the spawned process anyway. */ if (argv[0]) { - startup_child(argv); + backend.startup_child(argv); } sa.sa_handler = SIG_IGN; @@ -1917,6 +1947,9 @@ init(int argc, char *argv[]) if (nprocs != 0 || daemonized_tracer) startup_attach(); + if (backend.end_init) + backend.end_init(); + /* Do we want pids printed in our -o OUTFILE? * -ff: no (every pid has its own file); or * -f: yes (there can be more pids in the future); or @@ -1964,7 +1997,7 @@ cleanup(void) kill(tcp->pid, SIGCONT); kill(tcp->pid, fatal_sig); } - detach(tcp); + backend.detach(tcp); } if (cflag) call_summary(shared_log); @@ -2325,7 +2358,7 @@ trace(void) if (tcp->flags & TCB_SKIP_DETACH_ON_FIRST_EXEC) { tcp->flags &= ~TCB_SKIP_DETACH_ON_FIRST_EXEC; } else { - detach(tcp); /* do "-b execve" thingy */ + backend.detach(tcp); /* do "-b execve" thingy */ return true; } } @@ -2483,6 +2516,7 @@ restart_tracee: return true; } + int main(int argc, char *argv[]) { @@ -2490,7 +2524,7 @@ main(int argc, char *argv[]) exit_code = !nprocs; - while (trace()) + while (backend.trace()) ; cleanup(); diff --git a/syscall.c b/syscall.c index 3e91880..bb50659 100644 --- a/syscall.c +++ b/syscall.c @@ -1153,6 +1153,9 @@ ptrace_setregs(pid_t pid) static void get_regs(pid_t pid) { + if (backend.get_regs) + return backend.get_regs (pid); + #undef USE_GET_SYSCALL_RESULT_REGS #ifdef ptrace_getregset_or_getregs @@ -1230,7 +1233,11 @@ get_scno(struct tcb *tcp) if (get_regs_error) return -1; - int rc = arch_get_scno(tcp); + int rc; + if (backend.get_scno) + rc = backend.get_scno(tcp); + else + rc= arch_get_scno(tcp); if (rc != 1) return rc; diff --git a/upeek.c b/upeek.c index 01a12d3..8f191c7 100644 --- a/upeek.c +++ b/upeek.c @@ -34,6 +34,8 @@ #include "defs.h" #include "ptrace.h" +#undef upeek + int upeek(int pid, unsigned long off, kernel_ulong_t *res) { diff --git a/upoke.c b/upoke.c index dda0b8d..be4cea6 100644 --- a/upoke.c +++ b/upoke.c @@ -28,6 +28,8 @@ #include "defs.h" #include "ptrace.h" +#undef upoke + int upoke(int pid, unsigned long off, kernel_ulong_t val) { diff --git a/util.c b/util.c index 9144efb..0474c92 100644 --- a/util.c +++ b/util.c @@ -597,7 +597,7 @@ void printfd(struct tcb *tcp, int fd) { char path[PATH_MAX + 1]; - if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) { + if (show_fd_path && backend.getfdpath(tcp, fd, path, sizeof(path)) >= 0) { static const char socket_prefix[] = "socket:["; const size_t socket_prefix_len = sizeof(socket_prefix) - 1; const size_t path_len = strlen(path); @@ -855,7 +855,7 @@ printpathn(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int n) n = sizeof path - 1; /* Fetch one byte more to find out whether path length > n. */ - nul_seen = umovestr(tcp, addr, n + 1, path); + nul_seen = backend.umovestr(tcp, addr, n + 1, path); if (nul_seen < 0) printaddr(addr); else { @@ -912,7 +912,7 @@ printstr_ex(struct tcb *const tcp, const kernel_ulong_t addr, if (size > len) size = len; if (style & QUOTE_0_TERMINATED) - rc = umovestr(tcp, addr, size, str); + rc = backend.umovestr(tcp, addr, size, str); else rc = umoven(tcp, addr, size, str); @@ -1111,6 +1111,9 @@ vm_read_mem(const pid_t pid, void *const laddr, * move `len' bytes of data from process `pid' * at address `addr' to our space at `our_addr' */ +#pragma push_macro("umoven") +#undef umoven + int umoven(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, void *const our_addr) @@ -1221,6 +1224,8 @@ umoven(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, return 0; } +#pragma pop_macro("umoven") + int umoven_or_printaddr(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, void *const our_addr) ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel