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