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