]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/db_disasm.c
xnu-1504.3.12.tar.gz
[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(db_addr_t loc, __unused boolean_t altfmt, 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 db_printf("\n"); /* Make sure we have a new line for multiline displays */
73 dis_done();
74 return (loc+4);
75 }
76
77 /*
78 * Given four bytes of instruction (stored as an int, not an
79 * array of characters), compute if the instruction reads
80 * memory.
81 */
82 int
83 db_inst_load(__unused 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(__unused 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(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 }