/* * This file is part of mtrace. * Copyright (C) 2015 Stefani Seibold * This file is based on the ltrace source * Copyright (C) 2012 Petr Machata, Red Hat Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef _INC_BACKEND_H #define _INC_BACKEND_H #include "config.h" #include "arch.h" #include "os.h" #include "forward.h" #include "mtrace.h" #include #include /* Convert a PID to a path to the corresponding binary. */ char *pid2name(pid_t pid); /* Given a PID, find a leader of thread group. */ pid_t process_leader(pid_t pid); /* Given a PID of leader thread, fill in PIDs of all the tasks. The * function will initialize the pointer *RET_TASKS to a * newly-allocated array, and will store number of elements in that * array to *RET_N. You have to free that buffer when you don't need * it anymore. */ int process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n); /* set tracing options, the task must be in state traced */ int trace_set_options(struct task *task); /* make the forked process traceable */ void trace_me(void); /* stop tracing a task. */ int untrace_task(struct task *task, int signum); /* Called when mtrace needs to attach to task, such as when it attaches * to a running process, whose PID is given on the command line. */ int trace_attach(struct task *task); /* wait for a task ready for tracing */ int trace_wait(struct task *task); /* continue process */ int continue_task(struct task *task, int signum); /* Return current instruction pointer */ arch_addr_t get_instruction_pointer(struct task *task); /* Set instruction pointer of task to addr */ void set_instruction_pointer(struct task *task, arch_addr_t addr); /* do a single step */ int do_singlestep(struct task *task); /* handle a single step event */ int handle_singlestep(struct task *task, int (*singlestep)(struct task *task)); /* Find and return caller address, i.e. the address where the current * function returns. */ arch_addr_t get_return_addr(struct task *task); /* set instruction hw breakpoint */ int set_hw_bp(struct task *task, unsigned int slot, arch_addr_t addr); /* remove instruction hw breakpoint */ int reset_hw_bp(struct task *task, unsigned int slot, arch_addr_t addr); /* save the process context (state, registers, stack pointer) */ int fetch_context(struct task *task); /* save the process context for parameter fetching */ void save_param_context(struct task *task); /* get return value of a remote function */ unsigned long fetch_retval(struct task *task); /* get parameter value of a remote function */ unsigned long fetch_param(struct task *task, unsigned int param); /* get register value of a remote function */ unsigned long fetch_reg(struct task *task, unsigned int reg); /* Should copy len bytes from address addr of task to local buffer dst */ ssize_t copy_from_proc(struct task *task, arch_addr_t addr, void *dst, size_t len); /* Should copy len bytes from local buffer src to address addr of the remote task */ ssize_t copy_to_proc(struct task *task, arch_addr_t addr, const void *src, size_t len); /* Should copy len bytes from address addr of remote task to local * buffer dst and overwrite the task data with src */ ssize_t copy_from_to_proc(struct task *task, arch_addr_t addr, const void *src, void *dst, size_t len); /* Should copy max. len of a string from address addr from the remote task * to local buffer dst */ ssize_t copy_str_from_proc(struct task *task, arch_addr_t addr, char *dst, size_t len); /* Called at some point after we have attached to PROC. This callback * should insert an introspection breakpoint for handling dynamic * linker library loads. */ int linkmap_init(struct task *task, arch_addr_t dyn_addr); /* This should extract entry point address and interpreter (dynamic * linker) bias if possible. Returns 0 if there were no errors, -1 * otherwise. Sets *ENTRYP and *INTERP_BIASP to non-zero values if * the corresponding value is known, or zero otherwise; this is not * done for pointers that are NULL. */ int process_get_entry(struct task *task, unsigned long *entryp, unsigned long *interp_biasp); /* The following callbacks have to be implemented in OS backend if * os.h defines OS_HAVE_PROCESS_DATA. */ #ifdef OS_HAVE_PROCESS_DATA int os_task_init(struct task *task); void os_task_destroy(struct task *task); int os_task_clone(struct task *retp, struct task *task); #endif /* The following callbacks have to be implemented in OS backend if * os.h defines ARCH_HAVE_PROCESS_DATA. */ #ifdef ARCH_HAVE_PROCESS_DATA int arch_task_init(struct task *task); void arch_task_destroy(struct task *task); int arch_task_clone(struct task *retp, struct task *task); #endif /* stop all thread of a given task */ void stop_threads(struct task *task); /* scan writeable memory segments */ void *mem_scan(struct task *task, struct mt_msg *cmd, void *payload, unsigned long *data_len); /* os specific init */ int os_init(void); /* wait for the next unqueued trace event */ struct task *wait_event(); /* wakeup a wait_event() call */ void wait_event_wakeup(void); /* return true the elf file is 64 bit */ int is_64bit(struct mt_elf *mte); /* change user id of a running process */ void change_uid(const char *command); #endif