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