darwin-xnu/osfmk/ppc/db_disasm.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
   3 *
   4 * @APPLE_LICENSE_HEADER_START@
   5 * 
   6 * The contents of this file constitute Original Code as defined in and
   7 * are subject to the Apple Public Source License Version 1.1 (the
   8 * "License").  You may not use this file except in compliance with the
   9 * License.  Please obtain a copy of the License at
  10 * http://www.apple.com/publicsource and read it before using this file.
  11 * 
  12 * This Original Code and all software distributed under the License are
  13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
  17 * License for the specific language governing rights and limitations
  18 * under the License.
  19 * 
  20 * @APPLE_LICENSE_HEADER_END@
  21 */
  22/*
  23 * @OSF_COPYRIGHT@
  24 */
  25
  26/*
  27 * Instruction disassembler.
  28 */
  29
  30#include <mach/boolean.h>
  31#include <machine/db_machdep.h>
  32
  33#include <ddb/db_access.h>
  34#include <ddb/db_sym.h>
  35#include <ddb/db_output.h>
  36
  37#include <kern/task.h>
  38#include <kern/misc_protos.h>
  39
  40#include "ppc_disasm.h"
  41
  42db_addr_t       db_disasm_pc, db_disasm_symaddr;
  43boolean_t       db_disasm_print_symaddr;
  44
  45/*
  46 * Disassemble instruction at 'loc'.  'altfmt' specifies an
  47 * (optional) alternate format.  Return address of start of
  48 * next instruction.
  49 */
  50db_addr_t
  51db_disasm(
  52        db_addr_t       loc,
  53        boolean_t       altfmt,
  54        task_t          task)
  55{
  56        int inst;
  57        char *p;
  58
  59        inst = db_get_task_value(loc, 4, FALSE, task);
  60        db_disasm_pc = loc;
  61        db_disasm_print_symaddr = FALSE;
  62        p = in(inst);
  63        db_printf("%s", p);
  64        if (db_disasm_print_symaddr) {
  65                db_printf(" <");
  66                db_task_printsym(db_disasm_symaddr, DB_STGY_ANY, task);
  67                db_printf(">");
  68        }
  69        db_printf("\n");                /* Make sure we have a new line for multiline displays */
  70        dis_done();
  71        return (loc+4);
  72}
  73
  74/*
  75 * Given four bytes of instruction (stored as an int, not an
  76 * array of characters), compute if the instruction reads
  77 * memory.
  78 */
  79int
  80db_inst_load(
  81        unsigned long insw)
  82{
  83#if 1
  84        db_printf("db_inst_load: coming soon in a debugger near you!\n");
  85        return 0;
  86#else
  87        unsigned char insb, bits;
  88
  89        insb = insw & 0xff;
  90        insw >>= 8;
  91        bits = db_ldstrtab[insb];
  92        if (!(bits & DBLS_LOAD))
  93                return (0);
  94        while (1) {
  95                switch (bits & DBLS_MODS) {
  96                case 0:
  97                        return (1);     
  98                case DBLS_MODRM:
  99                        insb = insw & 0xff;
 100                        return ((insb & 0xc0) != 0xc0);
 101                case DBLS_SECOND|DBLS_MODRM:
 102                        insb = insw & 0xff;
 103                        return ((insb & 0xc0) != 0xc0 ? 2 : 0);
 104                case DBLS_SECOND:
 105                        return (2);
 106                case DBLS_ESCAPE:
 107                        insb = insw & 0xff;
 108                        insw >>= 8;
 109                        bits = db_ldstrtab0f[insb];
 110                        break;
 111                case DBLS_SWREG:
 112                        return (db_inst_swreg(TRUE, insw, insb));
 113                default:
 114                        panic ("db_inst_load: unknown mod bits");
 115                }
 116        }
 117#endif
 118}
 119
 120/*
 121 * Given four bytes of instruction (stored as an int, not an
 122 * array of characters), compute if the instruction writes
 123 * memory.
 124 */
 125int
 126db_inst_store(
 127        unsigned long insw)
 128{
 129#if 1
 130        db_printf("db_inst_store: coming soon in a debugger near you!\n");
 131        return 0;
 132#else
 133        unsigned char insb, bits;
 134
 135        insb = insw & 0xff;
 136        insw >>= 8;
 137        bits = db_ldstrtab[insb];
 138        if (!(bits & DBLS_STORE))
 139                return (0);
 140        while (1) {
 141                switch (bits & DBLS_MODS) {
 142                case 0:
 143                        return (1);     
 144                case DBLS_MODRM:
 145                        insb = insw & 0xff;
 146                        return ((insb & 0xc0) != 0xc0);
 147                case DBLS_SECOND|DBLS_MODRM:
 148                        insb = insw & 0xff;
 149                        return ((insb & 0xc0) != 0xc0 ? 2 : 0);
 150                case DBLS_SECOND:
 151                        return (2);
 152                case DBLS_ESCAPE:
 153                        insb = insw & 0xff;
 154                        insw >>= 8;
 155                        bits = db_ldstrtab0f[insb];
 156                        break;
 157                case DBLS_SWREG:
 158                        return (db_inst_swreg(FALSE, insw, insb));
 159                default:
 160                        panic ("db_inst_store: unknown mod bits");
 161                }
 162        }
 163#endif
 164}
 165
 166/*
 167 * Extra routines for the automatically generated disassembler
 168 */
 169char *
 170hex(
 171        bits n)
 172{
 173        char *p;
 174
 175        if (n < 10)
 176                return dec(n);
 177        p = dis_alloc(11);
 178        sprintf(p, "0x%lx", n);
 179        return p;
 180}
 181
 182char *
 183dec(
 184        bits n)
 185{
 186        char *p = dis_alloc(11);
 187        sprintf(p, "%lu", n);
 188        return p;
 189}
 190
 191char *
 192brdispl(
 193        bits displ,
 194        bits nbits)
 195{
 196        int sign, extended;
 197
 198        sign = 1 << (nbits - 1);
 199        extended = (displ & sign ? displ - (sign << 1) : displ);
 200        db_disasm_symaddr = db_disasm_pc + (extended << 2);
 201        db_disasm_print_symaddr = TRUE;
 202        return hex(extended << 2);
 203}
 204
 205char *
 206mbz(
 207        bits n)
 208{
 209        return n ? "[reserved bits not zero]" : "";
 210}
 211
 212size_t db_disasm_string_size = 0;
 213#define DB_DISASM_STRING_MAXSIZE        4096
 214char db_disasm_string[DB_DISASM_STRING_MAXSIZE];
 215
 216void *db_disasm_malloc(size_t size);    /* forward */
 217void *
 218db_disasm_malloc(
 219        size_t size)
 220{
 221        void * new_buf;
 222
 223        if (db_disasm_string_size + size <= DB_DISASM_STRING_MAXSIZE) {
 224                new_buf = (void *) (db_disasm_string + db_disasm_string_size);
 225                db_disasm_string_size += size;
 226                return new_buf;
 227        }
 228        db_printf("db_disasm_malloc(size=%d) failed: %d left !\n",
 229                  size,
 230                  DB_DISASM_STRING_MAXSIZE - db_disasm_string_size);
 231        return (void *) 0;
 232}
 233
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.