mirror of
https://github.com/sstefani/mtrace.git
synced 2025-12-07 17:26:44 +08:00
more accurate single step, prelink fixes, cleanup
This commit is contained in:
parent
cf997a7dc9
commit
3e2980613c
@ -177,7 +177,7 @@ void wait_event_wakeup(void);
|
|||||||
int is_64bit(struct mt_elf *mte);
|
int is_64bit(struct mt_elf *mte);
|
||||||
|
|
||||||
/* change user id of a running process */
|
/* change user id of a running process */
|
||||||
void change_uid(const char *command);
|
void change_uid(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
12
breakpoint.c
12
breakpoint.c
@ -73,6 +73,9 @@ static void enable_sw_breakpoint(struct task *task, struct breakpoint *bp)
|
|||||||
debug(DEBUG_PROCESS, "pid=%d, addr=%#lx", task->pid, bp->addr);
|
debug(DEBUG_PROCESS, "pid=%d, addr=%#lx", task->pid, bp->addr);
|
||||||
|
|
||||||
copy_from_to_proc(task, bp->addr, break_insn, bp->orig_value, BREAKPOINT_LENGTH);
|
copy_from_to_proc(task, bp->addr, break_insn, bp->orig_value, BREAKPOINT_LENGTH);
|
||||||
|
|
||||||
|
bp->break_insn = !memcmp(break_insn, bp->orig_value, BREAKPOINT_LENGTH);
|
||||||
|
bp->was_hw = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void disable_sw_breakpoint(struct task *task, const struct breakpoint *bp)
|
static void disable_sw_breakpoint(struct task *task, const struct breakpoint *bp)
|
||||||
@ -230,6 +233,7 @@ void reorder_hw_bp(struct task *task)
|
|||||||
|
|
||||||
bp->hw_bp_slot = i;
|
bp->hw_bp_slot = i;
|
||||||
bp->hw = 1;
|
bp->hw = 1;
|
||||||
|
bp->was_hw = 1;
|
||||||
|
|
||||||
each_task(leader, enable_hw_bp_cb, bp);
|
each_task(leader, enable_hw_bp_cb, bp);
|
||||||
|
|
||||||
@ -260,6 +264,7 @@ static int insert_hw_bp_slot(struct task *task, struct breakpoint *bp)
|
|||||||
bp->enabled = 1;
|
bp->enabled = 1;
|
||||||
bp->hw_bp_slot = i;
|
bp->hw_bp_slot = i;
|
||||||
bp->hw = 1;
|
bp->hw = 1;
|
||||||
|
bp->was_hw = 1;
|
||||||
|
|
||||||
each_task(leader, enable_hw_bp_cb, bp);
|
each_task(leader, enable_hw_bp_cb, bp);
|
||||||
|
|
||||||
@ -357,6 +362,7 @@ struct breakpoint *breakpoint_new_ext(struct task *task, arch_addr_t addr, struc
|
|||||||
bp->enabled = 0;
|
bp->enabled = 0;
|
||||||
bp->locked = 0;
|
bp->locked = 0;
|
||||||
bp->deleted = 0;
|
bp->deleted = 0;
|
||||||
|
bp->break_insn = 0;
|
||||||
bp->ext = ext;
|
bp->ext = ext;
|
||||||
bp->refcnt = 1;
|
bp->refcnt = 1;
|
||||||
bp->count = 0;
|
bp->count = 0;
|
||||||
@ -383,6 +389,7 @@ struct breakpoint *breakpoint_new_ext(struct task *task, arch_addr_t addr, struc
|
|||||||
case BP_SW:
|
case BP_SW:
|
||||||
memset(bp->orig_value, 0, sizeof(bp->orig_value));
|
memset(bp->orig_value, 0, sizeof(bp->orig_value));
|
||||||
bp->hw = 0;
|
bp->hw = 0;
|
||||||
|
bp->was_hw = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dict_add(leader->breakpoints, (unsigned long)addr, bp) < 0) {
|
if (dict_add(leader->breakpoints, (unsigned long)addr, bp) < 0) {
|
||||||
@ -505,12 +512,13 @@ void breakpoint_delete(struct task *task, struct breakpoint *bp)
|
|||||||
|
|
||||||
if (unlikely(options.verbose > 1 && bp->libsym)) {
|
if (unlikely(options.verbose > 1 && bp->libsym)) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"delete %s breakpoint %s:%s [%#lx] count=%u\n",
|
"delete %s breakpoint %s:%s [%#lx] count=%u was_hw=%u\n",
|
||||||
bp->type == BP_SW ? "sw" : "hw",
|
bp->type == BP_SW ? "sw" : "hw",
|
||||||
bp->libsym->libref->filename,
|
bp->libsym->libref->filename,
|
||||||
bp->libsym->func->demangled_name,
|
bp->libsym->func->demangled_name,
|
||||||
bp->addr,
|
bp->addr,
|
||||||
bp->count);
|
bp->count,
|
||||||
|
bp->was_hw);
|
||||||
}
|
}
|
||||||
|
|
||||||
bp->deleted = 1;
|
bp->deleted = 1;
|
||||||
|
|||||||
@ -51,6 +51,8 @@ struct breakpoint {
|
|||||||
unsigned int locked:1;
|
unsigned int locked:1;
|
||||||
unsigned int deleted:1;
|
unsigned int deleted:1;
|
||||||
unsigned int hw:1;
|
unsigned int hw:1;
|
||||||
|
unsigned int was_hw:1;
|
||||||
|
unsigned int break_insn:1;
|
||||||
union {
|
union {
|
||||||
unsigned char orig_value[BREAKPOINT_LENGTH];
|
unsigned char orig_value[BREAKPOINT_LENGTH];
|
||||||
#if HW_BREAKPOINTS > 0
|
#if HW_BREAKPOINTS > 0
|
||||||
|
|||||||
@ -113,7 +113,7 @@ struct library_symbol *library_symbol_new(struct libref *libref, arch_addr_t add
|
|||||||
return libsym;
|
return libsym;
|
||||||
}
|
}
|
||||||
|
|
||||||
void library_delete(struct task *task, struct library *lib)
|
static void library_delete(struct task *task, struct library *lib)
|
||||||
{
|
{
|
||||||
if (lib == NULL)
|
if (lib == NULL)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -101,9 +101,6 @@ struct library {
|
|||||||
/* create a new symbol */
|
/* create a new symbol */
|
||||||
struct library_symbol *library_symbol_new(struct libref *libref, arch_addr_t addr, const struct function *func);
|
struct library_symbol *library_symbol_new(struct libref *libref, arch_addr_t addr, const struct function *func);
|
||||||
|
|
||||||
/* Delete library. Symbols are destroyed and freed. */
|
|
||||||
void library_delete(struct task *leader, struct library *lib);
|
|
||||||
|
|
||||||
/* Add a library to the list of the thread leader libraries. */
|
/* Add a library to the list of the thread leader libraries. */
|
||||||
struct library *library_add(struct task *leader, struct libref *libref);
|
struct library *library_add(struct task *leader, struct libref *libref);
|
||||||
|
|
||||||
|
|||||||
8
main.c
8
main.c
@ -104,12 +104,12 @@ static void mtrace_exit(void)
|
|||||||
each_pid(remove_task);
|
each_pid(remove_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mtrace_init(char **cmd)
|
static void mtrace_init(char **cmd_args)
|
||||||
{
|
{
|
||||||
struct opt_p_t *opt_p_tmp;
|
struct opt_p_t *opt_p_tmp;
|
||||||
|
|
||||||
if (options.command) {
|
if (options.command) {
|
||||||
struct task *task = task_create(options.command, cmd);
|
struct task *task = task_create(cmd_args);
|
||||||
|
|
||||||
if (!task)
|
if (!task)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -138,7 +138,7 @@ static void mtrace_main(void)
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char **cmd = process_options(argc, argv);
|
char **cmd_args = process_options(argc, argv);
|
||||||
|
|
||||||
init_pid_hash();
|
init_pid_hash();
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ int main(int argc, char *argv[])
|
|||||||
if (os_init())
|
if (os_init())
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
mtrace_init(cmd);
|
mtrace_init(cmd_args);
|
||||||
mtrace_main();
|
mtrace_main();
|
||||||
mtrace_exit();
|
mtrace_exit();
|
||||||
|
|
||||||
|
|||||||
@ -315,7 +315,7 @@ finish:
|
|||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void change_uid(const char *command)
|
void change_uid(void)
|
||||||
{
|
{
|
||||||
uid_t run_uid, run_euid;
|
uid_t run_uid, run_euid;
|
||||||
gid_t run_gid, run_egid;
|
gid_t run_gid, run_egid;
|
||||||
@ -348,13 +348,12 @@ void change_uid(const char *command)
|
|||||||
run_egid = run_gid;
|
run_egid = run_gid;
|
||||||
|
|
||||||
if (!stat(options.command, &statbuf)) {
|
if (!stat(options.command, &statbuf)) {
|
||||||
if (statbuf.st_mode & S_ISUID) {
|
if (statbuf.st_mode & S_ISUID)
|
||||||
run_euid = statbuf.st_uid;
|
run_euid = statbuf.st_uid;
|
||||||
}
|
|
||||||
if (statbuf.st_mode & S_ISGID) {
|
if (statbuf.st_mode & S_ISGID)
|
||||||
run_egid = statbuf.st_gid;
|
run_egid = statbuf.st_gid;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (setregid(run_gid, run_egid) < 0) {
|
if (setregid(run_gid, run_egid) < 0) {
|
||||||
perror("mtrace-ng: setregid");
|
perror("mtrace-ng: setregid");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|||||||
@ -462,7 +462,7 @@ static void linkmap_del(struct task *task, struct lt_r_debug_64 *dbg)
|
|||||||
|
|
||||||
addr = ARCH_ADDR_T(rlm.l_next);
|
addr = ARCH_ADDR_T(rlm.l_next);
|
||||||
|
|
||||||
lib = library_find_with_key(&tmp_list, ARCH_ADDR_T(rlm.l_addr));
|
lib = library_find_with_key(&tmp_list, ARCH_ADDR_T(rlm.l_ld));
|
||||||
if (lib)
|
if (lib)
|
||||||
list_move_tail(&lib->list, &task->libraries_list);
|
list_move_tail(&lib->list, &task->libraries_list);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -466,7 +466,6 @@ int handle_singlestep(struct task *task, int (*singlestep)(struct task *task), s
|
|||||||
int status;
|
int status;
|
||||||
int stop_signal;
|
int stop_signal;
|
||||||
unsigned long ip;
|
unsigned long ip;
|
||||||
int ret;
|
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (unlikely(singlestep(task) == -1))
|
if (unlikely(singlestep(task) == -1))
|
||||||
@ -489,26 +488,27 @@ int handle_singlestep(struct task *task, int (*singlestep)(struct task *task), s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ip != bp->addr) {
|
if (ip != bp->addr) {
|
||||||
ret = 0;
|
if (likely(stop_signal == SIGTRAP)) {
|
||||||
|
if (bp->break_insn) {
|
||||||
if (likely(stop_signal == SIGTRAP))
|
queue_event(task);
|
||||||
return ret;
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
ret = 1;
|
|
||||||
|
|
||||||
if (likely(!stop_signal)) {
|
if (likely(!stop_signal)) {
|
||||||
queue_event(task);
|
queue_event(task);
|
||||||
return ret;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fix_signal(task, stop_signal) > 0) {
|
if (fix_signal(task, stop_signal) > 0) {
|
||||||
queue_event(task);
|
queue_event(task);
|
||||||
return ret;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret)
|
if (ip != bp->addr)
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
task.c
4
task.c
@ -305,7 +305,7 @@ fail:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct task *task_create(const char *command, char **argv)
|
struct task *task_create(char **argv)
|
||||||
{
|
{
|
||||||
struct task *task;
|
struct task *task;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
@ -319,7 +319,7 @@ struct task *task_create(const char *command, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!pid) { /* child */
|
if (!pid) { /* child */
|
||||||
change_uid(options.command);
|
change_uid();
|
||||||
trace_me();
|
trace_me();
|
||||||
execvp(options.command, argv);
|
execvp(options.command, argv);
|
||||||
fprintf(stderr, "Can't execute `%s': %s\n", options.command, strerror(errno));
|
fprintf(stderr, "Can't execute `%s': %s\n", options.command, strerror(errno));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user