📄 kgdb.c
字号:
putpacket (remcomOutBuffer); return; case '?': /* The last signal which caused a stop. ? Success: SAA, where AA is the signal number. Failure: void. */ remcomOutBuffer[0] = 'S'; remcomOutBuffer[1] = highhex (sigval); remcomOutBuffer[2] = lowhex (sigval); remcomOutBuffer[3] = 0; break; case 'D': /* Detach from host. D Success: OK, and return to the executing thread. Failure: will never know */ putpacket ("OK"); return; case 'k': case 'r': /* kill request or reset request. Success: restart of target. Failure: will never know. */ kill_restart (); break; case 'C': case 'S': case '!': case 'R': case 'd': /* Continue with signal sig. Csig;AA..AA Step with signal sig. Ssig;AA..AA Use the extended remote protocol. ! Restart the target system. R0 Toggle debug flag. d Search backwards. tAA:PP,MM Not supported: E04 */ gdb_cris_strcpy (remcomOutBuffer, error_message[E04]); break;#ifdef PROCESS_SUPPORT case 'T': /* Thread alive. TXX Is thread XX alive? Success: OK, thread XX is alive. Failure: E03, thread XX is dead. */ { int thread_id = (int)gdb_cris_strtol (&remcomInBuffer[1], 0, 16); /* Cannot tell whether it is alive or not. */ if (thread_id >= 0 && thread_id < number_of_tasks) gdb_cris_strcpy (remcomOutBuffer, "OK"); } break; case 'H': /* Set thread for subsequent operations: Hct c = 'c' for thread used in step and continue; t can be -1 for all threads. c = 'g' for thread used in other operations. t = 0 means pick any thread. Success: OK Failure: E01 */ { int thread_id = gdb_cris_strtol (&remcomInBuffer[2], 0, 16); if (remcomInBuffer[1] == 'c') { /* c = 'c' for thread used in step and continue */ /* Do not change current_thread_c here. It would create a mess in the scheduler. */ gdb_cris_strcpy (remcomOutBuffer, "OK"); } else if (remcomInBuffer[1] == 'g') { /* c = 'g' for thread used in other operations. t = 0 means pick any thread. Impossible since the scheduler does not allow that. */ if (thread_id >= 0 && thread_id < number_of_tasks) { current_thread_g = thread_id; gdb_cris_strcpy (remcomOutBuffer, "OK"); } else { /* Not expected - send an error message. */ gdb_cris_strcpy (remcomOutBuffer, error_message[E01]); } } else { /* Not expected - send an error message. */ gdb_cris_strcpy (remcomOutBuffer, error_message[E01]); } } break; case 'q': case 'Q': /* Query of general interest. qXXXX Set general value XXXX. QXXXX=yyyy */ { int pos; int nextpos; int thread_id; switch (remcomInBuffer[1]) { case 'C': /* Identify the remote current thread. */ gdb_cris_strcpy (&remcomOutBuffer[0], "QC"); remcomOutBuffer[2] = highhex (current_thread_c); remcomOutBuffer[3] = lowhex (current_thread_c); remcomOutBuffer[4] = '\0'; break; case 'L': gdb_cris_strcpy (&remcomOutBuffer[0], "QM"); /* Reply with number of threads. */ if (os_is_started()) { remcomOutBuffer[2] = highhex (number_of_tasks); remcomOutBuffer[3] = lowhex (number_of_tasks); } else { remcomOutBuffer[2] = highhex (0); remcomOutBuffer[3] = lowhex (1); } /* Done with the reply. */ remcomOutBuffer[4] = lowhex (1); pos = 5; /* Expects the argument thread id. */ for (; pos < (5 + HEXCHARS_IN_THREAD_ID); pos++) remcomOutBuffer[pos] = remcomInBuffer[pos]; /* Reply with the thread identifiers. */ if (os_is_started()) { /* Store the thread identifiers of all tasks. */ for (thread_id = 0; thread_id < number_of_tasks; thread_id++) { nextpos = pos + HEXCHARS_IN_THREAD_ID - 1; for (; pos < nextpos; pos ++) remcomOutBuffer[pos] = lowhex (0); remcomOutBuffer[pos++] = lowhex (thread_id); } } else { /* Store the thread identifier of the boot task. */ nextpos = pos + HEXCHARS_IN_THREAD_ID - 1; for (; pos < nextpos; pos ++) remcomOutBuffer[pos] = lowhex (0); remcomOutBuffer[pos++] = lowhex (current_thread_c); } remcomOutBuffer[pos] = '\0'; break; default: /* Not supported: "" */ /* Request information about section offsets: qOffsets. */ remcomOutBuffer[0] = 0; break; } } break;#endif /* PROCESS_SUPPORT */ default: /* The stub should ignore other request and send an empty response ($#<checksum>). This way we can extend the protocol and GDB can tell whether the stub it is talking to uses the old or the new. */ remcomOutBuffer[0] = 0; break; } putpacket(remcomOutBuffer); }}/* The jump is to the address 0x00000002. Performs a complete re-start from scratch. */static voidkill_restart (){ __asm__ volatile ("jump 2");}/********************************** Breakpoint *******************************//* The hook for both a static (compiled) and a dynamic breakpoint set by GDB. An internal stack is used by the stub. The register image of the caller is stored in the structure register_image. Interactive communication with the host is handled by handle_exception and finally the register image is restored. */void kgdb_handle_breakpoint(void);asm (" .global kgdb_handle_breakpointkgdb_handle_breakpoint:;;;; Response to the break-instruction;;;; Create a register image of the caller;; move $dccr,[reg+0x5E] ; Save the flags in DCCR before disable interrupts di ; Disable interrupts move.d $r0,[reg] ; Save R0 move.d $r1,[reg+0x04] ; Save R1 move.d $r2,[reg+0x08] ; Save R2 move.d $r3,[reg+0x0C] ; Save R3 move.d $r4,[reg+0x10] ; Save R4 move.d $r5,[reg+0x14] ; Save R5 move.d $r6,[reg+0x18] ; Save R6 move.d $r7,[reg+0x1C] ; Save R7 move.d $r8,[reg+0x20] ; Save R8 move.d $r9,[reg+0x24] ; Save R9 move.d $r10,[reg+0x28] ; Save R10 move.d $r11,[reg+0x2C] ; Save R11 move.d $r12,[reg+0x30] ; Save R12 move.d $r13,[reg+0x34] ; Save R13 move.d $sp,[reg+0x38] ; Save SP (R14);; Due to the old assembler-versions BRP might not be recognized .word 0xE670 ; move brp,$r0 subq 2,$r0 ; Set to address of previous instruction. move.d $r0,[reg+0x3c] ; Save the address in PC (R15) clear.b [reg+0x40] ; Clear P0 move $vr,[reg+0x41] ; Save special register P1 clear.w [reg+0x42] ; Clear P4 move $ccr,[reg+0x44] ; Save special register CCR move $mof,[reg+0x46] ; P7 clear.d [reg+0x4A] ; Clear P8 move $ibr,[reg+0x4E] ; P9, move $irp,[reg+0x52] ; P10, move $srp,[reg+0x56] ; P11, move $dtp0,[reg+0x5A] ; P12, register BAR, assembler might not know BAR ; P13, register DCCR already saved;; Due to the old assembler-versions BRP might not be recognized .word 0xE670 ; move brp,r0;; Static (compiled) breakpoints must return to the next instruction in order;; to avoid infinite loops. Dynamic (gdb-invoked) must restore the instruction;; in order to execute it when execution is continued. test.b [is_dyn_brkp] ; Is this a dynamic breakpoint? beq is_static ; No, a static breakpoint nop subq 2,$r0 ; rerun the instruction the break replacedis_static: moveq 1,$r1 move.b $r1,[is_dyn_brkp] ; Set the state variable to dynamic breakpoint move.d $r0,[reg+0x62] ; Save the return address in BRP move $usp,[reg+0x66] ; USP;;;; Handle the communication;; move.d internal_stack+1020,$sp ; Use the internal stack which grows upward moveq 5,$r10 ; SIGTRAP jsr handle_exception ; Interactive routine;;;; Return to the caller;; move.d [reg],$r0 ; Restore R0 move.d [reg+0x04],$r1 ; Restore R1 move.d [reg+0x08],$r2 ; Restore R2 move.d [reg+0x0C],$r3 ; Restore R3 move.d [reg+0x10],$r4 ; Restore R4 move.d [reg+0x14],$r5 ; Restore R5 move.d [reg+0x18],$r6 ; Restore R6 move.d [reg+0x1C],$r7 ; Restore R7 move.d [reg+0x20],$r8 ; Restore R8 move.d [reg+0x24],$r9 ; Restore R9 move.d [reg+0x28],$r10 ; Restore R10 move.d [reg+0x2C],$r11 ; Restore R11 move.d [reg+0x30],$r12 ; Restore R12 move.d [reg+0x34],$r13 ; Restore R13;;;; FIXME: Which registers should be restored?;; move.d [reg+0x38],$sp ; Restore SP (R14) move [reg+0x56],$srp ; Restore the subroutine return pointer. move [reg+0x5E],$dccr ; Restore DCCR move [reg+0x66],$usp ; Restore USP jump [reg+0x62] ; A jump to the content in register BRP works. nop ;");/* The hook for an interrupt generated by GDB. An internal stack is used by the stub. The register image of the caller is stored in the structure register_image. Interactive communication with the host is handled by handle_exception and finally the register image is restored. Due to the old assembler which does not recognise the break instruction and the breakpoint return pointer hex-code is used. */void kgdb_handle_serial(void);asm (" .global kgdb_handle_serialkgdb_handle_serial:;;;; Response to a serial interrupt;; move $dccr,[reg+0x5E] ; Save the flags in DCCR di ; Disable interrupts move.d $r0,[reg] ; Save R0 move.d $r1,[reg+0x04] ; Save R1 move.d $r2,[reg+0x08] ; Save R2 move.d $r3,[reg+0x0C] ; Save R3 move.d $r4,[reg+0x10] ; Save R4 move.d $r5,[reg+0x14] ; Save R5 move.d $r6,[reg+0x18] ; Save R6 move.d $r7,[reg+0x1C] ; Save R7 move.d $r8,[reg+0x20] ; Save R8 move.d $r9,[reg+0x24] ; Save R9 move.d $r10,[reg+0x28] ; Save R10 move.d $r11,[reg+0x2C] ; Save R11 move.d $r12,[reg+0x30] ; Save R12 move.d $r13,[reg+0x34] ; Save R13 move.d $sp,[reg+0x38] ; Save SP (R14) move $irp,[reg+0x3c] ; Save the address in PC (R15) clear.b [reg+0x40] ; Clear P0 move $vr,[reg+0x41] ; Save special register P1, clear.w [reg+0x42] ; Clear P4 move $ccr,[reg+0x44] ; Save special register CCR move $mof,[reg+0x46] ; P7 clear.d [reg+0x4A] ; Clear P8 move $ibr,[reg+0x4E] ; P9, move $irp,[reg+0x52] ; P10, move $srp,[reg+0x56] ; P11, move $dtp0,[reg+0x5A] ; P12, register BAR, assembler might not know BAR ; P13, register DCCR already saved;; Due to the old assembler-versions BRP might not be recognized .word 0xE670 ; move brp,r0 move.d $r0,[reg+0x62] ; Save the return address in BRP move $usp,[reg+0x66] ; USP;; get the serial character (from debugport.c) and check if it is a ctrl-c jsr getDebugChar cmp.b 3, $r10 bne goback nop;;;; Handle the communication;; move.d internal_stack+1020,$sp ; Use the internal stack moveq 2,$r10 ; SIGINT jsr handle_exception ; Interactive routinegoback:;;;; Return to the caller;; move.d [reg],$r0 ; Restore R0 move.d [reg+0x04],$r1 ; Restore R1 move.d [reg+0x08],$r2 ; Restore R2 move.d [reg+0x0C],$r3 ; Restore R3 move.d [reg+0x10],$r4 ; Restore R4 move.d [reg+0x14],$r5 ; Restore R5 move.d [reg+0x18],$r6 ; Restore R6 move.d [reg+0x1C],$r7 ; Restore R7 move.d [reg+0x20],$r8 ; Restore R8 move.d [reg+0x24],$r9 ; Restore R9 move.d [reg+0x28],$r10 ; Restore R10 move.d [reg+0x2C],$r11 ; Restore R11 move.d [reg+0x30],$r12 ; Restore R12 move.d [reg+0x34],$r13 ; Restore R13;;;; FIXME: Which registers should be restored?;; move.d [reg+0x38],$sp ; Restore SP (R14) move [reg+0x56],$srp ; Restore the subroutine return pointer. move [reg+0x5E],$dccr ; Restore DCCR move [reg+0x66],$usp ; Restore USP reti ; Return from the interrupt routine nop");/* Use this static breakpoint in the start-up only. */voidbreakpoint(void){ kgdb_started = 1; is_dyn_brkp = 0; /* This is a static, not a dynamic breakpoint. */ __asm__ volatile ("break 8"); /* Jump to handle_breakpoint. */}/* initialize kgdb. doesn't break into the debugger, but sets up irq and ports */voidkgdb_init(void){ /* could initialize debug port as well but it's done in head.S already... */ /* breakpoint handler is now set in irq.c */ set_int_vector(8, kgdb_handle_serial, 0); enableDebugIRQ();}/****************************** End of file **********************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -