📄 mips-lite.patch
字号:
- unsigned char checksum;- int count;- unsigned char ch;-- /*- * $<packet info>#<checksum>.- */-- do {- putDebugChar('$');- checksum = 0;- count = 0;-- while ((ch = buffer[count]) != 0) {- if (!(putDebugChar(ch)))- return;- checksum += ch;- count += 1;- }-- putDebugChar('#');- putDebugChar(hexchars[checksum >> 4]);- putDebugChar(hexchars[checksum & 0xf]);-- }- while ((getDebugChar() & 0x7f) != '+');-}---/*- * Convert the memory pointed to by mem into hex, placing result in buf.- * Return a pointer to the last char put in buf (null), in case of mem fault,- * return 0.- * may_fault is non-zero if we are reading from arbitrary memory, but is currently- * not used.- */-static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)-{- unsigned char ch;-- while (count-- > 0) {- if (kgdb_read_byte(mem++, &ch) != 0)- return 0;- *buf++ = hexchars[ch >> 4];- *buf++ = hexchars[ch & 0xf];- }-- *buf = 0;-- return buf;-}--/*- * convert the hex array pointed to by buf into binary to be placed in mem- * return a pointer to the character AFTER the last byte written- * may_fault is non-zero if we are reading from arbitrary memory, but is currently- * not used.- */-static char *hex2mem(char *buf, char *mem, int count, int binary, int may_fault)-{- int i;- unsigned char ch;-- for (i=0; i<count; i++)- {- if (binary) {- ch = *buf++;- if (ch == 0x7d)- ch = 0x20 ^ *buf++;- }- else {- ch = hex(*buf++) << 4;- ch |= hex(*buf++);- }- if (kgdb_write_byte(ch, mem++) != 0)- return 0;- }-- return mem;-}--/*- * This table contains the mapping between SPARC hardware trap types, and- * signals, which are primarily what GDB understands. It also indicates- * which hardware traps we need to commandeer when initializing the stub.- */-static struct hard_trap_info {- unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */- unsigned char signo; /* Signal that we map this trap into */-} hard_trap_info[] = {- { 6, SIGBUS }, /* instruction bus error */- { 7, SIGBUS }, /* data bus error */- { 9, SIGTRAP }, /* break */- { 10, SIGILL }, /* reserved instruction */-/* { 11, SIGILL }, */ /* CPU unusable */- { 12, SIGFPE }, /* overflow */- { 13, SIGTRAP }, /* trap */- { 14, SIGSEGV }, /* virtual instruction cache coherency */- { 15, SIGFPE }, /* floating point exception */- { 23, SIGSEGV }, /* watch */- { 31, SIGSEGV }, /* virtual data cache coherency */- { 0, 0} /* Must be last */-};--/* Save the normal trap handlers for user-mode traps. */-void *saved_vectors[32];--/*- * Set up exception handlers for tracing and breakpoints- */-void set_debug_traps(void)-{- struct hard_trap_info *ht;- unsigned long flags;- unsigned char c;-- local_irq_save(flags);- for (ht = hard_trap_info; ht->tt && ht->signo; ht++)- saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low);-- putDebugChar('+'); /* 'hello world' */- /*- * In case GDB is started before us, ack any packets- * (presumably "$?#xx") sitting there.- */- while((c = getDebugChar()) != '$');- while((c = getDebugChar()) != '#');- c = getDebugChar(); /* eat first csum byte */- c = getDebugChar(); /* eat second csum byte */- putDebugChar('+'); /* ack it */-- initialized = 1;- local_irq_restore(flags);-}--void restore_debug_traps(void)-{- struct hard_trap_info *ht;- unsigned long flags;-- local_irq_save(flags);- for (ht = hard_trap_info; ht->tt && ht->signo; ht++)- set_except_vector(ht->tt, saved_vectors[ht->tt]);- local_irq_restore(flags);-}--/*- * Convert the MIPS hardware trap type code to a Unix signal number.- */-static int computeSignal(int tt)-{- struct hard_trap_info *ht;-- for (ht = hard_trap_info; ht->tt && ht->signo; ht++)- if (ht->tt == tt)- return ht->signo;-- return SIGHUP; /* default for things we don't know about */-}--/*- * While we find nice hex chars, build an int.- * Return number of chars processed.- */-static int hexToInt(char **ptr, int *intValue)-{- int numChars = 0;- int hexValue;-- *intValue = 0;-- while (**ptr) {- hexValue = hex(**ptr);- if (hexValue < 0)- break;-- *intValue = (*intValue << 4) | hexValue;- numChars ++;-- (*ptr)++;- }-- return (numChars);-}--static int hexToLong(char **ptr, long *longValue)-{- int numChars = 0;- int hexValue;-- *longValue = 0;-- while (**ptr) {- hexValue = hex(**ptr);- if (hexValue < 0)- break;-- *longValue = (*longValue << 4) | hexValue;- numChars ++;-- (*ptr)++;- }-- return numChars;-}---#if 0-/*- * Print registers (on target console)- * Used only to debug the stub...- */-void show_gdbregs(struct gdb_regs * regs)-{- /*- * Saved main processor registers- */- printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",- regs->reg0, regs->reg1, regs->reg2, regs->reg3,- regs->reg4, regs->reg5, regs->reg6, regs->reg7);- printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",- regs->reg8, regs->reg9, regs->reg10, regs->reg11,- regs->reg12, regs->reg13, regs->reg14, regs->reg15);- printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",- regs->reg16, regs->reg17, regs->reg18, regs->reg19,- regs->reg20, regs->reg21, regs->reg22, regs->reg23);- printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",- regs->reg24, regs->reg25, regs->reg26, regs->reg27,- regs->reg28, regs->reg29, regs->reg30, regs->reg31);-- /*- * Saved cp0 registers- */- printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n",- regs->cp0_epc, regs->cp0_status, regs->cp0_cause);-}-#endif /* dead code */--/*- * We single-step by setting breakpoints. When an exception- * is handled, we need to restore the instructions hoisted- * when the breakpoints were set.- *- * This is where we save the original instructions.- */-static struct gdb_bp_save {- unsigned long addr;- unsigned int val;-} step_bp[2];--#define BP 0x0000000d /* break opcode */--/*- * Set breakpoint instructions for single stepping.- */-static void single_step(struct gdb_regs *regs)-{- union mips_instruction insn;- unsigned long targ;- int is_branch, is_cond, i;-- targ = regs->cp0_epc;- insn.word = *(unsigned int *)targ;- is_branch = is_cond = 0;-- switch (insn.i_format.opcode) {- /*- * jr and jalr are in r_format format.- */- case spec_op:- switch (insn.r_format.func) {- case jalr_op:- case jr_op:- targ = *(®s->reg0 + insn.r_format.rs);- is_branch = 1;- break;- }- break;-- /*- * This group contains:- * bltz_op, bgez_op, bltzl_op, bgezl_op,- * bltzal_op, bgezal_op, bltzall_op, bgezall_op.- */- case bcond_op:- is_branch = is_cond = 1;- targ += 4 + (insn.i_format.simmediate << 2);- break;-- /*- * These are unconditional and in j_format.- */- case jal_op:- case j_op:- is_branch = 1;- targ += 4;- targ >>= 28;- targ <<= 28;- targ |= (insn.j_format.target << 2);- break;-- /*- * These are conditional.- */- case beq_op:- case beql_op:- case bne_op:- case bnel_op:- case blez_op:- case blezl_op:- case bgtz_op:- case bgtzl_op:- case cop0_op:- case cop1_op:- case cop2_op:- case cop1x_op:- is_branch = is_cond = 1;- targ += 4 + (insn.i_format.simmediate << 2);- break;- }-- if (is_branch) {- i = 0;- if (is_cond && targ != (regs->cp0_epc + 8)) {- step_bp[i].addr = regs->cp0_epc + 8;- step_bp[i++].val = *(unsigned *)(regs->cp0_epc + 8);- *(unsigned *)(regs->cp0_epc + 8) = BP;- }- step_bp[i].addr = targ;- step_bp[i].val = *(unsigned *)targ;- *(unsigned *)targ = BP;- } else {- step_bp[0].addr = regs->cp0_epc + 4;- step_bp[0].val = *(unsigned *)(regs->cp0_epc + 4);- *(unsigned *)(regs->cp0_epc + 4) = BP;- }-}--/*- * If asynchronously interrupted by gdb, then we need to set a breakpoint- * at the interrupted instruction so that we wind up stopped with a- * reasonable stack frame.- */-static struct gdb_bp_save async_bp;--/*- * Swap the interrupted EPC with our asynchronous breakpoint routine.- * This is safer than stuffing the breakpoint in-place, since no cache- * flushes (or resulting smp_call_functions) are required. The- * assumption is that only one CPU will be handling asynchronous bp's,- * and only one can be active at a time.- */-extern spinlock_t smp_call_lock;--void set_async_breakpoint(unsigned long *epc)-{- /* skip breaking into userland */- if ((*epc & 0x80000000) == 0)- return;--#ifdef CONFIG_SMP- /* avoid deadlock if someone is make IPC */- if (spin_is_locked(&smp_call_lock))- return;-#endif-- async_bp.addr = *epc;- *epc = (unsigned long)async_breakpoint;-}--static void kgdb_wait(void *arg)-{- unsigned flags;- int cpu = smp_processor_id();-- local_irq_save(flags);-- __raw_spin_lock(&kgdb_cpulock[cpu]);- __raw_spin_unlock(&kgdb_cpulock[cpu]);-- local_irq_restore(flags);-}---/*- * This function does all command processing for interfacing to gdb. It- * returns 1 if you should skip the instruction at the trap address, 0- * otherwise.- */-void handle_exception (struct gdb_regs *regs)-{- int trap; /* Trap type */- int sigval;- long addr;- int length;- char *ptr;- unsigned long *stack;- int i;- int bflag = 0;-- kgdb_started = 1;-- /*- * acquire the big kgdb spinlock- */- if (!spin_trylock(&kgdb_lock)) {- /*- * some other CPU has the lock, we should go back to- * receive the gdb_wait IPC- */- return;- }-- /*- * If we're in async_breakpoint(), restore the real EPC from- * the breakpoint.- */- if (regs->cp0_epc == (unsigned long)async_breakinst) {- regs->cp0_epc = async_bp.addr;- async_bp.addr = 0;- }-- /*- * acquire the CPU spinlocks- */- for (i = num_online_cpus()-1; i >= 0; i--)- if (__raw_spin_trylock(&kgdb_cpulock[i]) == 0)- panic("kgdb: couldn't get cpulock %d\n", i);-- /*- * force other cpus to enter kgdb- */- smp_call_function(kgdb_wait, NULL, 0, 0);-- /*- * If we're in breakpoint() increment the PC- */- trap = (regs->cp0_cause & 0x7c) >> 2;- if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst)- regs->cp0_epc += 4;-- /*- * If we were single_stepping, restore the opcodes hoisted- * for the breakpoint[s].- */- if (step_bp[0].addr) {- *(unsigned *)step_bp[0].addr = step_bp[0].val;- step_bp[0].addr = 0;-- if (step_bp[1].addr) {- *(unsigned *)step_bp[1].addr = step_bp[1].val;- step_bp[1].addr = 0;- }- }-- stack = (long *)regs->reg29; /* stack ptr */- sigval = computeSignal(trap);-- /*- * reply to host 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[REG_EPC >> 4];- *ptr++ = hexchars[REG_EPC & 0xf];- *ptr++ = ':';- ptr = mem2hex((char *)®s->cp0_epc, ptr, sizeof(long), 0);- *ptr++ = ';';-- /*- * Send frame pointer- */- *ptr++ = hexchars[REG_FP >> 4];- *ptr++ = hexchars[REG_FP & 0xf];- *ptr++ = ':';- ptr = mem2hex((char *)®s->reg30, ptr, sizeof(long), 0);- *ptr++ = ';';-- /*- * Send stack pointer- */- *ptr++ = hexchars[REG_SP >> 4];- *ptr++ = hexchars[REG_SP & 0xf];- *ptr++ = ':';- ptr = mem2hex((char *)®s->reg29, ptr, sizeof(long), 0);- *ptr++ = ';';-
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -