linux-old/arch/ppc/xmon/xmon.c
<<
>>
Prefs
   1/*
   2 * Routines providing a simple monitor for use on the PowerMac.
   3 *
   4 * Copyright (C) 1996 Paul Mackerras.
   5 */
   6#include <linux/errno.h>
   7#include <linux/sched.h>
   8#include <asm/ptrace.h>
   9#include <asm/string.h>
  10#include "nonstdio.h"
  11#include "privinst.h"
  12
  13#define scanhex xmon_scanhex
  14#define skipbl  xmon_skipbl
  15
  16static unsigned adrs;
  17static int size = 1;
  18static unsigned ndump = 64;
  19static unsigned nidump = 16;
  20static int termch;
  21
  22static u_int bus_error_jmp[100];
  23#define setjmp xmon_setjmp
  24#define longjmp xmon_longjmp
  25
  26/* Breakpoint stuff */
  27struct bpt {
  28        unsigned address;
  29        unsigned instr;
  30        unsigned count;
  31        unsigned char enabled;
  32};
  33
  34#define NBPTS   16
  35static struct bpt bpts[NBPTS];
  36static struct bpt dabr;
  37static struct bpt iabr;
  38static unsigned bpinstr = 0x7fe00008;   /* trap */
  39
  40/* Prototypes */
  41extern void (*debugger_fault_handler)(struct pt_regs *);
  42static int cmds(struct pt_regs *);
  43static int mread(unsigned, void *, int);
  44static int mwrite(unsigned, void *, int);
  45static void handle_fault(struct pt_regs *);
  46static void byterev(unsigned char *, int);
  47static void memex(void);
  48static int bsesc(void);
  49static void dump(void);
  50static void prdump(unsigned, int);
  51#ifdef __MWERKS__
  52static void prndump(unsigned, int);
  53static int nvreadb(unsigned);
  54#endif
  55static int ppc_inst_dump(unsigned, int);
  56void print_address(unsigned);
  57static int getsp(void);
  58static void dump_hash_table(void);
  59static void backtrace(struct pt_regs *);
  60static void excprint(struct pt_regs *);
  61static void prregs(struct pt_regs *);
  62static void memops(int);
  63static void memlocate(void);
  64static void memzcan(void);
  65static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
  66int skipbl(void);
  67int scanhex(unsigned *valp);
  68static void scannl(void);
  69static int hexdigit(int);
  70void getstring(char *, int);
  71static void flush_input(void);
  72static int inchar(void);
  73static void take_input(char *);
  74/* static void openforth(void); */
  75static unsigned read_spr(int);
  76static void write_spr(int, unsigned);
  77static void super_regs(void);
  78static void remove_bpts(void);
  79static void insert_bpts(void);
  80static struct bpt *at_breakpoint(unsigned pc);
  81static void bpt_cmds(void);
  82
  83extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
  84extern void printf(const char *fmt, ...);
  85extern int putchar(int ch);
  86extern int setjmp(u_int *);
  87extern void longjmp(u_int *, int);
  88
  89#define GETWORD(v)      (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
  90
  91static char *help_string = "\
  92Commands:\n\
  93  d     dump bytes\n\
  94  di    dump instructions\n\
  95  df    dump float values\n\
  96  dd    dump double values\n\
  97  e     print exception information\n\
  98  h     dump hash table\n\
  99  m     examine/change memory\n\
 100  mm    move a block of memory\n\
 101  ms    set a block of memory\n\
 102  md    compare two blocks of memory\n\
 103  r     print registers\n\
 104  S     print special registers\n\
 105  t     print backtrace\n\
 106  x     exit monitor\n\
 107";
 108
 109static int xmon_trace;
 110#define SSTEP   1               /* stepping because of 's' command */
 111#define BRSTEP  2               /* stepping over breakpoint */
 112
 113void
 114xmon(struct pt_regs *excp)
 115{
 116        struct pt_regs regs;
 117        int msr, cmd;
 118
 119        printk("Entering xmon kernel debugger.\n");
 120        
 121        if (excp == NULL) {
 122                asm volatile ("stw      0,0(%0)\n\
 123                        lwz     0,0(1)\n\
 124                        stw     0,4(%0)\n\
 125                        stmw    2,8(%0)" : : "b" (&regs));
 126                regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
 127                regs.msr = get_msr();
 128                regs.ctr = get_ctr();
 129                regs.xer = get_xer();
 130                regs.ccr = get_cr();
 131                regs.trap = 0;
 132                excp = &regs;
 133        }
 134
 135        msr = get_msr();
 136        set_msr(msr & ~0x8000); /* disable interrupts */
 137        remove_bpts();
 138        excprint(excp);
 139        cmd = cmds(excp);
 140        if (cmd == 's') {
 141                xmon_trace = SSTEP;
 142                excp->msr |= 0x400;
 143        } else if (at_breakpoint(excp->nip)) {
 144                xmon_trace = BRSTEP;
 145                excp->msr |= 0x400;
 146        } else {
 147                xmon_trace = 0;
 148                insert_bpts();
 149        }
 150        set_msr(msr);           /* restore interrupt enable */
 151}
 152
 153void
 154xmon_irq(int irq, void *d, struct pt_regs *regs)
 155{
 156        printf("Keyboard interrupt\n");
 157        xmon(regs);
 158}
 159
 160int
 161xmon_bpt(struct pt_regs *regs)
 162{
 163        struct bpt *bp;
 164
 165        bp = at_breakpoint(regs->nip);
 166        if (!bp)
 167                return 0;
 168        if (bp->count) {
 169                --bp->count;
 170                remove_bpts();
 171                excprint(regs);
 172                xmon_trace = BRSTEP;
 173                regs->msr |= 0x400;
 174        } else {
 175                xmon(regs);
 176        }
 177        return 1;
 178}
 179
 180int
 181xmon_sstep(struct pt_regs *regs)
 182{
 183        if (!xmon_trace)
 184                return 0;
 185        if (xmon_trace == BRSTEP) {
 186                xmon_trace = 0;
 187                insert_bpts();
 188        } else {
 189                xmon(regs);
 190        }
 191        return 1;
 192}
 193
 194int
 195xmon_dabr_match(struct pt_regs *regs)
 196{
 197        if (dabr.enabled && dabr.count) {
 198                --dabr.count;
 199                remove_bpts();
 200                excprint(regs);
 201                xmon_trace = BRSTEP;
 202                regs->msr |= 0x400;
 203        } else {
 204                dabr.instr = regs->nip;
 205                xmon(regs);
 206        }
 207        return 1;
 208}
 209
 210int
 211xmon_iabr_match(struct pt_regs *regs)
 212{
 213        if (iabr.enabled && iabr.count) {
 214                --iabr.count;
 215                remove_bpts();
 216                excprint(regs);
 217                xmon_trace = BRSTEP;
 218                regs->msr |= 0x400;
 219        } else {
 220                xmon(regs);
 221        }
 222        return 1;
 223}
 224
 225static struct bpt *
 226at_breakpoint(unsigned pc)
 227{
 228        int i;
 229        struct bpt *bp;
 230
 231        if (dabr.enabled && pc == dabr.instr)
 232                return &dabr;
 233        if (iabr.enabled && pc == iabr.address)
 234                return &iabr;
 235        bp = bpts;
 236        for (i = 0; i < NBPTS; ++i, ++bp)
 237                if (bp->enabled && pc == bp->address)
 238                        return bp;
 239        return 0;
 240}
 241
 242static void
 243insert_bpts()
 244{
 245        int i;
 246        struct bpt *bp;
 247
 248        bp = bpts;
 249        for (i = 0; i < NBPTS; ++i, ++bp) {
 250                if (!bp->enabled)
 251                        continue;
 252                if (mread(bp->address, &bp->instr, 4) != 4
 253                    || mwrite(bp->address, &bpinstr, 4) != 4) {
 254                        printf("Couldn't insert breakpoint at %x, disabling\n",
 255                               bp->address);
 256                        bp->enabled = 0;
 257                }
 258        }
 259        if (dabr.enabled)
 260                set_dabr(dabr.address);
 261        if (iabr.enabled)
 262                set_iabr(iabr.address);
 263}
 264
 265static void
 266remove_bpts()
 267{
 268        int i;
 269        struct bpt *bp;
 270        unsigned instr;
 271
 272        set_dabr(0);
 273        set_iabr(0);
 274        bp = bpts;
 275        for (i = 0; i < NBPTS; ++i, ++bp) {
 276                if (!bp->enabled)
 277                        continue;
 278                if (mread(bp->address, &instr, 4) == 4
 279                    && instr == bpinstr
 280                    && mwrite(bp->address, &bp->instr, 4) != 4)
 281                        printf("Couldn't remove breakpoint at %x\n",
 282                               bp->address);
 283        }
 284}
 285
 286static char *last_cmd;
 287
 288/* Command interpreting routine */
 289static int
 290cmds(struct pt_regs *excp)
 291{
 292        int cmd;
 293
 294        last_cmd = NULL;
 295        for(;;) {
 296                printf("mon> ");
 297                fflush(stdout);
 298                flush_input();
 299                termch = 0;
 300                cmd = skipbl();
 301                if( cmd == '\n' ) {
 302                        if (last_cmd == NULL)
 303                                continue;
 304                        take_input(last_cmd);
 305                        last_cmd = NULL;
 306                        cmd = inchar();
 307                }
 308                switch (cmd) {
 309                case 'm':
 310                        cmd = inchar();
 311                        switch (cmd) {
 312                        case 'm':
 313                        case 's':
 314                        case 'd':
 315                                memops(cmd);
 316                                break;
 317                        case 'l':
 318                                memlocate();
 319                                break;
 320                        case 'z':
 321                                memzcan();
 322                                break;
 323                        default:
 324                                termch = cmd;
 325                                memex();
 326                        }
 327                        break;
 328                case 'd':
 329                        dump();
 330                        break;
 331                case 'r':
 332                        if (excp != NULL)
 333                                prregs(excp);   /* print regs */
 334                        break;
 335                case 'e':
 336                        if (excp == NULL)
 337                                printf("No exception information\n");
 338                        else
 339                                excprint(excp);
 340                        break;
 341                case 'S':
 342                        super_regs();
 343                        break;
 344                case 't':
 345                        backtrace(excp);
 346                        break;
 347#if 0
 348                case 'f':
 349                        openforth();
 350                        break;
 351#endif
 352                case 'h':
 353                        dump_hash_table();
 354                        break;
 355                case 's':
 356                case 'x':
 357                case EOF:
 358                        return cmd;
 359                case '?':
 360                        printf(help_string);
 361                        break;
 362                default:
 363                        printf("Unrecognized command: ");
 364                        if( ' ' < cmd && cmd <= '~' )
 365                                putchar(cmd);
 366                        else
 367                                printf("\\x%x", cmd);
 368                        printf(" (type ? for help)\n");
 369                        break;
 370                case 'b':
 371                        bpt_cmds();
 372                        break;
 373                }
 374        }
 375}
 376
 377static void
 378bpt_cmds(void)
 379{
 380        int cmd;
 381        unsigned a;
 382        int mode, i;
 383        struct bpt *bp;
 384
 385        cmd = inchar();
 386        switch (cmd) {
 387        case 'd':
 388                mode = 7;
 389                cmd = inchar();
 390                if (cmd == 'r')
 391                        mode = 5;
 392                else if (cmd == 'w')
 393                        mode = 6;
 394                else
 395                        termch = cmd;
 396                dabr.address = 0;
 397                dabr.count = 0;
 398                dabr.enabled = scanhex(&dabr.address);
 399                scanhex(&dabr.count);
 400                if (dabr.enabled)
 401                        dabr.address = (dabr.address & ~7) | mode;
 402                break;
 403        case 'i':
 404                iabr.address = 0;
 405                iabr.count = 0;
 406                iabr.enabled = scanhex(&iabr.address);
 407                if (iabr.enabled)
 408                        iabr.address |= 3;
 409                scanhex(&iabr.count);
 410                break;
 411        case 'c':
 412                if (!scanhex(&a)) {
 413                        /* clear all breakpoints */
 414                        for (i = 0; i < NBPTS; ++i)
 415                                bpts[i].enabled = 0;
 416                        iabr.enabled = 0;
 417                        dabr.enabled = 0;
 418                        printf("All breakpoints cleared\n");
 419                } else {
 420                        bp = at_breakpoint(a);
 421                        if (bp == 0) {
 422                                printf("No breakpoint at %x\n", a);
 423                        } else {
 424                                bp->enabled = 0;
 425                        }
 426                }
 427                break;
 428        default:
 429                termch = cmd;
 430                if (!scanhex(&a)) {
 431                        /* print all breakpoints */
 432                        printf("type  address   count\n");
 433                        if (dabr.enabled) {
 434                                printf("data %.8x %8x [", dabr.address & ~7,
 435                                       dabr.count);
 436                                if (dabr.address & 1)
 437                                        printf("r");
 438                                if (dabr.address & 2)
 439                                        printf("w");
 440                                printf("]\n");
 441                        }
 442                        if (iabr.enabled)
 443                                printf("inst %.8x %8x\n", iabr.address & ~3,
 444                                       iabr.count);
 445                        for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
 446                                if (bp->enabled)
 447                                        printf("trap %.8x %8x\n", bp->address,
 448                                               bp->count);
 449                        break;
 450                }
 451                bp = at_breakpoint(a);
 452                if (bp == 0) {
 453                        for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
 454                                if (!bp->enabled)
 455                                        break;
 456                        if (bp >= &bpts[NBPTS]) {
 457                                printf("Sorry, no free breakpoints\n");
 458                                break;
 459                        }
 460                }
 461                bp->enabled = 1;
 462                bp->address = a;
 463                bp->count = 0;
 464                scanhex(&bp->count);
 465                break;
 466        }
 467}
 468
 469static void
 470backtrace(struct pt_regs *excp)
 471{
 472        unsigned sp;
 473        unsigned stack[2];
 474        struct pt_regs regs;
 475        extern char int_return, syscall_ret_1, syscall_ret_2;
 476        extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret;
 477
 478        if (excp != NULL)
 479                sp = excp->gpr[1];
 480        else
 481                sp = getsp();
 482        scanhex(&sp);
 483        scannl();
 484        for (; sp != 0; sp = stack[0]) {
 485                if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
 486                        break;
 487                printf("%x ", stack[1]);
 488                if (stack[1] == (unsigned) &int_return
 489                    || stack[1] == (unsigned) &syscall_ret_1
 490                    || stack[1] == (unsigned) &syscall_ret_2
 491                    || stack[1] == (unsigned) &lost_irq_ret
 492                    || stack[1] == (unsigned) &do_bottom_half_ret
 493                    || stack[1] == (unsigned) &do_signal_ret) {
 494                        if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
 495                                break;
 496                        printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
 497                               regs.nip);
 498                        sp = regs.gpr[1];
 499                        if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
 500                                break;
 501                }
 502        }
 503        printf("\n");
 504}
 505
 506int
 507getsp()
 508{
 509    int x;
 510
 511    asm("mr %0,1" : "=r" (x) :);
 512    return x;
 513}
 514
 515void
 516excprint(struct pt_regs *fp)
 517{
 518        printf("vector: %x at pc = %x, msr = %x, sp = %x [%x]\n",
 519               fp->trap, fp->nip, fp->msr, fp->gpr[1], fp);
 520        if (fp->trap == 0x300 || fp->trap == 0x600)
 521                printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
 522        if (current)
 523                printf("current = %x, pid = %d, comm = %s\n",
 524                       current, current->pid, current->comm);
 525}
 526
 527void
 528prregs(struct pt_regs *fp)
 529{
 530        int n;
 531        unsigned base;
 532
 533        if (scanhex(&base))
 534                fp = (struct pt_regs *) base;
 535        for (n = 0; n < 32; ++n)
 536                printf("R%.2d = %.8x%s", n, fp->gpr[n],
 537                       (n & 3) == 3? "\n": "   ");
 538        printf("pc  = %.8x   msr = %.8x   lr  = %.8x   cr  = %.8x\n",
 539               fp->nip, fp->msr, fp->link, fp->ccr);
 540        printf("ctr = %.8x   xer = %.8x   trap = %4x\n",
 541               fp->ctr, fp->xer, fp->trap);
 542}
 543
 544unsigned int
 545read_spr(int n)
 546{
 547    unsigned int instrs[2];
 548    int (*code)(void);
 549
 550    instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
 551    instrs[1] = 0x4e800020;
 552    store_inst(instrs);
 553    store_inst(instrs+1);
 554    code = (int (*)(void)) instrs;
 555    return code();
 556}
 557
 558void
 559write_spr(int n, unsigned int val)
 560{
 561    unsigned int instrs[2];
 562    int (*code)(unsigned int);
 563
 564    instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
 565    instrs[1] = 0x4e800020;
 566    store_inst(instrs);
 567    store_inst(instrs+1);
 568    code = (int (*)(unsigned int)) instrs;
 569    code(val);
 570}
 571
 572static unsigned int regno;
 573extern char exc_prolog;
 574extern char dec_exc;
 575
 576void
 577super_regs()
 578{
 579        int i, cmd;
 580        unsigned val;
 581
 582        cmd = skipbl();
 583        if (cmd == '\n') {
 584                printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
 585                printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
 586                       get_sprg2(), get_sprg3());
 587                printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
 588                printf("sr0-15 =");
 589                for (i = 0; i < 16; ++i)
 590                        printf(" %x", get_sr(i));
 591                printf("\n");
 592                asm("mr %0,1" : "=r" (i) :);
 593                printf("sp = %x ", i);
 594                asm("mr %0,2" : "=r" (i) :);
 595                printf("toc = %x\n", i);
 596                return;
 597        }
 598
 599        scanhex(&regno);
 600        switch (cmd) {
 601        case 'w':
 602                val = read_spr(regno);
 603                scanhex(&val);
 604                write_spr(regno, val);
 605                /* fall through */
 606        case 'r':
 607                printf("spr %x = %x\n", regno, read_spr(regno));
 608                break;
 609        case 's':
 610                val = get_sr(regno);
 611                scanhex(&val);
 612                set_sr(regno, val);
 613                break;
 614        case 'm':
 615                val = get_msr();
 616                scanhex(&val);
 617                set_msr(val);
 618                break;
 619        }
 620        scannl();
 621}
 622
 623#if 0
 624static void
 625openforth()
 626{
 627    int c;
 628    char *p;
 629    char cmd[1024];
 630    int args[5];
 631    extern int (*prom_entry)(int *);
 632
 633    p = cmd;
 634    c = skipbl();
 635    while (c != '\n') {
 636        *p++ = c;
 637        c = inchar();
 638    }
 639    *p = 0;
 640    args[0] = (int) "interpret";
 641    args[1] = 1;
 642    args[2] = 1;
 643    args[3] = (int) cmd;
 644    (*prom_entry)(args);
 645    printf("\n");
 646    if (args[4] != 0)
 647        printf("error %x\n", args[4]);
 648}
 649#endif
 650
 651static void
 652dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
 653{
 654        extern void *Hash;
 655        extern unsigned long Hash_size;
 656        unsigned *htab = Hash;
 657        unsigned hsize = Hash_size;
 658        unsigned v, hmask, va, last_va;
 659        int found, last_found, i;
 660        unsigned *hg, w1, last_w2, last_va0;
 661
 662        last_found = 0;
 663        hmask = hsize / 64 - 1;
 664        va = start;
 665        start = (start >> 12) & 0xffff;
 666        end = (end >> 12) & 0xffff;
 667        for (v = start; v < end; ++v) {
 668                found = 0;
 669                hg = htab + (((v ^ seg) & hmask) * 16);
 670                w1 = 0x80000000 | (seg << 7) | (v >> 10);
 671                for (i = 0; i < 8; ++i, hg += 2) {
 672                        if (*hg == w1) {
 673                                found = 1;
 674                                break;
 675                        }
 676                }
 677                if (!found) {
 678                        w1 ^= 0x40;
 679                        hg = htab + ((~(v ^ seg) & hmask) * 16);
 680                        for (i = 0; i < 8; ++i, hg += 2) {
 681                                if (*hg == w1) {
 682                                        found = 1;
 683                                        break;
 684                                }
 685                        }
 686                }
 687                if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
 688                        if (last_found) {
 689                                if (last_va != last_va0)
 690                                        printf(" ... %x", last_va);
 691                                printf("\n");
 692                        }
 693                        if (found) {
 694                                printf("%x to %x", va, hg[1]);
 695                                last_va0 = va;
 696                        }
 697                        last_found = found;
 698                }
 699                if (found) {
 700                        last_w2 = hg[1] & ~0x180;
 701                        last_va = va;
 702                }
 703                va += 4096;
 704        }
 705        if (last_found)
 706                printf(" ... %x\n", last_va);
 707}
 708static unsigned hash_ctx;
 709static unsigned hash_start;
 710static unsigned hash_end;
 711
 712static void
 713dump_hash_table()
 714{
 715        int seg;
 716        unsigned seg_start, seg_end;
 717
 718        hash_ctx = 0;
 719        hash_start = 0;
 720        hash_end = 0xfffff000;
 721        scanhex(&hash_ctx);
 722        scanhex(&hash_start);
 723        scanhex(&hash_end);
 724        printf("Mappings for context %x\n", hash_ctx);
 725        seg_start = hash_start;
 726        for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
 727                seg_end = (seg << 28) | 0x0ffff000;
 728                if (seg_end > hash_end)
 729                        seg_end = hash_end;
 730                dump_hash_table_seg((hash_ctx << 4) + seg, seg_start, seg_end);
 731                seg_start = seg_end + 0x1000;
 732        }
 733}
 734
 735/*
 736 * Stuff for reading and writing memory safely
 737 */
 738extern inline void sync(void)
 739{
 740        asm volatile("sync; isync");
 741}
 742
 743extern inline void __delay(unsigned int loops)
 744{
 745        if (loops != 0)
 746                __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
 747                                     "r" (loops) : "ctr");
 748}
 749
 750int
 751mread(unsigned adrs, void *buf, int size)
 752{
 753        volatile int n;
 754        char *p, *q;
 755
 756        n = 0;
 757        if( setjmp(bus_error_jmp) == 0 ){
 758                debugger_fault_handler = handle_fault;
 759                sync();
 760                p = (char *) adrs;
 761                q = (char *) buf;
 762                switch (size) {
 763                case 2: *(short *)q = *(short *)p;      break;
 764                case 4: *(int *)q = *(int *)p;          break;
 765                default:
 766                        for( ; n < size; ++n ) {
 767                                *q++ = *p++;
 768                                sync();
 769                        }
 770                }
 771                sync();
 772                /* wait a little while to see if we get a machine check */
 773                __delay(200);
 774                n = size;
 775        }
 776        debugger_fault_handler = 0;
 777        return n;
 778}
 779
 780int
 781mwrite(unsigned adrs, void *buf, int size)
 782{
 783        volatile int n;
 784        char *p, *q;
 785
 786        n = 0;
 787        if( setjmp(bus_error_jmp) == 0 ){
 788                debugger_fault_handler = handle_fault;
 789                sync();
 790                p = (char *) adrs;
 791                q = (char *) buf;
 792                switch (size) {
 793                case 2: *(short *)p = *(short *)q;      break;
 794                case 4: *(int *)p = *(int *)q;          break;
 795                default:
 796                        for( ; n < size; ++n ) {
 797                                *p++ = *q++;
 798                                sync();
 799                        }
 800                }
 801                sync();
 802                n = size;
 803        } else {
 804                printf("*** Error writing address %x\n", adrs + n);
 805        }
 806        debugger_fault_handler = 0;
 807        return n;
 808}
 809
 810static int fault_type;
 811static char *fault_chars[] = { "--", "**", "##" };
 812
 813static void
 814handle_fault(struct pt_regs *regs)
 815{
 816        fault_type = regs->trap == 0x200? 0: regs->trap == 0x300? 1: 2;
 817        longjmp(bus_error_jmp, 1);
 818}
 819
 820#define SWAP(a, b, t)   ((t) = (a), (a) = (b), (b) = (t))
 821
 822void
 823byterev(unsigned char *val, int size)
 824{
 825        int t;
 826        
 827        switch (size) {
 828        case 2:
 829                SWAP(val[0], val[1], t);
 830                break;
 831        case 4:
 832                SWAP(val[0], val[3], t);
 833                SWAP(val[1], val[2], t);
 834                break;
 835        }
 836}
 837
 838static int brev;
 839static int mnoread;
 840
 841void
 842memex()
 843{
 844    int cmd, inc, i, nslash;
 845    unsigned n;
 846    unsigned char val[4];
 847
 848    last_cmd = "m\n";
 849    scanhex(&adrs);
 850    while ((cmd = skipbl()) != '\n') {
 851        switch( cmd ){
 852        case 'b':       size = 1;       break;
 853        case 'w':       size = 2;       break;
 854        case 'l':       size = 4;       break;
 855        case 'r':       brev = !brev;   break;
 856        case 'n':       mnoread = 1;    break;
 857        case '.':       mnoread = 0;    break;
 858        }
 859    }
 860    if( size <= 0 )
 861        size = 1;
 862    else if( size > 4 )
 863        size = 4;
 864    for(;;){
 865        if (!mnoread)
 866            n = mread(adrs, val, size);
 867        printf("%.8x%c", adrs, brev? 'r': ' ');
 868        if (!mnoread) {
 869            if (brev)
 870                byterev(val, size);
 871            putchar(' ');
 872            for (i = 0; i < n; ++i)
 873                printf("%.2x", val[i]);
 874            for (; i < size; ++i)
 875                printf("%s", fault_chars[fault_type]);
 876        }
 877        putchar(' ');
 878        inc = size;
 879        nslash = 0;
 880        for(;;){
 881            if( scanhex(&n) ){
 882                for (i = 0; i < size; ++i)
 883                    val[i] = n >> (i * 8);
 884                if (!brev)
 885                    byterev(val, size);
 886                mwrite(adrs, val, size);
 887                inc = size;
 888            }
 889            cmd = skipbl();
 890            if (cmd == '\n')
 891                break;
 892            inc = 0;
 893            switch (cmd) {
 894            case '\'':
 895                for(;;){
 896                    n = inchar();
 897                    if( n == '\\' )
 898                        n = bsesc();
 899                    else if( n == '\'' )
 900                        break;
 901                    for (i = 0; i < size; ++i)
 902                        val[i] = n >> (i * 8);
 903                    if (!brev)
 904                        byterev(val, size);
 905                    mwrite(adrs, val, size);
 906                    adrs += size;
 907                }
 908                adrs -= size;
 909                inc = size;
 910                break;
 911            case ',':
 912                adrs += size;
 913                break;
 914            case '.':
 915                mnoread = 0;
 916                break;
 917            case ';':
 918                break;
 919            case 'x':
 920            case EOF:
 921                scannl();
 922                return;
 923            case 'b':
 924            case 'v':
 925                size = 1;
 926                break;
 927            case 'w':
 928                size = 2;
 929                break;
 930            case 'l':
 931                size = 4;
 932                break;
 933            case '^':
 934                adrs -= size;
 935                break;
 936                break;
 937            case '/':
 938                if (nslash > 0)
 939                    adrs -= 1 << nslash;
 940                else
 941                    nslash = 0;
 942                nslash += 4;
 943                adrs += 1 << nslash;
 944                break;
 945            case '\\':
 946                if (nslash < 0)
 947                    adrs += 1 << -nslash;
 948                else
 949                    nslash = 0;
 950                nslash -= 4;
 951                adrs -= 1 << -nslash;
 952                break;
 953            case 'm':
 954                scanhex(&adrs);
 955                break;
 956            case 'n':
 957                mnoread = 1;
 958                break;
 959            case 'r':
 960                brev = !brev;
 961                break;
 962            case '<':
 963                n = size;
 964                scanhex(&n);
 965                adrs -= n;
 966                break;
 967            case '>':
 968                n = size;
 969                scanhex(&n);
 970                adrs += n;
 971                break;
 972            }
 973        }
 974        adrs += inc;
 975    }
 976}
 977
 978int
 979bsesc()
 980{
 981        int c;
 982
 983        c = inchar();
 984        switch( c ){
 985        case 'n':       c = '\n';       break;
 986        case 'r':       c = '\r';       break;
 987        case 'b':       c = '\b';       break;
 988        case 't':       c = '\t';       break;
 989        }
 990        return c;
 991}
 992
 993#define isxdigit(c)     (('0' <= (c) && (c) <= '9') \
 994                         || ('a' <= (c) && (c) <= 'f') \
 995                         || ('A' <= (c) && (c) <= 'F'))
 996void
 997dump()
 998{
 999        int c;
1000
1001        c = inchar();
1002        if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1003                termch = c;
1004        scanhex(&adrs);
1005        if( termch != '\n')
1006                termch = 0;
1007        if( c == 'i' ){
1008                scanhex(&nidump);
1009                if( nidump == 0 )
1010                        nidump = 16;
1011                adrs += ppc_inst_dump(adrs, nidump);
1012                last_cmd = "di\n";
1013        } else {
1014                scanhex(&ndump);
1015                if( ndump == 0 )
1016                        ndump = 64;
1017                prdump(adrs, ndump);
1018                adrs += ndump;
1019                last_cmd = "d\n";
1020        }
1021}
1022
1023void
1024prdump(unsigned adrs, int ndump)
1025{
1026        register int n, m, c, r, nr;
1027        unsigned char temp[16];
1028
1029        for( n = ndump; n > 0; ){
1030                printf("%.8x", adrs);
1031                putchar(' ');
1032                r = n < 16? n: 16;
1033                nr = mread(adrs, temp, r);
1034                adrs += nr;
1035                for( m = 0; m < r; ++m ){
1036                        putchar((m & 3) == 0 && m > 0? '.': ' ');
1037                        if( m < nr )
1038                                printf("%.2x", temp[m]);
1039                        else
1040                                printf("%s", fault_chars[fault_type]);
1041                }
1042                for(; m < 16; ++m )
1043                        printf("   ");
1044                printf("  |");
1045                for( m = 0; m < r; ++m ){
1046                        if( m < nr ){
1047                                c = temp[m];
1048                                putchar(' ' <= c && c <= '~'? c: '.');
1049                        } else
1050                                putchar(' ');
1051                }
1052                n -= r;
1053                for(; m < 16; ++m )
1054                        putchar(' ');
1055                printf("|\n");
1056                if( nr < r )
1057                        break;
1058        }
1059}
1060
1061int
1062ppc_inst_dump(unsigned adr, int count)
1063{
1064        int nr, dotted;
1065        unsigned first_adr;
1066        unsigned long inst, last_inst;
1067        unsigned char val[4];
1068
1069        dotted = 0;
1070        for (first_adr = adr; count > 0; --count, adr += 4){
1071                nr = mread(adr, val, 4);
1072                if( nr == 0 ){
1073                        const char *x = fault_chars[fault_type];
1074                        printf("%.8x  %s%s%s%s\n", adr, x, x, x, x);
1075                        break;
1076                }
1077                inst = GETWORD(val);
1078                if (adr > first_adr && inst == last_inst) {
1079                        if (!dotted) {
1080                                printf(" ...\n");
1081                                dotted = 1;
1082                        }
1083                        continue;
1084                }
1085                dotted = 0;
1086                last_inst = inst;
1087                printf("%.8x  ", adr);
1088                printf("%.8x\t", inst);
1089                print_insn_big_powerpc(stdout, inst, adr);      /* always returns 4 */
1090                printf("\n");
1091        }
1092        return adr - first_adr;
1093}
1094
1095void
1096print_address(addr)
1097unsigned addr;
1098{
1099        printf("0x%x", addr);
1100}
1101
1102/*
1103 * Memory operations - move, set, print differences
1104 */
1105static unsigned mdest;          /* destination address */
1106static unsigned msrc;           /* source address */
1107static unsigned mval;           /* byte value to set memory to */
1108static unsigned mcount;         /* # bytes to affect */
1109static unsigned mdiffs;         /* max # differences to print */
1110
1111void
1112memops(int cmd)
1113{
1114        scanhex(&mdest);
1115        if( termch != '\n' )
1116                termch = 0;
1117        scanhex(cmd == 's'? &mval: &msrc);
1118        if( termch != '\n' )
1119                termch = 0;
1120        scanhex(&mcount);
1121        switch( cmd ){
1122        case 'm':
1123                memmove((void *)mdest, (void *)msrc, mcount);
1124                break;
1125        case 's':
1126                memset((void *)mdest, mval, mcount);
1127                break;
1128        case 'd':
1129                if( termch != '\n' )
1130                        termch = 0;
1131                scanhex(&mdiffs);
1132                memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1133                break;
1134        }
1135}
1136
1137void
1138memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1139{
1140        unsigned n, prt;
1141
1142        prt = 0;
1143        for( n = nb; n > 0; --n )
1144                if( *p1++ != *p2++ )
1145                        if( ++prt <= maxpr )
1146                                printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1147                                        p1[-1], (unsigned)p2 - 1, p2[-1]);
1148        if( prt > maxpr )
1149                printf("Total of %d differences\n", prt);
1150}
1151
1152static unsigned mend;
1153static unsigned mask;
1154
1155void
1156memlocate()
1157{
1158        unsigned a, n;
1159        unsigned char val[4];
1160
1161        last_cmd = "ml";
1162        scanhex(&mdest);
1163        if (termch != '\n') {
1164                termch = 0;
1165                scanhex(&mend);
1166                if (termch != '\n') {
1167                        termch = 0;
1168                        scanhex(&mval);
1169                        mask = ~0;
1170                        if (termch != '\n') termch = 0;
1171                        scanhex(&mask);
1172                }
1173        }
1174        n = 0;
1175        for (a = mdest; a < mend; a += 4) {
1176                if (mread(a, val, 4) == 4
1177                        && ((GETWORD(val) ^ mval) & mask) == 0) {
1178                        printf("%.8x:  %.8x\n", a, GETWORD(val));
1179                        if (++n >= 10)
1180                                break;
1181                }
1182        }
1183}
1184
1185static unsigned mskip = 0x1000;
1186static unsigned mlim = 0xffffffff;
1187
1188void
1189memzcan()
1190{
1191        unsigned char v;
1192        unsigned a;
1193        int ok, ook;
1194
1195        scanhex(&mdest);
1196        if (termch != '\n') termch = 0;
1197        scanhex(&mskip);
1198        if (termch != '\n') termch = 0;
1199        scanhex(&mlim);
1200        ook = 0;
1201        for (a = mdest; a < mlim; a += mskip) {
1202                ok = mread(a, &v, 1);
1203                if (ok && !ook) {
1204                        printf("%.8x .. ", a);
1205                        fflush(stdout);
1206                } else if (!ok && ook)
1207                        printf("%.8x\n", a - mskip);
1208                ook = ok;
1209                if (a + mskip < a)
1210                        break;
1211        }
1212        if (ook)
1213                printf("%.8x\n", a - mskip);
1214}
1215
1216/* Input scanning routines */
1217int
1218skipbl()
1219{
1220        int c;
1221
1222        if( termch != 0 ){
1223                c = termch;
1224                termch = 0;
1225        } else
1226                c = inchar();
1227        while( c == ' ' || c == '\t' )
1228                c = inchar();
1229        return c;
1230}
1231
1232int
1233scanhex(vp)
1234unsigned *vp;
1235{
1236        int c, d;
1237        unsigned v;
1238
1239        c = skipbl();
1240        d = hexdigit(c);
1241        if( d == EOF ){
1242                termch = c;
1243                return 0;
1244        }
1245        v = 0;
1246        do {
1247                v = (v << 4) + d;
1248                c = inchar();
1249                d = hexdigit(c);
1250        } while( d != EOF );
1251        termch = c;
1252        *vp = v;
1253        return 1;
1254}
1255
1256void
1257scannl()
1258{
1259        int c;
1260
1261        c = termch;
1262        termch = 0;
1263        while( c != '\n' )
1264                c = inchar();
1265}
1266
1267int
1268hexdigit(c)
1269{
1270        if( '0' <= c && c <= '9' )
1271                return c - '0';
1272        if( 'A' <= c && c <= 'F' )
1273                return c - ('A' - 10);
1274        if( 'a' <= c && c <= 'f' )
1275                return c - ('a' - 10);
1276        return EOF;
1277}
1278
1279void
1280getstring(char *s, int size)
1281{
1282        int c;
1283
1284        c = skipbl();
1285        do {
1286                if( size > 1 ){
1287                        *s++ = c;
1288                        --size;
1289                }
1290                c = inchar();
1291        } while( c != ' ' && c != '\t' && c != '\n' );
1292        termch = c;
1293        *s = 0;
1294}
1295
1296static char line[256];
1297static char *lineptr;
1298
1299void
1300flush_input()
1301{
1302        lineptr = NULL;
1303}
1304
1305int
1306inchar()
1307{
1308        if (lineptr == NULL || *lineptr == 0) {
1309                if (fgets(line, sizeof(line), stdin) == NULL) {
1310                        lineptr = NULL;
1311                        return EOF;
1312                }
1313                lineptr = line;
1314        }
1315        return *lineptr++;
1316}
1317
1318void
1319take_input(str)
1320char *str;
1321{
1322        lineptr = str;
1323}
1324
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.