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