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