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