mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 19:26:25 +00:00
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb: kgdb: Always process the whole breakpoint list on activate or deactivate kgdb: continue and warn on signal passing from gdb kgdb,x86: do not set kgdb_single_step on x86 kgdb: allow for cpu switch when single stepping kgdb,i386: Fix corner case access to ss with NMI watch dog exception kgdb: Replace strstr() by strchr() for single-character needles kgdbts: Read buffer overflow kgdb: Read buffer overflow kgdb,x86: remove redundant test
This commit is contained in:
commit
880188b243
3 changed files with 59 additions and 25 deletions
|
@ -86,9 +86,15 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
||||||
gdb_regs[GDB_DS] = regs->ds;
|
gdb_regs[GDB_DS] = regs->ds;
|
||||||
gdb_regs[GDB_ES] = regs->es;
|
gdb_regs[GDB_ES] = regs->es;
|
||||||
gdb_regs[GDB_CS] = regs->cs;
|
gdb_regs[GDB_CS] = regs->cs;
|
||||||
gdb_regs[GDB_SS] = __KERNEL_DS;
|
|
||||||
gdb_regs[GDB_FS] = 0xFFFF;
|
gdb_regs[GDB_FS] = 0xFFFF;
|
||||||
gdb_regs[GDB_GS] = 0xFFFF;
|
gdb_regs[GDB_GS] = 0xFFFF;
|
||||||
|
if (user_mode_vm(regs)) {
|
||||||
|
gdb_regs[GDB_SS] = regs->ss;
|
||||||
|
gdb_regs[GDB_SP] = regs->sp;
|
||||||
|
} else {
|
||||||
|
gdb_regs[GDB_SS] = __KERNEL_DS;
|
||||||
|
gdb_regs[GDB_SP] = kernel_stack_pointer(regs);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
gdb_regs[GDB_R8] = regs->r8;
|
gdb_regs[GDB_R8] = regs->r8;
|
||||||
gdb_regs[GDB_R9] = regs->r9;
|
gdb_regs[GDB_R9] = regs->r9;
|
||||||
|
@ -101,8 +107,8 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
||||||
gdb_regs32[GDB_PS] = regs->flags;
|
gdb_regs32[GDB_PS] = regs->flags;
|
||||||
gdb_regs32[GDB_CS] = regs->cs;
|
gdb_regs32[GDB_CS] = regs->cs;
|
||||||
gdb_regs32[GDB_SS] = regs->ss;
|
gdb_regs32[GDB_SS] = regs->ss;
|
||||||
#endif
|
|
||||||
gdb_regs[GDB_SP] = kernel_stack_pointer(regs);
|
gdb_regs[GDB_SP] = kernel_stack_pointer(regs);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -220,8 +226,7 @@ static void kgdb_correct_hw_break(void)
|
||||||
dr7 |= ((breakinfo[breakno].len << 2) |
|
dr7 |= ((breakinfo[breakno].len << 2) |
|
||||||
breakinfo[breakno].type) <<
|
breakinfo[breakno].type) <<
|
||||||
((breakno << 2) + 16);
|
((breakno << 2) + 16);
|
||||||
if (breakno >= 0 && breakno <= 3)
|
set_debugreg(breakinfo[breakno].addr, breakno);
|
||||||
set_debugreg(breakinfo[breakno].addr, breakno);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
|
if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
|
||||||
|
@ -395,7 +400,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
|
||||||
/* set the trace bit if we're stepping */
|
/* set the trace bit if we're stepping */
|
||||||
if (remcomInBuffer[0] == 's') {
|
if (remcomInBuffer[0] == 's') {
|
||||||
linux_regs->flags |= X86_EFLAGS_TF;
|
linux_regs->flags |= X86_EFLAGS_TF;
|
||||||
kgdb_single_step = 1;
|
|
||||||
atomic_set(&kgdb_cpu_doing_single_step,
|
atomic_set(&kgdb_cpu_doing_single_step,
|
||||||
raw_smp_processor_id());
|
raw_smp_processor_id());
|
||||||
}
|
}
|
||||||
|
|
|
@ -712,6 +712,12 @@ static int run_simple_test(int is_get_char, int chr)
|
||||||
|
|
||||||
/* End of packet == #XX so look for the '#' */
|
/* End of packet == #XX so look for the '#' */
|
||||||
if (put_buf_cnt > 3 && put_buf[put_buf_cnt - 3] == '#') {
|
if (put_buf_cnt > 3 && put_buf[put_buf_cnt - 3] == '#') {
|
||||||
|
if (put_buf_cnt >= BUFMAX) {
|
||||||
|
eprintk("kgdbts: ERROR: put buffer overflow on"
|
||||||
|
" '%s' line %i\n", ts.name, ts.idx);
|
||||||
|
put_buf_cnt = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
put_buf[put_buf_cnt] = '\0';
|
put_buf[put_buf_cnt] = '\0';
|
||||||
v2printk("put%i: %s\n", ts.idx, put_buf);
|
v2printk("put%i: %s\n", ts.idx, put_buf);
|
||||||
/* Trigger check here */
|
/* Trigger check here */
|
||||||
|
@ -885,16 +891,16 @@ static void kgdbts_run_tests(void)
|
||||||
int nmi_sleep = 0;
|
int nmi_sleep = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ptr = strstr(config, "F");
|
ptr = strchr(config, 'F');
|
||||||
if (ptr)
|
if (ptr)
|
||||||
fork_test = simple_strtol(ptr + 1, NULL, 10);
|
fork_test = simple_strtol(ptr + 1, NULL, 10);
|
||||||
ptr = strstr(config, "S");
|
ptr = strchr(config, 'S');
|
||||||
if (ptr)
|
if (ptr)
|
||||||
do_sys_open_test = simple_strtol(ptr + 1, NULL, 10);
|
do_sys_open_test = simple_strtol(ptr + 1, NULL, 10);
|
||||||
ptr = strstr(config, "N");
|
ptr = strchr(config, 'N');
|
||||||
if (ptr)
|
if (ptr)
|
||||||
nmi_sleep = simple_strtol(ptr+1, NULL, 10);
|
nmi_sleep = simple_strtol(ptr+1, NULL, 10);
|
||||||
ptr = strstr(config, "I");
|
ptr = strchr(config, 'I');
|
||||||
if (ptr)
|
if (ptr)
|
||||||
sstep_test = simple_strtol(ptr+1, NULL, 10);
|
sstep_test = simple_strtol(ptr+1, NULL, 10);
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,7 @@ struct task_struct *kgdb_usethread;
|
||||||
struct task_struct *kgdb_contthread;
|
struct task_struct *kgdb_contthread;
|
||||||
|
|
||||||
int kgdb_single_step;
|
int kgdb_single_step;
|
||||||
|
pid_t kgdb_sstep_pid;
|
||||||
|
|
||||||
/* Our I/O buffers. */
|
/* Our I/O buffers. */
|
||||||
static char remcom_in_buffer[BUFMAX];
|
static char remcom_in_buffer[BUFMAX];
|
||||||
|
@ -541,12 +542,17 @@ static struct task_struct *getthread(struct pt_regs *regs, int tid)
|
||||||
*/
|
*/
|
||||||
if (tid == 0 || tid == -1)
|
if (tid == 0 || tid == -1)
|
||||||
tid = -atomic_read(&kgdb_active) - 2;
|
tid = -atomic_read(&kgdb_active) - 2;
|
||||||
if (tid < 0) {
|
if (tid < -1 && tid > -NR_CPUS - 2) {
|
||||||
if (kgdb_info[-tid - 2].task)
|
if (kgdb_info[-tid - 2].task)
|
||||||
return kgdb_info[-tid - 2].task;
|
return kgdb_info[-tid - 2].task;
|
||||||
else
|
else
|
||||||
return idle_task(-tid - 2);
|
return idle_task(-tid - 2);
|
||||||
}
|
}
|
||||||
|
if (tid <= 0) {
|
||||||
|
printk(KERN_ERR "KGDB: Internal thread select error\n");
|
||||||
|
dump_stack();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* find_task_by_pid_ns() does not take the tasklist lock anymore
|
* find_task_by_pid_ns() does not take the tasklist lock anymore
|
||||||
|
@ -619,7 +625,8 @@ static void kgdb_flush_swbreak_addr(unsigned long addr)
|
||||||
static int kgdb_activate_sw_breakpoints(void)
|
static int kgdb_activate_sw_breakpoints(void)
|
||||||
{
|
{
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
int error = 0;
|
int error;
|
||||||
|
int ret = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
|
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
|
||||||
|
@ -629,13 +636,16 @@ static int kgdb_activate_sw_breakpoints(void)
|
||||||
addr = kgdb_break[i].bpt_addr;
|
addr = kgdb_break[i].bpt_addr;
|
||||||
error = kgdb_arch_set_breakpoint(addr,
|
error = kgdb_arch_set_breakpoint(addr,
|
||||||
kgdb_break[i].saved_instr);
|
kgdb_break[i].saved_instr);
|
||||||
if (error)
|
if (error) {
|
||||||
return error;
|
ret = error;
|
||||||
|
printk(KERN_INFO "KGDB: BP install failed: %lx", addr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
kgdb_flush_swbreak_addr(addr);
|
kgdb_flush_swbreak_addr(addr);
|
||||||
kgdb_break[i].state = BP_ACTIVE;
|
kgdb_break[i].state = BP_ACTIVE;
|
||||||
}
|
}
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgdb_set_sw_break(unsigned long addr)
|
static int kgdb_set_sw_break(unsigned long addr)
|
||||||
|
@ -682,7 +692,8 @@ static int kgdb_set_sw_break(unsigned long addr)
|
||||||
static int kgdb_deactivate_sw_breakpoints(void)
|
static int kgdb_deactivate_sw_breakpoints(void)
|
||||||
{
|
{
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
int error = 0;
|
int error;
|
||||||
|
int ret = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
|
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
|
||||||
|
@ -691,13 +702,15 @@ static int kgdb_deactivate_sw_breakpoints(void)
|
||||||
addr = kgdb_break[i].bpt_addr;
|
addr = kgdb_break[i].bpt_addr;
|
||||||
error = kgdb_arch_remove_breakpoint(addr,
|
error = kgdb_arch_remove_breakpoint(addr,
|
||||||
kgdb_break[i].saved_instr);
|
kgdb_break[i].saved_instr);
|
||||||
if (error)
|
if (error) {
|
||||||
return error;
|
printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr);
|
||||||
|
ret = error;
|
||||||
|
}
|
||||||
|
|
||||||
kgdb_flush_swbreak_addr(addr);
|
kgdb_flush_swbreak_addr(addr);
|
||||||
kgdb_break[i].state = BP_SET;
|
kgdb_break[i].state = BP_SET;
|
||||||
}
|
}
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kgdb_remove_sw_break(unsigned long addr)
|
static int kgdb_remove_sw_break(unsigned long addr)
|
||||||
|
@ -1204,8 +1217,10 @@ static int gdb_cmd_exception_pass(struct kgdb_state *ks)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
error_packet(remcom_out_buffer, -EINVAL);
|
kgdb_msg_write("KGDB only knows signal 9 (pass)"
|
||||||
return 0;
|
" and 15 (pass and disconnect)\n"
|
||||||
|
"Executing a continue without signal passing\n", 0);
|
||||||
|
remcom_in_buffer[0] = 'c';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Indicate fall through */
|
/* Indicate fall through */
|
||||||
|
@ -1395,6 +1410,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
|
||||||
struct kgdb_state kgdb_var;
|
struct kgdb_state kgdb_var;
|
||||||
struct kgdb_state *ks = &kgdb_var;
|
struct kgdb_state *ks = &kgdb_var;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int sstep_tries = 100;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
int i, cpu;
|
int i, cpu;
|
||||||
|
|
||||||
|
@ -1425,13 +1441,14 @@ acquirelock:
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not start the debugger connection on this CPU if the last
|
* For single stepping, try to only enter on the processor
|
||||||
* instance of the exception handler wanted to come into the
|
* that was single stepping. To gaurd against a deadlock, the
|
||||||
* debugger on a different CPU via a single step
|
* kernel will only try for the value of sstep_tries before
|
||||||
|
* giving up and continuing on.
|
||||||
*/
|
*/
|
||||||
if (atomic_read(&kgdb_cpu_doing_single_step) != -1 &&
|
if (atomic_read(&kgdb_cpu_doing_single_step) != -1 &&
|
||||||
atomic_read(&kgdb_cpu_doing_single_step) != cpu) {
|
(kgdb_info[cpu].task &&
|
||||||
|
kgdb_info[cpu].task->pid != kgdb_sstep_pid) && --sstep_tries) {
|
||||||
atomic_set(&kgdb_active, -1);
|
atomic_set(&kgdb_active, -1);
|
||||||
touch_softlockup_watchdog();
|
touch_softlockup_watchdog();
|
||||||
clocksource_touch_watchdog();
|
clocksource_touch_watchdog();
|
||||||
|
@ -1524,6 +1541,13 @@ acquirelock:
|
||||||
}
|
}
|
||||||
|
|
||||||
kgdb_restore:
|
kgdb_restore:
|
||||||
|
if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
|
||||||
|
int sstep_cpu = atomic_read(&kgdb_cpu_doing_single_step);
|
||||||
|
if (kgdb_info[sstep_cpu].task)
|
||||||
|
kgdb_sstep_pid = kgdb_info[sstep_cpu].task->pid;
|
||||||
|
else
|
||||||
|
kgdb_sstep_pid = 0;
|
||||||
|
}
|
||||||
/* Free kgdb_active */
|
/* Free kgdb_active */
|
||||||
atomic_set(&kgdb_active, -1);
|
atomic_set(&kgdb_active, -1);
|
||||||
touch_softlockup_watchdog();
|
touch_softlockup_watchdog();
|
||||||
|
|
Loading…
Reference in a new issue