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