📄 kgdb.c
字号:
/* * arch/cris/arch-v32/kernel/kgdb.c * * CRIS v32 version by Orjan Friberg, Axis Communications AB. * * S390 version * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), * * Originally written by Glenn Engel, Lake Stevens Instrument Division * * Contributed by HP Systems * * Modified for SPARC by Stu Grossman, Cygnus Support. * * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de> * * Copyright (C) 1995 Andreas Busse *//* FIXME: Check the documentation. *//* * kgdb usage notes: * ----------------- * * If you select CONFIG_ETRAX_KGDB in the configuration, the kernel will be * built with different gcc flags: "-g" is added to get debug infos, and * "-fomit-frame-pointer" is omitted to make debugging easier. Since the * resulting kernel will be quite big (approx. > 7 MB), it will be stripped * before compresion. Such a kernel will behave just as usually, except if * given a "debug=<device>" command line option. (Only serial devices are * allowed for <device>, i.e. no printers or the like; possible values are * machine depedend and are the same as for the usual debug device, the one * for logging kernel messages.) If that option is given and the device can be * initialized, the kernel will connect to the remote gdb in trap_init(). The * serial parameters are fixed to 8N1 and 115200 bps, for easyness of * implementation. * * To start a debugging session, start that gdb with the debugging kernel * image (the one with the symbols, vmlinux.debug) named on the command line. * This file will be used by gdb to get symbol and debugging infos about the * kernel. Next, select remote debug mode by * target remote <device> * where <device> is the name of the serial device over which the debugged * machine is connected. Maybe you have to adjust the baud rate by * set remotebaud <rate> * or also other parameters with stty: * shell stty ... </dev/... * If the kernel to debug has already booted, it waited for gdb and now * connects, and you'll see a breakpoint being reported. If the kernel isn't * running yet, start it now. The order of gdb and the kernel doesn't matter. * Another thing worth knowing about in the getting-started phase is how to * debug the remote protocol itself. This is activated with * set remotedebug 1 * gdb will then print out each packet sent or received. You'll also get some * messages about the gdb stub on the console of the debugged machine. * * If all that works, you can use lots of the usual debugging techniques on * the kernel, e.g. inspecting and changing variables/memory, setting * breakpoints, single stepping and so on. It's also possible to interrupt the * debugged kernel by pressing C-c in gdb. Have fun! :-) * * The gdb stub is entered (and thus the remote gdb gets control) in the * following situations: * * - If breakpoint() is called. This is just after kgdb initialization, or if * a breakpoint() call has been put somewhere into the kernel source. * (Breakpoints can of course also be set the usual way in gdb.) * In eLinux, we call breakpoint() in init/main.c after IRQ initialization. * * - If there is a kernel exception, i.e. bad_super_trap() or die_if_kernel() * are entered. All the CPU exceptions are mapped to (more or less..., see * the hard_trap_info array below) appropriate signal, which are reported * to gdb. die_if_kernel() is usually called after some kind of access * error and thus is reported as SIGSEGV. * * - When panic() is called. This is reported as SIGABRT. * * - If C-c is received over the serial line, which is treated as * SIGINT. * * Of course, all these signals are just faked for gdb, since there is no * signal concept as such for the kernel. It also isn't possible --obviously-- * to set signal handlers from inside gdb, or restart the kernel with a * signal. * * Current limitations: * * - While the kernel is stopped, interrupts are disabled for safety reasons * (i.e., variables not changing magically or the like). But this also * means that the clock isn't running anymore, and that interrupts from the * hardware may get lost/not be served in time. This can cause some device * errors... * * - When single-stepping, only one instruction of the current thread is * executed, but interrupts are allowed for that time and will be serviced * if pending. Be prepared for that. * * - All debugging happens in kernel virtual address space. There's no way to * access physical memory not mapped in kernel space, or to access user * space. A way to work around this is using get_user_long & Co. in gdb * expressions, but only for the current process. * * - Interrupting the kernel only works if interrupts are currently allowed, * and the interrupt of the serial line isn't blocked by some other means * (IPL too high, disabled, ...) * * - The gdb stub is currently not reentrant, i.e. errors that happen therein * (e.g. accessing invalid memory) may not be caught correctly. This could * be removed in future by introducing a stack of struct registers. * *//* * To enable debugger support, two things need to happen. One, a * call to kgdb_init() is necessary in order to allow any breakpoints * or error conditions to be properly intercepted and reported to gdb. * Two, a breakpoint needs to be generated to begin communication. This * is most easily accomplished by a call to breakpoint(). * * The following gdb commands are supported: * * command function Return value * * g return the value of the CPU registers hex data or ENN * G set the value of the CPU registers OK or ENN * * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN * * c Resume at current address SNN ( signal NN) * cAA..AA Continue at address AA..AA SNN * * s Step one instruction SNN * sAA..AA Step one instruction from AA..AA SNN * * k kill * * ? What was the last sigval ? SNN (signal NN) * * bBB..BB Set baud rate to BB..BB OK or BNN, then sets * baud rate * * All commands and responses are sent with a packet which includes a * checksum. A packet consists of * * $<packet info>#<checksum>. * * where * <packet info> :: <characters representing the command or response> * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> * * When a packet is received, it is first acknowledged with either '+' or '-'. * '+' indicates a successful transfer. '-' indicates a failed transfer. * * Example: * * Host: Reply: * $m0,10#2a +$00010203040506070809101112131415#42 * */#include <linux/string.h>#include <linux/signal.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/linkage.h>#include <linux/reboot.h>#include <asm/setup.h>#include <asm/ptrace.h>#include <asm/irq.h>#include <asm/arch/hwregs/reg_map.h>#include <asm/arch/hwregs/reg_rdwr.h>#include <asm/arch/hwregs/intr_vect_defs.h>#include <asm/arch/hwregs/ser_defs.h>/* From entry.S. */extern void gdb_handle_exception(void);/* From kgdb_asm.S. */extern void kgdb_handle_exception(void);static int kgdb_started = 0;/********************************* Register image ****************************/typedefstruct register_image{ /* Offset */ unsigned int r0; /* 0x00 */ unsigned int r1; /* 0x04 */ unsigned int r2; /* 0x08 */ unsigned int r3; /* 0x0C */ unsigned int r4; /* 0x10 */ unsigned int r5; /* 0x14 */ unsigned int r6; /* 0x18 */ unsigned int r7; /* 0x1C */ unsigned int r8; /* 0x20; Frame pointer (if any) */ unsigned int r9; /* 0x24 */ unsigned int r10; /* 0x28 */ unsigned int r11; /* 0x2C */ unsigned int r12; /* 0x30 */ unsigned int r13; /* 0x34 */ unsigned int sp; /* 0x38; R14, Stack pointer */ unsigned int acr; /* 0x3C; R15, Address calculation register. */ unsigned char bz; /* 0x40; P0, 8-bit zero register */ unsigned char vr; /* 0x41; P1, Version register (8-bit) */ unsigned int pid; /* 0x42; P2, Process ID */ unsigned char srs; /* 0x46; P3, Support register select (8-bit) */ unsigned short wz; /* 0x47; P4, 16-bit zero register */ unsigned int exs; /* 0x49; P5, Exception status */ unsigned int eda; /* 0x4D; P6, Exception data address */ unsigned int mof; /* 0x51; P7, Multiply overflow register */ unsigned int dz; /* 0x55; P8, 32-bit zero register */ unsigned int ebp; /* 0x59; P9, Exception base pointer */ unsigned int erp; /* 0x5D; P10, Exception return pointer. Contains the PC we are interested in. */ unsigned int srp; /* 0x61; P11, Subroutine return pointer */ unsigned int nrp; /* 0x65; P12, NMI return pointer */ unsigned int ccs; /* 0x69; P13, Condition code stack */ unsigned int usp; /* 0x6D; P14, User mode stack pointer */ unsigned int spc; /* 0x71; P15, Single step PC */ unsigned int pc; /* 0x75; Pseudo register (for the most part set to ERP). */} registers;typedefstruct bp_register_image{ /* Support register bank 0. */ unsigned int s0_0; unsigned int s1_0; unsigned int s2_0; unsigned int s3_0; unsigned int s4_0; unsigned int s5_0; unsigned int s6_0; unsigned int s7_0; unsigned int s8_0; unsigned int s9_0; unsigned int s10_0; unsigned int s11_0; unsigned int s12_0; unsigned int s13_0; unsigned int s14_0; unsigned int s15_0; /* Support register bank 1. */ unsigned int s0_1; unsigned int s1_1; unsigned int s2_1; unsigned int s3_1; unsigned int s4_1; unsigned int s5_1; unsigned int s6_1; unsigned int s7_1; unsigned int s8_1; unsigned int s9_1; unsigned int s10_1; unsigned int s11_1; unsigned int s12_1; unsigned int s13_1; unsigned int s14_1; unsigned int s15_1; /* Support register bank 2. */ unsigned int s0_2; unsigned int s1_2; unsigned int s2_2; unsigned int s3_2; unsigned int s4_2; unsigned int s5_2; unsigned int s6_2; unsigned int s7_2; unsigned int s8_2; unsigned int s9_2; unsigned int s10_2; unsigned int s11_2; unsigned int s12_2; unsigned int s13_2; unsigned int s14_2; unsigned int s15_2; /* Support register bank 3. */ unsigned int s0_3; /* BP_CTRL */ unsigned int s1_3; /* BP_I0_START */ unsigned int s2_3; /* BP_I0_END */ unsigned int s3_3; /* BP_D0_START */ unsigned int s4_3; /* BP_D0_END */ unsigned int s5_3; /* BP_D1_START */ unsigned int s6_3; /* BP_D1_END */ unsigned int s7_3; /* BP_D2_START */ unsigned int s8_3; /* BP_D2_END */ unsigned int s9_3; /* BP_D3_START */ unsigned int s10_3; /* BP_D3_END */ unsigned int s11_3; /* BP_D4_START */ unsigned int s12_3; /* BP_D4_END */ unsigned int s13_3; /* BP_D5_START */ unsigned int s14_3; /* BP_D5_END */ unsigned int s15_3; /* BP_RESERVED */} support_registers;enum register_name{ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, SP, ACR, BZ, VR, PID, SRS, WZ, EXS, EDA, MOF, DZ, EBP, ERP, SRP, NRP, CCS, USP, SPC, PC, S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15};/* The register sizes of the registers in register_name. An unimplemented register is designated by size 0 in this array. */static int register_size[] ={ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 1, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};/* Contains the register image of the kernel. (Global so that they can be reached from assembler code.) */registers reg;support_registers sreg;/************** Prototypes for local library functions ***********************//* Copy of strcpy from libc. */static char *gdb_cris_strcpy(char *s1, const char *s2);/* Copy of strlen from libc. */static int gdb_cris_strlen(const char *s);/* Copy of memchr from libc. */static void *gdb_cris_memchr(const void *s, int c, int n);/* Copy of strtol from libc. Does only support base 16. */static int gdb_cris_strtol(const char *s, char **endptr, int base);/********************** Prototypes for local functions. **********************//* Write a value to a specified register regno in the register image of the current thread. */static int write_register(int regno, char *val);/* Read a value from a specified register in the register image. Returns the status of the read operation. The register value is returned in valptr. */static int read_register(char regno, unsigned int *valptr);/* Serial port, reads one character. ETRAX 100 specific. from debugport.c */int getDebugChar(void);#ifdef CONFIG_ETRAXFS_SIMint getDebugChar(void){ return socketread();}#endif/* Serial port, writes one character. ETRAX 100 specific. from debugport.c */void putDebugChar(int val);#ifdef CONFIG_ETRAXFS_SIMvoid putDebugChar(int val){ socketwrite((char *)&val, 1);}#endif/* Returns the character equivalent of a nibble, bit 7, 6, 5, and 4 of a byte, represented by int x. */static char highhex(int x);/* Returns the character equivalent of a nibble, bit 3, 2, 1, and 0 of a byte, represented by int x. */static char lowhex(int x);/* Returns the integer equivalent of a hexadecimal character. */static int hex(char ch);/* Convert the memory, pointed to by mem into hexadecimal representation. Put the result in buf, and return a pointer to the last character in buf (null). */static char *mem2hex(char *buf, unsigned char *mem, int count);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -