Home | History | Annotate | Download | only in cmd
      1 /*
      2  * BedBug Functions
      3  */
      4 
      5 #include <common.h>
      6 #include <cli.h>
      7 #include <command.h>
      8 #include <console.h>
      9 #include <linux/ctype.h>
     10 #include <net.h>
     11 #include <bedbug/type.h>
     12 #include <bedbug/bedbug.h>
     13 #include <bedbug/regs.h>
     14 #include <bedbug/ppc.h>
     15 
     16 DECLARE_GLOBAL_DATA_PTR;
     17 
     18 extern void show_regs __P ((struct pt_regs *));
     19 extern int run_command __P ((const char *, int));
     20 
     21 ulong dis_last_addr = 0;	/* Last address disassembled   */
     22 ulong dis_last_len = 20;	/* Default disassembler length */
     23 CPU_DEBUG_CTX bug_ctx;		/* Bedbug context structure    */
     24 
     25 
     26 /* ======================================================================
     27  * U-Boot's puts function does not append a newline, so the bedbug stuff
     28  * will use this for the output of the dis/assembler.
     29  * ====================================================================== */
     30 
     31 int bedbug_puts (const char *str)
     32 {
     33 	/* -------------------------------------------------- */
     34 
     35 	printf ("%s\r\n", str);
     36 	return 0;
     37 }				/* bedbug_puts */
     38 
     39 
     40 
     41 /* ======================================================================
     42  * Initialize the bug_ctx structure used by the bedbug debugger.  This is
     43  * specific to the CPU since each has different debug registers and
     44  * settings.
     45  * ====================================================================== */
     46 
     47 void bedbug_init (void)
     48 {
     49 	/* -------------------------------------------------- */
     50 	return;
     51 }				/* bedbug_init */
     52 
     53 
     54 
     55 /* ======================================================================
     56  * Entry point from the interpreter to the disassembler.  Repeated calls
     57  * will resume from the last disassembled address.
     58  * ====================================================================== */
     59 int do_bedbug_dis (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
     60 {
     61 	ulong addr;		/* Address to start disassembly from    */
     62 	ulong len;		/* # of instructions to disassemble     */
     63 
     64 	/* -------------------------------------------------- */
     65 
     66 	/* Setup to go from the last address if none is given */
     67 	addr = dis_last_addr;
     68 	len = dis_last_len;
     69 
     70 	if (argc < 2)
     71 		return CMD_RET_USAGE;
     72 
     73 	if ((flag & CMD_FLAG_REPEAT) == 0) {
     74 		/* New command */
     75 		addr = simple_strtoul (argv[1], NULL, 16);
     76 
     77 		/* If an extra param is given then it is the length */
     78 		if (argc > 2)
     79 			len = simple_strtoul (argv[2], NULL, 16);
     80 	}
     81 
     82 	/* Run the disassembler */
     83 	disppc ((unsigned char *) addr, 0, len, bedbug_puts, F_RADHEX);
     84 
     85 	dis_last_addr = addr + (len * 4);
     86 	dis_last_len = len;
     87 	return 0;
     88 }				/* do_bedbug_dis */
     89 
     90 U_BOOT_CMD (ds, 3, 1, do_bedbug_dis,
     91 	    "disassemble memory",
     92 	    "ds <address> [# instructions]");
     93 
     94 /* ======================================================================
     95  * Entry point from the interpreter to the assembler.  Assembles
     96  * instructions in consecutive memory locations until a '.' (period) is
     97  * entered on a line by itself.
     98  * ====================================================================== */
     99 int do_bedbug_asm (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
    100 {
    101 	long mem_addr;		/* Address to assemble into     */
    102 	unsigned long instr;	/* Machine code for text        */
    103 	char prompt[15];	/* Prompt string for user input */
    104 	int asm_err;		/* Error code from the assembler */
    105 
    106 	/* -------------------------------------------------- */
    107 	int rcode = 0;
    108 
    109 	if (argc < 2)
    110 		return CMD_RET_USAGE;
    111 
    112 	printf ("\nEnter '.' when done\n");
    113 	mem_addr = simple_strtoul (argv[1], NULL, 16);
    114 
    115 	while (1) {
    116 		putc ('\n');
    117 		disppc ((unsigned char *) mem_addr, 0, 1, bedbug_puts,
    118 			F_RADHEX);
    119 
    120 		sprintf (prompt, "%08lx:    ", mem_addr);
    121 		cli_readline(prompt);
    122 
    123 		if (console_buffer[0] && strcmp (console_buffer, ".")) {
    124 			if ((instr =
    125 			     asmppc (mem_addr, console_buffer,
    126 				     &asm_err)) != 0) {
    127 				*(unsigned long *) mem_addr = instr;
    128 				mem_addr += 4;
    129 			} else {
    130 				printf ("*** Error: %s ***\n",
    131 					asm_error_str (asm_err));
    132 				rcode = 1;
    133 			}
    134 		} else {
    135 			break;
    136 		}
    137 	}
    138 	return rcode;
    139 }				/* do_bedbug_asm */
    140 
    141 U_BOOT_CMD (as, 2, 0, do_bedbug_asm,
    142 	    "assemble memory", "as <address>");
    143 
    144 /* ======================================================================
    145  * Used to set a break point from the interpreter.  Simply calls into the
    146  * CPU-specific break point set routine.
    147  * ====================================================================== */
    148 
    149 int do_bedbug_break (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
    150 {
    151 	/* -------------------------------------------------- */
    152 	if (bug_ctx.do_break)
    153 		(*bug_ctx.do_break) (cmdtp, flag, argc, argv);
    154 	return 0;
    155 
    156 }				/* do_bedbug_break */
    157 
    158 U_BOOT_CMD (break, 3, 0, do_bedbug_break,
    159 	    "set or clear a breakpoint",
    160 	    " - Set or clear a breakpoint\n"
    161 	    "break <address> - Break at an address\n"
    162 	    "break off <bp#> - Disable breakpoint.\n"
    163 	    "break show      - List breakpoints.");
    164 
    165 /* ======================================================================
    166  * Called from the debug interrupt routine.  Simply calls the CPU-specific
    167  * breakpoint handling routine.
    168  * ====================================================================== */
    169 
    170 void do_bedbug_breakpoint (struct pt_regs *regs)
    171 {
    172 	/* -------------------------------------------------- */
    173 
    174 	if (bug_ctx.break_isr)
    175 		(*bug_ctx.break_isr) (regs);
    176 
    177 	return;
    178 }				/* do_bedbug_breakpoint */
    179 
    180 
    181 
    182 /* ======================================================================
    183  * Called from the CPU-specific breakpoint handling routine.  Enter a
    184  * mini main loop until the stopped flag is cleared from the breakpoint
    185  * context.
    186  *
    187  * This handles the parts of the debugger that are common to all CPU's.
    188  * ====================================================================== */
    189 
    190 void bedbug_main_loop (unsigned long addr, struct pt_regs *regs)
    191 {
    192 	int len;		/* Length of command line */
    193 	int flag;		/* Command flags          */
    194 	int rc = 0;		/* Result from run_command */
    195 	char prompt_str[20];	/* Prompt string          */
    196 	static char lastcommand[CONFIG_SYS_CBSIZE] = { 0 };	/* previous command */
    197 	/* -------------------------------------------------- */
    198 
    199 	if (bug_ctx.clear)
    200 		(*bug_ctx.clear) (bug_ctx.current_bp);
    201 
    202 	printf ("Breakpoint %d: ", bug_ctx.current_bp);
    203 	disppc ((unsigned char *) addr, 0, 1, bedbug_puts, F_RADHEX);
    204 
    205 	bug_ctx.stopped = 1;
    206 	bug_ctx.regs = regs;
    207 
    208 	sprintf (prompt_str, "BEDBUG.%d =>", bug_ctx.current_bp);
    209 
    210 	/* A miniature main loop */
    211 	while (bug_ctx.stopped) {
    212 		len = cli_readline(prompt_str);
    213 
    214 		flag = 0;	/* assume no special flags for now */
    215 
    216 		if (len > 0)
    217 			strcpy (lastcommand, console_buffer);
    218 		else if (len == 0)
    219 			flag |= CMD_FLAG_REPEAT;
    220 
    221 		if (len == -1)
    222 			printf ("<INTERRUPT>\n");
    223 		else
    224 			rc = run_command_repeatable(lastcommand, flag);
    225 
    226 		if (rc <= 0) {
    227 			/* invalid command or not repeatable, forget it */
    228 			lastcommand[0] = 0;
    229 		}
    230 	}
    231 
    232 	bug_ctx.regs = NULL;
    233 	bug_ctx.current_bp = 0;
    234 
    235 	return;
    236 }				/* bedbug_main_loop */
    237 
    238 
    239 
    240 /* ======================================================================
    241  * Interpreter command to continue from a breakpoint.  Just clears the
    242  * stopped flag in the context so that the breakpoint routine will
    243  * return.
    244  * ====================================================================== */
    245 int do_bedbug_continue (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
    246 {
    247 	/* -------------------------------------------------- */
    248 
    249 	if (!bug_ctx.stopped) {
    250 		printf ("Not at a breakpoint\n");
    251 		return 1;
    252 	}
    253 
    254 	bug_ctx.stopped = 0;
    255 	return 0;
    256 }				/* do_bedbug_continue */
    257 
    258 U_BOOT_CMD (continue, 1, 0, do_bedbug_continue,
    259 	    "continue from a breakpoint",
    260 	    "");
    261 
    262 /* ======================================================================
    263  * Interpreter command to continue to the next instruction, stepping into
    264  * subroutines.  Works by calling the find_next_addr() routine to compute
    265  * the address passes control to the CPU-specific set breakpoint routine
    266  * for the current breakpoint number.
    267  * ====================================================================== */
    268 int do_bedbug_step (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
    269 {
    270 	unsigned long addr;	/* Address to stop at */
    271 
    272 	/* -------------------------------------------------- */
    273 
    274 	if (!bug_ctx.stopped) {
    275 		printf ("Not at a breakpoint\n");
    276 		return 1;
    277 	}
    278 
    279 	if (!find_next_address((unsigned char *) &addr, false, bug_ctx.regs))
    280 		return 1;
    281 
    282 	if (bug_ctx.set)
    283 		(*bug_ctx.set) (bug_ctx.current_bp, addr);
    284 
    285 	bug_ctx.stopped = 0;
    286 	return 0;
    287 }				/* do_bedbug_step */
    288 
    289 U_BOOT_CMD (step, 1, 1, do_bedbug_step,
    290 	    "single step execution.",
    291 	    "");
    292 
    293 /* ======================================================================
    294  * Interpreter command to continue to the next instruction, stepping over
    295  * subroutines.  Works by calling the find_next_addr() routine to compute
    296  * the address passes control to the CPU-specific set breakpoint routine
    297  * for the current breakpoint number.
    298  * ====================================================================== */
    299 int do_bedbug_next (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
    300 {
    301 	unsigned long addr;	/* Address to stop at */
    302 
    303 	/* -------------------------------------------------- */
    304 
    305 	if (!bug_ctx.stopped) {
    306 		printf ("Not at a breakpoint\n");
    307 		return 1;
    308 	}
    309 
    310 	if (!find_next_address((unsigned char *) &addr, true, bug_ctx.regs))
    311 		return 1;
    312 
    313 	if (bug_ctx.set)
    314 		(*bug_ctx.set) (bug_ctx.current_bp, addr);
    315 
    316 	bug_ctx.stopped = 0;
    317 	return 0;
    318 }				/* do_bedbug_next */
    319 
    320 U_BOOT_CMD (next, 1, 1, do_bedbug_next,
    321 	    "single step execution, stepping over subroutines.",
    322 	    "");
    323 
    324 /* ======================================================================
    325  * Interpreter command to print the current stack.  This assumes an EABI
    326  * architecture, so it starts with GPR R1 and works back up the stack.
    327  * ====================================================================== */
    328 int do_bedbug_stack (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
    329 {
    330 	unsigned long sp;	/* Stack pointer                */
    331 	unsigned long func;	/* LR from stack                */
    332 	int depth;		/* Stack iteration level        */
    333 	int skip = 1;		/* Flag to skip the first entry */
    334 	unsigned long top;	/* Top of memory address        */
    335 
    336 	/* -------------------------------------------------- */
    337 
    338 	if (!bug_ctx.stopped) {
    339 		printf ("Not at a breakpoint\n");
    340 		return 1;
    341 	}
    342 
    343 	top = gd->bd->bi_memstart + gd->bd->bi_memsize;
    344 	depth = 0;
    345 
    346 	printf ("Depth     PC\n");
    347 	printf ("-----  --------\n");
    348 	printf ("%5d  %08lx\n", depth++, bug_ctx.regs->nip);
    349 
    350 	sp = bug_ctx.regs->gpr[1];
    351 	func = *(unsigned long *) (sp + 4);
    352 
    353 	while ((func < top) && (sp < top)) {
    354 		if (!skip)
    355 			printf ("%5d  %08lx\n", depth++, func);
    356 		else
    357 			--skip;
    358 
    359 		sp = *(unsigned long *) sp;
    360 		func = *(unsigned long *) (sp + 4);
    361 	}
    362 	return 0;
    363 }				/* do_bedbug_stack */
    364 
    365 U_BOOT_CMD (where, 1, 1, do_bedbug_stack,
    366 	    "Print the running stack.",
    367 	    "");
    368 
    369 /* ======================================================================
    370  * Interpreter command to dump the registers.  Calls the CPU-specific
    371  * show registers routine.
    372  * ====================================================================== */
    373 int do_bedbug_rdump (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
    374 {
    375 	/* -------------------------------------------------- */
    376 
    377 	if (!bug_ctx.stopped) {
    378 		printf ("Not at a breakpoint\n");
    379 		return 1;
    380 	}
    381 
    382 	show_regs (bug_ctx.regs);
    383 	return 0;
    384 }				/* do_bedbug_rdump */
    385 
    386 U_BOOT_CMD (rdump, 1, 1, do_bedbug_rdump,
    387 	    "Show registers.", "");
    388 /* ====================================================================== */
    389 
    390 
    391 /*
    392  * Copyright (c) 2001 William L. Pitts
    393  * All rights reserved.
    394  *
    395  * Redistribution and use in source and binary forms are freely
    396  * permitted provided that the above copyright notice and this
    397  * paragraph and the following disclaimer are duplicated in all
    398  * such forms.
    399  *
    400  * This software is provided "AS IS" and without any express or
    401  * implied warranties, including, without limitation, the implied
    402  * warranties of merchantability and fitness for a particular
    403  * purpose.
    404  */
    405