minor bug fixes

fix a crash on a race condition during new task creation
disable scratch hw bp after use
always stop threads when change a non scratch hw bp
only change os specific data for the leader
This commit is contained in:
Stefani Seibold 2015-11-26 08:02:40 +01:00
parent 3aed8a6e6b
commit 4fe84ebf6c
5 changed files with 59 additions and 32 deletions

1
.gitignore vendored
View File

@ -35,3 +35,4 @@ mtrace-ng
debian/files debian/files
debian/mtrace-ng.substvars debian/mtrace-ng.substvars
debian/mtrace-ng debian/mtrace-ng
tags

View File

@ -171,6 +171,7 @@ void reorder_hw_bp(struct task *task)
return; return;
n = 0; n = 0;
list_for_each(it, &leader->hw_bp_list) { list_for_each(it, &leader->hw_bp_list) {
bp = container_of(it, struct breakpoint, link_list); bp = container_of(it, struct breakpoint, link_list);
if (bp->enabled) { if (bp->enabled) {
@ -180,16 +181,19 @@ void reorder_hw_bp(struct task *task)
} }
} }
if (!n)
return;
qsort(bp_list, n, sizeof(*bp_list), hw_bp_sort); qsort(bp_list, n, sizeof(*bp_list), hw_bp_sort);
for(i = 0; i < n; ++i) { for(i = 0; i < n; ++i)
bp_list[i]->hwcnt = (i < HW_BREAKPOINTS - 1) ? BP_REORDER_THRESHOLD >> (i + 4) : 0; bp_list[i]->hwcnt = (i < HW_BREAKPOINTS - 1) ? BP_REORDER_THRESHOLD >> (i + 4) : 0;
}
if (n > HW_BREAKPOINTS - 1) if (n > HW_BREAKPOINTS - 1)
n = HW_BREAKPOINTS - 1; n = HW_BREAKPOINTS - 1;
p = bp_list; p = bp_list;
for(i = 0; i < n; ++i) { for(i = 0; i < n; ++i) {
if (bp_list[i]->hw) { if (bp_list[i]->hw) {
assert(bp_list[i]->hw_bp_slot != HW_BP_SCRATCH_SLOT); assert(bp_list[i]->hw_bp_slot != HW_BP_SCRATCH_SLOT);
@ -201,14 +205,23 @@ void reorder_hw_bp(struct task *task)
else else
*p++ = bp_list[i]; *p++ = bp_list[i];
} }
if (p == bp_list)
return;
*p = NULL; *p = NULL;
stop_threads(leader);
i = HW_BP_SCRATCH_SLOT + 1; i = HW_BP_SCRATCH_SLOT + 1;
for(p = bp_list; (bp = *p); ++p) { p = bp_list;
do {
bp = *p;
while(hw_bp_set & (1 << i)) while(hw_bp_set & (1 << i))
++i; ++i;
stop_threads(leader);
disable_sw_breakpoint(leader, bp); disable_sw_breakpoint(leader, bp);
if (leader->hw_bp[i]) if (leader->hw_bp[i])
@ -220,7 +233,8 @@ void reorder_hw_bp(struct task *task)
each_task(leader, enable_hw_bp_cb, bp); each_task(leader, enable_hw_bp_cb, bp);
++i; ++i;
} ++p;
} while(*p);
} }
static int insert_hw_bp_slot(struct task *task, struct breakpoint *bp) static int insert_hw_bp_slot(struct task *task, struct breakpoint *bp)
@ -233,7 +247,6 @@ static int insert_hw_bp_slot(struct task *task, struct breakpoint *bp)
break; break;
if (bp->type == BP_HW && leader->hw_bp[i]->type == BP_AUTO) { if (bp->type == BP_HW && leader->hw_bp[i]->type == BP_AUTO) {
stop_threads(leader);
hw2sw_bp(leader, leader->hw_bp[i]); hw2sw_bp(leader, leader->hw_bp[i]);
break; break;
} }
@ -396,14 +409,14 @@ void breakpoint_enable(struct task *task, struct breakpoint *bp)
bp->enabled = 1; bp->enabled = 1;
return; return;
} }
#endif
stop_threads(task);
#if HW_BREAKPOINTS > 1 #if HW_BREAKPOINTS > 1
if (bp->type >= BP_HW) { if (bp->type >= BP_HW) {
if (!insert_hw_bp_slot(task, bp)) if (!insert_hw_bp_slot(task, bp))
return; return;
} }
#endif #endif
#endif
stop_threads(task);
bp->hw = 0; bp->hw = 0;
enable_sw_breakpoint(task, bp); enable_sw_breakpoint(task, bp);
bp->enabled = 1; bp->enabled = 1;
@ -418,6 +431,7 @@ void breakpoint_disable(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);
if (likely(bp->enabled)) { if (likely(bp->enabled)) {
stop_threads(task);
#if HW_BREAKPOINTS > 0 #if HW_BREAKPOINTS > 0
if (bp->hw) { if (bp->hw) {
struct task *leader = task->leader; struct task *leader = task->leader;
@ -439,7 +453,6 @@ void breakpoint_disable(struct task *task, struct breakpoint *bp)
return; return;
} }
#endif #endif
stop_threads(task);
disable_sw_breakpoint(task, bp); disable_sw_breakpoint(task, bp);
bp->enabled = 0; bp->enabled = 0;
} }

View File

@ -240,6 +240,11 @@ static int handle_call_after(struct task *task, struct breakpoint *bp)
if (unlikely(options.verbose > 1)) if (unlikely(options.verbose > 1))
start_time(&start); start_time(&start);
#if HW_BREAKPOINTS > 0
if (bp->hw)
disable_scratch_hw_bp(task, bp);
#endif
task->libsym->func->report_out(task, task->libsym); task->libsym->func->report_out(task, task->libsym);
if (unlikely(options.verbose > 1)) if (unlikely(options.verbose > 1))

View File

@ -609,10 +609,10 @@ done:
int os_task_init(struct task *task) int os_task_init(struct task *task)
{ {
struct task *leader = task->leader; if (task == task->leader) {
task->os.debug_addr = 0;
leader->os.debug_addr = 0; task->os.debug_state = RT_ADD;
leader->os.debug_state = RT_ADD; }
return 0; return 0;
} }

46
task.c
View File

@ -131,6 +131,7 @@ static int leader_setup(struct task *leader)
static int task_init(struct task *task) static int task_init(struct task *task)
{ {
pid_t tgid; pid_t tgid;
struct task *leader;
/* Add process so that we know who the leader is. */ /* Add process so that we know who the leader is. */
tgid = process_leader(task->pid); tgid = process_leader(task->pid);
@ -140,7 +141,26 @@ static int task_init(struct task *task)
} }
if (tgid == task->pid) { if (tgid == task->pid) {
task->leader = task; leader = task;
}
else {
leader = pid2task(tgid);
if (!leader) {
fprintf(stderr, "%s no leader for tgpid=%d\n", __FUNCTION__, tgid);
return -1;
}
}
task->leader = leader;
if (arch_task_init(task) < 0)
return -1;
if (os_task_init(task) < 0)
return -1;
if (task == leader) {
task->threads = 1; task->threads = 1;
breakpoint_setup(task); breakpoint_setup(task);
@ -148,27 +168,14 @@ static int task_init(struct task *task)
list_add_tail(&task->leader_list, &list_of_leaders); list_add_tail(&task->leader_list, &list_of_leaders);
} }
else { else {
task->leader = pid2task(tgid); leader->threads++;
if (!task->leader) {
fprintf(stderr, "%s no leader for tgpid=%d\n", __FUNCTION__, tgid);
return -1;
}
task->leader->threads++;
task->breakpoints = NULL; task->breakpoints = NULL;
list_add_tail(&task->task_list, &task->leader->task_list); list_add_tail(&task->task_list, &leader->task_list);
} }
task->attached = 1; task->attached = 1;
if (arch_task_init(task) < 0)
return -1;
if (os_task_init(task) < 0)
return -1;
breakpoint_hw_destroy(task); breakpoint_hw_destroy(task);
return 0; return 0;
@ -243,16 +250,17 @@ struct task *task_new(pid_t pid)
library_setup(task); library_setup(task);
init_event(task);
if (task_init(task) < 0) if (task_init(task) < 0)
goto fail1; goto fail1;
init_event(task);
insert_pid(task); insert_pid(task);
return task; return task;
fail1: fail1:
task_destroy(task); free(task);
return NULL; return NULL;
} }