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