]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/db_disasm.c
xnu-124.13.tar.gz
[apple/xnu.git] / osfmk / ppc / db_disasm.c
CommitLineData
1c79356b
A
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 dis_done();
70 return (loc+4);
71}
72
73/*
74 * Given four bytes of instruction (stored as an int, not an
75 * array of characters), compute if the instruction reads
76 * memory.
77 */
78int
79db_inst_load(
80 unsigned long insw)
81{
82#if 1
83 db_printf("db_inst_load: coming soon in a debugger near you!\n");
84 return 0;
85#else
86 unsigned char insb, bits;
87
88 insb = insw & 0xff;
89 insw >>= 8;
90 bits = db_ldstrtab[insb];
91 if (!(bits & DBLS_LOAD))
92 return (0);
93 while (1) {
94 switch (bits & DBLS_MODS) {
95 case 0:
96 return (1);
97 case DBLS_MODRM:
98 insb = insw & 0xff;
99 return ((insb & 0xc0) != 0xc0);
100 case DBLS_SECOND|DBLS_MODRM:
101 insb = insw & 0xff;
102 return ((insb & 0xc0) != 0xc0 ? 2 : 0);
103 case DBLS_SECOND:
104 return (2);
105 case DBLS_ESCAPE:
106 insb = insw & 0xff;
107 insw >>= 8;
108 bits = db_ldstrtab0f[insb];
109 break;
110 case DBLS_SWREG:
111 return (db_inst_swreg(TRUE, insw, insb));
112 default:
113 panic ("db_inst_load: unknown mod bits");
114 }
115 }
116#endif
117}
118
119/*
120 * Given four bytes of instruction (stored as an int, not an
121 * array of characters), compute if the instruction writes
122 * memory.
123 */
124int
125db_inst_store(
126 unsigned long insw)
127{
128#if 1
129 db_printf("db_inst_store: coming soon in a debugger near you!\n");
130 return 0;
131#else
132 unsigned char insb, bits;
133
134 insb = insw & 0xff;
135 insw >>= 8;
136 bits = db_ldstrtab[insb];
137 if (!(bits & DBLS_STORE))
138 return (0);
139 while (1) {
140 switch (bits & DBLS_MODS) {
141 case 0:
142 return (1);
143 case DBLS_MODRM:
144 insb = insw & 0xff;
145 return ((insb & 0xc0) != 0xc0);
146 case DBLS_SECOND|DBLS_MODRM:
147 insb = insw & 0xff;
148 return ((insb & 0xc0) != 0xc0 ? 2 : 0);
149 case DBLS_SECOND:
150 return (2);
151 case DBLS_ESCAPE:
152 insb = insw & 0xff;
153 insw >>= 8;
154 bits = db_ldstrtab0f[insb];
155 break;
156 case DBLS_SWREG:
157 return (db_inst_swreg(FALSE, insw, insb));
158 default:
159 panic ("db_inst_store: unknown mod bits");
160 }
161 }
162#endif
163}
164
165/*
166 * Extra routines for the automatically generated disassembler
167 */
168char *
169hex(
170 bits n)
171{
172 char *p;
173
174 if (n < 10)
175 return dec(n);
176 p = dis_alloc(11);
177 sprintf(p, "0x%lx", n);
178 return p;
179}
180
181char *
182dec(
183 bits n)
184{
185 char *p = dis_alloc(11);
186 sprintf(p, "%lu", n);
187 return p;
188}
189
190char *
191brdispl(
192 bits displ,
193 bits nbits)
194{
195 int sign, extended;
196
197 sign = 1 << (nbits - 1);
198 extended = (displ & sign ? displ - (sign << 1) : displ);
199 db_disasm_symaddr = db_disasm_pc + (extended << 2);
200 db_disasm_print_symaddr = TRUE;
201 return hex(extended << 2);
202}
203
204char *
205mbz(
206 bits n)
207{
208 return n ? "[reserved bits not zero]" : "";
209}
210
211size_t db_disasm_string_size = 0;
212#define DB_DISASM_STRING_MAXSIZE 4096
213char db_disasm_string[DB_DISASM_STRING_MAXSIZE];
214
215void *db_disasm_malloc(size_t size); /* forward */
216void *
217db_disasm_malloc(
218 size_t size)
219{
220 void * new_buf;
221
222 if (db_disasm_string_size + size <= DB_DISASM_STRING_MAXSIZE) {
223 new_buf = (void *) (db_disasm_string + db_disasm_string_size);
224 db_disasm_string_size += size;
225 return new_buf;
226 }
227 db_printf("db_disasm_malloc(size=%d) failed: %d left !\n",
228 size,
229 DB_DISASM_STRING_MAXSIZE - db_disasm_string_size);
230 return (void *) 0;
231}