📄 rtl-stub.c
字号:
/* for some reason, the mappings in reg.h are not *completely* correct. That * is, they don't match up with the mappings in GDB. For instance, EF_PC is * supposed to be the 64th integer in the gdb_regs array, not the 28th. i * don't know how gdb possibly works with normal core files, but to get things * to work here, we are going to *ignore* asm-alpha/regs.h and go with what * gdb says. -Nathan */static void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs){ gdb_regs[EF_V0] = regs->r0; /* return value */ gdb_regs[EF_T0] = regs->r1; /* temporary registers 1-8 */ gdb_regs[EF_T1] = regs->r2; gdb_regs[EF_T2] = regs->r3; gdb_regs[EF_T3] = regs->r4; gdb_regs[EF_T4] = regs->r5; gdb_regs[EF_T5] = regs->r6; gdb_regs[EF_T6] = regs->r7; gdb_regs[EF_T7] = regs->r8; gdb_regs[EF_S0] = 0; /* saved regs 9-15; we don't deal */ /* with these */ gdb_regs[EF_S1] = 0; gdb_regs[EF_S2] = 0; gdb_regs[EF_S3] = 0; gdb_regs[EF_S4] = 0; gdb_regs[EF_S5] = 0; gdb_regs[EF_S6] = 0; gdb_regs[16] = regs->r16; /* argument regs 16-21 */ gdb_regs[17] = regs->r17; gdb_regs[18] = regs->r18; gdb_regs[19] = regs->r19; gdb_regs[20] = regs->r20; gdb_regs[21] = regs->r21; gdb_regs[22] = regs->r22; /* temporary regs 22-25 */ gdb_regs[23] = regs->r23; gdb_regs[24] = regs->r24; gdb_regs[25] = regs->r25; gdb_regs[26] = regs->r26; /* return address */ gdb_regs[27] = regs->r27; /* procedure value */ gdb_regs[28] = regs->r28; /* assembler temp */ gdb_regs[30] = rdusp(); /* stack pointer */ gdb_regs[65] = regs->ps; /* processor status */ gdb_regs[64] = regs->pc; /* processor counter */ gdb_regs[EF_GP] = regs->gp; /* global pointer */} /* static void regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs) */static void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs){ regs->r0 = gdb_regs[EF_V0]; regs->r1 = gdb_regs[EF_T0]; regs->r2 = gdb_regs[EF_T1]; regs->r3 = gdb_regs[EF_T2]; regs->r4 = gdb_regs[EF_T3]; regs->r5 = gdb_regs[EF_T4]; regs->r6 = gdb_regs[EF_T5]; regs->r7 = gdb_regs[EF_T6]; regs->r8 = gdb_regs[EF_T7]; regs->r16 = gdb_regs[EF_A0]; regs->r17 = gdb_regs[EF_A1]; regs->r18 = gdb_regs[EF_A2]; regs->r19 = gdb_regs[EF_A3]; regs->r20 = gdb_regs[EF_A4]; regs->r21 = gdb_regs[EF_A5]; regs->r22 = gdb_regs[EF_T8]; regs->r23 = gdb_regs[EF_T9]; regs->r24 = gdb_regs[EF_T10]; regs->r25 = gdb_regs[EF_T11]; regs->r26 = gdb_regs[EF_RA]; regs->r27 = gdb_regs[EF_T12]; regs->r28 = gdb_regs[EF_AT]; regs->ps = gdb_regs[EF_PS]; regs->pc = gdb_regs[EF_PC]; regs->gp = gdb_regs[EF_GP];} /* static void gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs) */static int handle_exception(int exceptionVector, int signo, struct pt_regs *regs){ long addr, length, newPC; unsigned long flags; char *ptr; unsigned long gdb_regs[NUMREGS];#ifdef CONFIG_RTL_DEBUGGER_THREADS pthread_t current_thread = pthread_self();#endif /* CONFIG_RTL_DEBUGGER_THREADS */ rtl_hard_savef_and_cli(flags); if (user_mode(regs) && !(rtl_is_psc_active())) { rtl_printf("rtl_debug: got a user-mode exception\n"); return 0; } memset(gdb_regs, 0, NUMREGBYTES); if (remote_debug) show_regs(regs); if ((exceptionVector == 6) && (mem_err_expected == 1)) { mem_err = 1; /* set mem error flag */ mem_err_expected = 0; conpr("mem2hex() croaked\n"); if (remote_debug) conpr("Return after memory error\n"); if (remote_debug) show_regs(regs); rtl_hard_restore_flags(flags); return (1); } if (rtl_running_linux()) { rtl_hard_restore_flags(flags); rtl_printf("rtl_debug: not our fault; Linux's\n"); return 0; /* let Linux handle it's own faults */ } /* ok, here we know pthread_self() is an RT-thread */ pthread_cleanup_push(&rtl_exit_debugger, 0); rtl_enter_debugger(exceptionVector, (void *) regs->pc); /* reply to host that an exception has occurred */ set_bit(0, &send_exception_info); while (1) { error = 0; remcomOutBuffer[0] = 0; if (test_and_clear_bit(0, &send_exception_info)) { strcpy(remcomInBuffer, "?"); } else { getpacket(remcomInBuffer);/*conpr("getpacket: ");conpr(remcomInBuffer);conpr("\n");*/ } switch (remcomInBuffer[0]) { case 'q': if (!strcmp(remcomInBuffer, "qOffsets") && text && data && bss) { sprintf(remcomOutBuffer, "Text=%x;Data=%x;Bss=%x", (unsigned) text, (unsigned) data, (unsigned) bss); }#ifdef CONFIG_RTL_DEBUGGER_THREADS if (!strcmp(remcomInBuffer, "qC")) { sprintf(remcomOutBuffer, "QC%x", (unsigned long) (pthread_self())); } else if (!strncmp(remcomInBuffer, "qL", 2)) { /* we assume we have a limit of 31 threads -- * to fit in one packet */ char packethead[17]; pthread_t task; int ntasks = 0; int i; strcpy(remcomOutBuffer, remcomInBuffer); for (i = 0; i < rtl_num_cpus(); i++) { int cpu_id = cpu_logical_map(i); schedule_t *s = &rtl_sched[cpu_id]; spin_lock(&s->rtl_tasks_lock); task = s->rtl_tasks; while (task != &s->rtl_linux_task && ntasks < 31) { sprintf((remcomOutBuffer) + strlen (remcomOutBuffer), "00000000%08x", (unsigned long) task); task = task->next; ntasks++; } spin_unlock(&s->rtl_tasks_lock); } sprintf(packethead, "qM%02x%01x", ntasks, 1 /* done */ ); memcpy(remcomOutBuffer, packethead, strlen(packethead)); }#endif /* CONFIG_RTL_DEBUGGER_THREADS */ break;#ifdef CONFIG_RTL_DEBUGGER_THREADS case 'H': if ( /* remcomInBuffer[1] == 'c' || */ remcomInBuffer[1] == 'g') { if (remcomInBuffer[2] == '-') { current_thread = (pthread_t) - strtoul(remcomInBuffer + 3, 0, 16); } else { current_thread = (pthread_t) strtoul(remcomInBuffer + 2, 0, 16); } debugpr("Hc/g: %x", (unsigned long) current_thread); strcpy(remcomOutBuffer, "OK"); } break; case 'T':{ pthread_t thread; if (remcomInBuffer[1] == '-') { thread = (pthread_t) - strtoul(remcomInBuffer + 2, 0, 16); } else { thread = (pthread_t) strtoul(remcomInBuffer + 1, 0, 16); } if (!pthread_kill(thread, 0)) { strcpy(remcomOutBuffer, "OK"); } else { strcpy(remcomOutBuffer, "ERROR"); } } break;#endif /* CONFIG_RTL_DEBUGGER_THREADS */#ifdef CONFIG_RTL_DEBUGGER_Z_PROTOCOL case 'Z': case 'z': { int type = remcomInBuffer[1] - '0'; long address = strtoul(remcomInBuffer + 3, 0, 16); int res; if (type != 0) { strcpy(remcomOutBuffer, "ERROR"); break; } spin_lock(&bp_lock); if (remcomInBuffer[0] == 'Z') { res = insert_bp((char *) address); } else { remove_bp((char *) address); res = 0; } spin_unlock(&bp_lock); if (res) { strcpy(remcomOutBuffer, "ERROR"); } else { strcpy(remcomOutBuffer, "OK"); } } break;#endif /* CONFIG_RTL_DEBUGGER_Z_PROTOCOL */ case '?':#ifdef CONFIG_RTL_DEBUGGER_THREADS sprintf(remcomOutBuffer, "T%02xthread:%x;", signo, (unsigned long) pthread_self());#else remcomOutBuffer[0] = 'S'; remcomOutBuffer[1] = hexchars[signo >> 4]; remcomOutBuffer[2] = hexchars[signo % 16]; remcomOutBuffer[3] = 0;#endif /* CONFIG_RTL_DEBUGGER_THREADS */ break; case 'd': remote_debug = !(remote_debug); /* toggle debug flag */ printk("Remote debug %s\n", remote_debug ? "on" : "off"); break; case 'g': /* return the value of the CPU registers */ regs_to_gdb_regs(gdb_regs, regs);#ifdef CONFIG_RTL_DEBUGGER_THREADS if (current_thread != pthread_self()) { gdb_regs[EF_SP] = (long) current_thread->stack; gdb_regs[EF_PC] = *(current_thread->stack); rtl_printf("*(current_thread->stack: %x\n", (current_thread->stack)); debugpr("reg read for %x", (unsigned long) current_thread); }#endif /* CONFIG_RTL_DEBUGGER_THREADS */ mem2hex((char *) gdb_regs, remcomOutBuffer, NUMREGBYTES); break; case 'G': /* set the value of the CPU registers - return OK */ hex2mem(&remcomInBuffer[1], (char *) gdb_regs, NUMREGBYTES); gdb_regs_to_regs(gdb_regs, regs); strcpy(remcomOutBuffer, "OK"); break; /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ case 'm': /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ ptr = &remcomInBuffer[1]; if (hexToInt(&ptr, &addr)) if (*(ptr++) == ',') if (hexToInt(&ptr, &length)) { ptr = 0; if (!mem2hex ((char *) addr, remcomOutBuffer, length)) { strcpy (remcomOutBuffer, "E03"); debug_error ("memory fault\n", NULL); } } if (ptr) { strcpy(remcomOutBuffer, "E01"); debug_error ("malformed read memory command: %s\n", remcomInBuffer); } break; /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ case 'M': /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ ptr = &remcomInBuffer[1]; if (hexToInt(&ptr, &addr)) if (*(ptr++) == ',') if (hexToInt(&ptr, &length)) if (*(ptr++) == ':') { if (!hex2mem (ptr, (char *) addr, length)) { strcpy (remcomOutBuffer, "E03"); debug_error ("memory fault\n", NULL); } else { strcpy (remcomOutBuffer, "OK"); } ptr = 0; } if (ptr) { strcpy(remcomOutBuffer, "E02"); debug_error ("malformed write memory command: %s\n", remcomInBuffer); } break; /* cAA..AA Continue at address AA..AA(optional) */ /* sAA..AA Step one instruction from AA..AA(optional) */ case 'c': case 's': /* try to read optional parameter, pc unchanged if no * parm */ ptr = &remcomInBuffer[1]; if (hexToInt(&ptr, &addr)) { if (remote_debug) printk("Changing EF_PC to 0x%x\n", addr); regs->pc = addr; } newPC = regs->pc; /* clear the trace bit */#if 0 /* XXX don't know how to do these yet. -Nathan regs->ps &= 0xfffffeff; */ /* set the trace bit if we're stepping */ if (remcomInBuffer[0] == 's') regs.eflags |= 0x100;#endif /* 0 */ if (remote_debug) { printk("Resuming execution\n"); show_regs(regs); } debugpr("cont\n"); goto cleanup; /* kill the program */ case 'k': goto cleanup; } /* switch *//*conpr("putpacket: ");conpr(remcomOutBuffer);conpr("\n");*/ /* reply to the request */ putpacket(remcomOutBuffer); } /* while (1) */ cleanup:pthread_cleanup_pop(1); rtl_hard_restore_flags(flags); return (1);#undef regs}/* we don't have a hard_trap_info struct and we have to use this gigantic * switch statement because of the special case of generic traps. This also * means that we have to pass across the registers so that we can get the * value from r16 to determine which generic trap it is. */static int computeSignal(unsigned int tt, struct pt_regs *regs){ switch (tt) { case 0: /* breakpoint */ case 1: /* bugcheck */ return SIGTRAP; case 2: /* gentrap */ switch ((long) regs->r16) { case GEN_INTOVF: case GEN_INTDIV: case GEN_FLTOVF: case GEN_FLTDIV: case GEN_FLTUND: case GEN_FLTINV: case GEN_FLTINE: case GEN_ROPRAND: return SIGFPE; case GEN_DECOVF: case GEN_DECDIV: case GEN_DECINV: case GEN_ASSERTERR: case GEN_NULPTRERR: case GEN_STKOVF: case GEN_STRLENERR: case GEN_SUBSTRERR: case GEN_RANGERR: case GEN_SUBRNG: case GEN_SUBRNG1: case GEN_SUBRNG2: case GEN_SUBRNG3: case GEN_SUBRNG4: case GEN_SUBRNG5: case GEN_SUBRNG6: case GEN_SUBRNG7: return SIGTRAP; } /* switch ((long) regs->r16) */ case 3: /* FEN fault */ return SIGILL; case 4: /* opDEC */ return SIGILL; } /* switch (tt) */ /* don't know what signal to return? SIGHUP to the rescue! */ return SIGHUP;}int rtl_debug_exception(int vector, struct pt_regs *regs){ int signo = computeSignal(vector, regs); return handle_exception(vector, signo, regs);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -