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