📄 gdb-stub.c
字号:
#define __get_ibar(X) ({ unsigned long x; asm volatile("movsg ibar"#X",%0" : "=r"(x)); x; }) if (__debug_regs->dcr & DCR_IBE0 && __get_ibar(0) == addr) { //gdbstub_printk("clear h/w break 0: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE0; asm volatile("movgs gr0,ibar0"); return 0; } if (__debug_regs->dcr & DCR_IBE1 && __get_ibar(1) == addr) { //gdbstub_printk("clear h/w break 1: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE1; asm volatile("movgs gr0,ibar1"); return 0; } if (__debug_regs->dcr & DCR_IBE2 && __get_ibar(2) == addr) { //gdbstub_printk("clear h/w break 2: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE2; asm volatile("movgs gr0,ibar2"); return 0; } if (__debug_regs->dcr & DCR_IBE3 && __get_ibar(3) == addr) { //gdbstub_printk("clear h/w break 3: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE3; asm volatile("movgs gr0,ibar3"); return 0; } return -EINVAL; /* clear data read/write/access watchpoint */ case 2: case 3: case 4: if ((addr & ~7) != ((addr + len - 1) & ~7)) return -EINVAL; tmp = addr & 7; memset(dbmr.bytes, 0xff, sizeof(dbmr.bytes)); for (loop = 0; loop < len; loop++) dbmr.bytes[tmp + loop] = 0; addr &= ~7;#define __get_dbar(X) ({ unsigned long x; asm volatile("movsg dbar"#X",%0" : "=r"(x)); x; })#define __get_dbmr0(X) ({ unsigned long x; asm volatile("movsg dbmr"#X"0,%0" : "=r"(x)); x; })#define __get_dbmr1(X) ({ unsigned long x; asm volatile("movsg dbmr"#X"1,%0" : "=r"(x)); x; }) /* consider DBAR 0 */ tmp = type==2 ? DCR_DWBE0 : type==3 ? DCR_DRBE0 : DCR_DRBE0|DCR_DWBE0; if ((__debug_regs->dcr & (DCR_DRBE0|DCR_DWBE0)) != tmp || __get_dbar(0) != addr || __get_dbmr0(0) != dbmr.mask0 || __get_dbmr1(0) != dbmr.mask1) goto skip_dbar0; //gdbstub_printk("clear h/w watchpoint 0 type %ld: %08lx\n", type, addr); __debug_regs->dcr &= ~(DCR_DRBE0|DCR_DWBE0); asm volatile(" movgs gr0,dbar0 \n" " movgs gr0,dbmr00 \n" " movgs gr0,dbmr01 \n" " movgs gr0,dbdr00 \n" " movgs gr0,dbdr01 \n"); return 0; skip_dbar0: /* consider DBAR 0 */ tmp = type==2 ? DCR_DWBE1 : type==3 ? DCR_DRBE1 : DCR_DRBE1|DCR_DWBE1; if ((__debug_regs->dcr & (DCR_DRBE1|DCR_DWBE1)) != tmp || __get_dbar(1) != addr || __get_dbmr0(1) != dbmr.mask0 || __get_dbmr1(1) != dbmr.mask1) goto skip_dbar1; //gdbstub_printk("clear h/w watchpoint 1 type %ld: %08lx\n", type, addr); __debug_regs->dcr &= ~(DCR_DRBE1|DCR_DWBE1); asm volatile(" movgs gr0,dbar1 \n" " movgs gr0,dbmr10 \n" " movgs gr0,dbmr11 \n" " movgs gr0,dbdr10 \n" " movgs gr0,dbdr11 \n"); return 0; skip_dbar1: return -ENOSPC; default: return -EINVAL; }} /* end gdbstub_clear_breakpoint() *//*****************************************************************************//* * check a for an internal software breakpoint, and wind the PC back if necessary */static void gdbstub_check_breakpoint(void){ unsigned long addr = __debug_frame->pc - 4; int bkpt; for (bkpt = 255; bkpt >= 0; bkpt--) if (gdbstub_bkpts[bkpt].addr == addr) break; if (bkpt >= 0) __debug_frame->pc = addr; //gdbstub_printk("alter pc [%d] %08lx\n", bkpt, __debug_frame->pc);} /* end gdbstub_check_breakpoint() *//*****************************************************************************//* * */static void __attribute__((unused)) gdbstub_show_regs(void){ uint32_t *reg; int loop; gdbstub_printk("\n"); gdbstub_printk("Frame: @%p [%s]\n", __debug_frame, __debug_frame->psr & PSR_S ? "kernel" : "user"); reg = (uint32_t *) __debug_frame; for (loop = 0; loop < REG__END; loop++) { printk("%s %08x", regnames[loop + 0], reg[loop + 0]); if (loop == REG__END - 1 || loop % 5 == 4) printk("\n"); else printk(" | "); } gdbstub_printk("Process %s (pid: %d)\n", current->comm, current->pid);} /* end gdbstub_show_regs() *//*****************************************************************************//* * dump debugging regs */static void __attribute__((unused)) gdbstub_dump_debugregs(void){ unsigned long x; x = __debug_regs->dcr; gdbstub_printk("DCR %08lx ", x); x = __debug_regs->brr; gdbstub_printk("BRR %08lx\n", x); gdbstub_printk("IBAR0 %08lx ", __get_ibar(0)); gdbstub_printk("IBAR1 %08lx ", __get_ibar(1)); gdbstub_printk("IBAR2 %08lx ", __get_ibar(2)); gdbstub_printk("IBAR3 %08lx\n", __get_ibar(3)); gdbstub_printk("DBAR0 %08lx ", __get_dbar(0)); gdbstub_printk("DBMR00 %08lx ", __get_dbmr0(0)); gdbstub_printk("DBMR01 %08lx\n", __get_dbmr1(0)); gdbstub_printk("DBAR1 %08lx ", __get_dbar(1)); gdbstub_printk("DBMR10 %08lx ", __get_dbmr0(1)); gdbstub_printk("DBMR11 %08lx\n", __get_dbmr1(1)); gdbstub_printk("\n");} /* end gdbstub_dump_debugregs() *//*****************************************************************************//* * dump the MMU state into a structure so that it can be accessed with GDB */void gdbstub_get_mmu_state(void){ asm volatile("movsg hsr0,%0" : "=r"(__debug_mmu.regs.hsr0)); asm volatile("movsg pcsr,%0" : "=r"(__debug_mmu.regs.pcsr)); asm volatile("movsg esr0,%0" : "=r"(__debug_mmu.regs.esr0)); asm volatile("movsg ear0,%0" : "=r"(__debug_mmu.regs.ear0)); asm volatile("movsg epcr0,%0" : "=r"(__debug_mmu.regs.epcr0)); /* read the protection / SAT registers */ __debug_mmu.iamr[0].L = __get_IAMLR(0); __debug_mmu.iamr[0].P = __get_IAMPR(0); __debug_mmu.iamr[1].L = __get_IAMLR(1); __debug_mmu.iamr[1].P = __get_IAMPR(1); __debug_mmu.iamr[2].L = __get_IAMLR(2); __debug_mmu.iamr[2].P = __get_IAMPR(2); __debug_mmu.iamr[3].L = __get_IAMLR(3); __debug_mmu.iamr[3].P = __get_IAMPR(3); __debug_mmu.iamr[4].L = __get_IAMLR(4); __debug_mmu.iamr[4].P = __get_IAMPR(4); __debug_mmu.iamr[5].L = __get_IAMLR(5); __debug_mmu.iamr[5].P = __get_IAMPR(5); __debug_mmu.iamr[6].L = __get_IAMLR(6); __debug_mmu.iamr[6].P = __get_IAMPR(6); __debug_mmu.iamr[7].L = __get_IAMLR(7); __debug_mmu.iamr[7].P = __get_IAMPR(7); __debug_mmu.iamr[8].L = __get_IAMLR(8); __debug_mmu.iamr[8].P = __get_IAMPR(8); __debug_mmu.iamr[9].L = __get_IAMLR(9); __debug_mmu.iamr[9].P = __get_IAMPR(9); __debug_mmu.iamr[10].L = __get_IAMLR(10); __debug_mmu.iamr[10].P = __get_IAMPR(10); __debug_mmu.iamr[11].L = __get_IAMLR(11); __debug_mmu.iamr[11].P = __get_IAMPR(11); __debug_mmu.iamr[12].L = __get_IAMLR(12); __debug_mmu.iamr[12].P = __get_IAMPR(12); __debug_mmu.iamr[13].L = __get_IAMLR(13); __debug_mmu.iamr[13].P = __get_IAMPR(13); __debug_mmu.iamr[14].L = __get_IAMLR(14); __debug_mmu.iamr[14].P = __get_IAMPR(14); __debug_mmu.iamr[15].L = __get_IAMLR(15); __debug_mmu.iamr[15].P = __get_IAMPR(15); __debug_mmu.damr[0].L = __get_DAMLR(0); __debug_mmu.damr[0].P = __get_DAMPR(0); __debug_mmu.damr[1].L = __get_DAMLR(1); __debug_mmu.damr[1].P = __get_DAMPR(1); __debug_mmu.damr[2].L = __get_DAMLR(2); __debug_mmu.damr[2].P = __get_DAMPR(2); __debug_mmu.damr[3].L = __get_DAMLR(3); __debug_mmu.damr[3].P = __get_DAMPR(3); __debug_mmu.damr[4].L = __get_DAMLR(4); __debug_mmu.damr[4].P = __get_DAMPR(4); __debug_mmu.damr[5].L = __get_DAMLR(5); __debug_mmu.damr[5].P = __get_DAMPR(5); __debug_mmu.damr[6].L = __get_DAMLR(6); __debug_mmu.damr[6].P = __get_DAMPR(6); __debug_mmu.damr[7].L = __get_DAMLR(7); __debug_mmu.damr[7].P = __get_DAMPR(7); __debug_mmu.damr[8].L = __get_DAMLR(8); __debug_mmu.damr[8].P = __get_DAMPR(8); __debug_mmu.damr[9].L = __get_DAMLR(9); __debug_mmu.damr[9].P = __get_DAMPR(9); __debug_mmu.damr[10].L = __get_DAMLR(10); __debug_mmu.damr[10].P = __get_DAMPR(10); __debug_mmu.damr[11].L = __get_DAMLR(11); __debug_mmu.damr[11].P = __get_DAMPR(11); __debug_mmu.damr[12].L = __get_DAMLR(12); __debug_mmu.damr[12].P = __get_DAMPR(12); __debug_mmu.damr[13].L = __get_DAMLR(13); __debug_mmu.damr[13].P = __get_DAMPR(13); __debug_mmu.damr[14].L = __get_DAMLR(14); __debug_mmu.damr[14].P = __get_DAMPR(14); __debug_mmu.damr[15].L = __get_DAMLR(15); __debug_mmu.damr[15].P = __get_DAMPR(15);#ifdef CONFIG_MMU do { /* read the DAT entries from the TLB */ struct __debug_amr *p; int loop; asm volatile("movsg tplr,%0" : "=r"(__debug_mmu.regs.tplr)); asm volatile("movsg tppr,%0" : "=r"(__debug_mmu.regs.tppr)); asm volatile("movsg tpxr,%0" : "=r"(__debug_mmu.regs.tpxr)); asm volatile("movsg cxnr,%0" : "=r"(__debug_mmu.regs.cxnr)); p = __debug_mmu.tlb; /* way 0 */ asm volatile("movgs %0,tpxr" :: "r"(0 << TPXR_WAY_SHIFT)); for (loop = 0; loop < 64; loop++) { asm volatile("tlbpr %0,gr0,#1,#0" :: "r"(loop << PAGE_SHIFT)); asm volatile("movsg tplr,%0" : "=r"(p->L)); asm volatile("movsg tppr,%0" : "=r"(p->P)); p++; } /* way 1 */ asm volatile("movgs %0,tpxr" :: "r"(1 << TPXR_WAY_SHIFT)); for (loop = 0; loop < 64; loop++) { asm volatile("tlbpr %0,gr0,#1,#0" :: "r"(loop << PAGE_SHIFT)); asm volatile("movsg tplr,%0" : "=r"(p->L)); asm volatile("movsg tppr,%0" : "=r"(p->P)); p++; } asm volatile("movgs %0,tplr" :: "r"(__debug_mmu.regs.tplr)); asm volatile("movgs %0,tppr" :: "r"(__debug_mmu.regs.tppr)); asm volatile("movgs %0,tpxr" :: "r"(__debug_mmu.regs.tpxr)); } while(0);#endif} /* end gdbstub_get_mmu_state() *//*****************************************************************************//* * handle event interception and GDB remote protocol processing * - on entry: * PSR.ET==0, PSR.S==1 and the CPU is in debug mode * __debug_frame points to the saved registers * __frame points to the kernel mode exception frame, if it was in kernel * mode when the break happened */void gdbstub(int sigval){ unsigned long addr, length, loop, dbar, temp, temp2, temp3; uint32_t zero; char *ptr; int flush_cache = 0; LEDS(0x5000); if (sigval < 0) {#ifndef CONFIG_GDBSTUB_IMMEDIATE /* return immediately if GDB immediate activation option not set */ return;#else sigval = SIGINT;#endif } save_user_regs(&__break_user_context);#if 0 gdbstub_printk("--> gdbstub() %08x %p %08x %08x\n", __debug_frame->pc, __debug_frame, __debug_regs->brr, __debug_regs->bpsr);// gdbstub_show_regs();#endif LEDS(0x5001); /* if we were interrupted by input on the serial gdbstub serial port, * restore the context prior to the interrupt so that we return to that * directly */ temp = (unsigned long) __entry_kerneltrap_table; temp2 = (unsigned long) __entry_usertrap_table; temp3 = __debug_frame->pc & ~15; if (temp3 == temp + TBR_TT_INTERRUPT_15 || temp3 == temp2 + TBR_TT_INTERRUPT_15 ) { asm volatile("movsg pcsr,%0" : "=r"(__debug_frame->pc)); __debug_frame->psr |= PSR_ET; __debug_frame->psr &= ~PSR_S; if (__debug_frame->psr & PSR_PS) __debug_frame->psr |= PSR_S; __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12; __debug_regs->brr |= BRR_EB; sigval = SIGINT; } /* handle the decrement timer going off (FR451 only) */ if (temp3 == temp + TBR_TT_DECREMENT_TIMER || temp3 == temp2 + TBR_TT_DECREMENT_TIMER ) { asm volatile("movgs %0,timerd" :: "r"(10000000)); asm volatile("movsg pcsr,%0" : "=r"(__debug_frame->pc)); __debug_frame->psr |= PSR_ET; __debug_frame->psr &= ~PSR_S; if (__debug_frame->psr & PSR_PS) __debug_frame->psr |= PSR_S; __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12; __debug_regs->brr |= BRR_EB; sigval = SIGXCPU;; } LEDS(0x5002); /* after a BREAK insn, the PC lands on the far side of it */ if (__debug_regs->brr & BRR_SB) gdbstub_check_breakpoint(); LEDS(0x5003); /* handle attempts to write console data via GDB "O" commands */ if (__debug_frame->pc == (unsigned long) gdbstub_console_write + 4) { __gdbstub_console_write((struct console *) __debug_frame->gr8, (const char *) __debug_frame->gr9, (unsigned) __debug_frame->gr10); goto done; } if (gdbstub_rx_unget) { sigval = SIGINT; goto packet_waiting; } if (!sigval) sigval = gdbstub_compute_signal(__debug_regs->brr); LEDS(0x5004); /* send a message to the debugger's user saying what happened if it may * not be clear cut (we can't map exceptions onto signals properly) */ if (sigval != SIGINT && sigval != SIGTRAP && sigval != SIGILL) { static const char title[] = "Break "; static const char crlf[] = "\r\n"; unsigned long brr = __debug_regs->brr; char hx; ptr = output_buffer; *ptr++ = 'O'; ptr = mem2hex(title, ptr, sizeof(title) - 1,0); hx = hexchars[(brr & 0xf0000000) >> 28]; *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; hx = hexchars[(brr & 0x0f000000) >> 24]; *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; hx = hexchars[(brr & 0x00f00000) >> 20]; *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; hx = hexchars[(brr & 0x000f0000) >> 16]; *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; hx = hexchars[(brr & 0x0000f000) >> 12]; *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; hx = hexchars[(brr & 0x00000f00) >> 8]; *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; hx = hexchars[(brr & 0x000000f0) >> 4]; *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; hx = hexchars[(brr & 0x0000000f)]; *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0); *ptr = 0; gdbstub_send_packet(output_buffer); /* send it off... */ } LEDS(0x5005); /* tell the debugger that an exception has occurred */ ptr = output_buffer; /* Send trap type (converted to signal) */ *ptr++ = 'T'; *ptr++ = hexchars[sigval >> 4]; *ptr++ = hexchars[sigval & 0xf]; /* Send Error PC */ *ptr++ = hexchars[GDB_REG_PC >> 4]; *ptr++ = hexchars[GDB_REG_PC & 0xf]; *ptr++ = ':'; ptr = mem2hex(&__debug_frame->pc, ptr, 4, 0); *ptr++ = ';'; /* * Send frame pointer */ *ptr++ = hexchars[GDB_REG_FP >> 4]; *ptr++ = hexchars[GDB_REG_FP & 0xf]; *ptr++ = ':'; ptr = mem2hex(&__debug_frame->fp, ptr, 4, 0); *ptr++ = ';'; /* * Send stack pointer */ *ptr++ = hexchars[GDB_REG_SP >> 4]; *ptr++ = hexchars[GDB_REG_SP & 0xf]; *ptr++ = ':'; ptr = mem2hex(&__debug_frame->sp, ptr, 4, 0); *ptr++ = ';'; *ptr++ = 0; gdbstub_send_packet(output_buffer); /* send it off... */ LEDS(0x5006); packet_waiting: gdbstub_get_mmu_state(); /* wait for input from remote GDB */ while (1) { output_buffer[0] = 0; LEDS(0x5007); gdbstub_recv_packet(input_buffer); LEDS(0x5600 | input_buffer[0]); switch (input_buffer[0]) { /* request repeat of last signal number */ case '?': output_buffer[0] = 'S'; output_buffer[1] = hexchars[sigval >> 4]; output_buffer[2] = hexchars[sigval & 0xf]; output_buffer[3] = 0; break; case 'd': /* toggle debug flag */ break; /* return the value of the CPU registers * - GR0, GR1, GR2, GR3, GR4, GR5, GR6, GR7, * - GR8, GR9, GR10, GR11, GR12, GR13, GR14, GR15, * - GR16, GR17, GR18, GR19, GR20, GR21, GR22, GR23, * - GR24, GR25, GR26, GR27, GR28, GR29, GR30, GR31, * - GR32, GR33, GR34, GR35, GR36, GR37, GR38, GR39, * - GR40, GR41, GR42, GR43, GR44, GR45, GR46, GR47, * - GR48, GR49, GR50, GR51, GR52, GR53, GR54, GR55, * - GR56, GR57, GR58, GR59, GR60, GR61, GR62, GR63, * - FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7, * - FP8, FP9, FP10, FP11, FP12, FP13, FP14, FP15, * - FP16, FP17, FP18, FP19, FP20, FP21, FP22, FP23, * - FP24, FP25, FP26, FP27, FP28, FP29, FP30, FP31, * - FP32, FP33, FP34, FP35, FP36, FP37, FP38, FP39, * - FP40, FP41, FP42, FP43, FP44, FP45, FP46, FP47, * - FP48, FP49, FP50, FP51, FP52, FP53, FP54, FP55, * - FP56, FP57, FP58, FP59, FP60, FP61, FP62, FP63, * - PC, PSR, CCR, CCCR, * - _X132, _X133, _X134 * - TBR, BRR, DBAR0, DBAR1, DBAR2, DBAR3, * - _X141, _X142, _X143, _X144, * - LR, LCR */ case 'g': zero = 0; ptr = output_buffer; /* deal with GR0, GR1-GR27, GR28-GR31, GR32-GR63 */ ptr = mem2hex(&zero, ptr, 4, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -