]> git.saurik.com Git - apple/boot.git/blob - i386/nasm/ndisasm.c
boot-111.tar.gz
[apple/boot.git] / i386 / nasm / ndisasm.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* ndisasm.c the Netwide Disassembler main module
26 *
27 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
28 * Julian Hall. All rights reserved. The software is
29 * redistributable under the licence given in the file "Licence"
30 * distributed in the NASM archive.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <errno.h>
38
39 #include "nasm.h"
40 #include "nasmlib.h"
41 #include "sync.h"
42 #include "disasm.h"
43
44 #define BPL 8 /* bytes per line of hex dump */
45
46 static const char *help =
47 "usage: ndisasm [-a] [-i] [-h] [-r] [-u] [-b bits] [-o origin] [-s sync...]\n"
48 " [-e bytes] [-k start,bytes] file\n"
49 " -a or -i activates auto (intelligent) sync\n"
50 " -u sets USE32 (32-bit mode)\n"
51 " -b 16 or -b 32 sets number of bits too\n"
52 " -h displays this text\n"
53 " -r displays the version number\n"
54 " -e skips <bytes> bytes of header\n"
55 " -k avoids disassembling <bytes> bytes from position <start>\n";
56
57 static void output_ins (unsigned long, unsigned char *, int, char *);
58 static void skip (unsigned long dist, FILE *fp);
59
60 int main(int argc, char **argv) {
61 unsigned char buffer[INSN_MAX * 2], *p, *q;
62 char outbuf[256];
63 char *pname = *argv;
64 char *filename = NULL;
65 unsigned long nextsync, synclen, initskip = 0L;
66 int lenread, lendis;
67 int autosync = FALSE;
68 int bits = 16;
69 int eof = FALSE;
70 int rn_error;
71 long offset;
72 FILE *fp;
73
74 offset = 0;
75 init_sync();
76
77 while (--argc) {
78 char *v, *vv, *p = *++argv;
79 if (*p == '-') {
80 p++;
81 while (*p) switch (tolower(*p)) {
82 case 'a': /* auto or intelligent sync */
83 case 'i':
84 autosync = TRUE;
85 p++;
86 break;
87 case 'h':
88 fprintf(stderr, help);
89 return 0;
90 case 'r':
91 fprintf(stderr, "NDISASM version " NASM_VER "\n");
92 return 0;
93 case 'u': /* USE32 */
94 bits = 32;
95 p++;
96 break;
97 case 'b': /* bits */
98 v = p[1] ? p+1 : --argc ? *++argv : NULL;
99 if (!v) {
100 fprintf(stderr, "%s: `-b' requires an argument\n", pname);
101 return 1;
102 }
103 if (!strcmp(v, "16"))
104 bits = 16;
105 else if (!strcmp(v, "32"))
106 bits = 32;
107 else {
108 fprintf(stderr, "%s: argument to `-b' should"
109 " be `16' or `32'\n", pname);
110 }
111 p = ""; /* force to next argument */
112 break;
113 case 'o': /* origin */
114 v = p[1] ? p+1 : --argc ? *++argv : NULL;
115 if (!v) {
116 fprintf(stderr, "%s: `-o' requires an argument\n", pname);
117 return 1;
118 }
119 offset = readnum (v, &rn_error);
120 if (rn_error) {
121 fprintf(stderr, "%s: `-o' requires a numeric argument\n",
122 pname);
123 return 1;
124 }
125 p = ""; /* force to next argument */
126 break;
127 case 's': /* sync point */
128 v = p[1] ? p+1 : --argc ? *++argv : NULL;
129 if (!v) {
130 fprintf(stderr, "%s: `-s' requires an argument\n", pname);
131 return 1;
132 }
133 add_sync (readnum (v, &rn_error), 0L);
134 if (rn_error) {
135 fprintf(stderr, "%s: `-s' requires a numeric argument\n",
136 pname);
137 return 1;
138 }
139 p = ""; /* force to next argument */
140 break;
141 case 'e': /* skip a header */
142 v = p[1] ? p+1 : --argc ? *++argv : NULL;
143 if (!v) {
144 fprintf(stderr, "%s: `-e' requires an argument\n", pname);
145 return 1;
146 }
147 initskip = readnum (v, &rn_error);
148 if (rn_error) {
149 fprintf(stderr, "%s: `-e' requires a numeric argument\n",
150 pname);
151 return 1;
152 }
153 p = ""; /* force to next argument */
154 break;
155 case 'k': /* skip a region */
156 v = p[1] ? p+1 : --argc ? *++argv : NULL;
157 if (!v) {
158 fprintf(stderr, "%s: `-k' requires an argument\n", pname);
159 return 1;
160 }
161 vv = strchr(v, ',');
162 if (!vv) {
163 fprintf(stderr, "%s: `-k' requires two numbers separated"
164 " by a comma\n", pname);
165 return 1;
166 }
167 *vv++ = '\0';
168 nextsync = readnum (v, &rn_error);
169 if (rn_error) {
170 fprintf(stderr, "%s: `-k' requires numeric arguments\n",
171 pname);
172 return 1;
173 }
174 synclen = readnum (vv, &rn_error);
175 if (rn_error) {
176 fprintf(stderr, "%s: `-k' requires numeric arguments\n",
177 pname);
178 return 1;
179 }
180 add_sync (nextsync, synclen);
181 p = ""; /* force to next argument */
182 break;
183 }
184 } else if (!filename) {
185 filename = p;
186 } else {
187 fprintf(stderr, "%s: more than one filename specified\n", pname);
188 return 1;
189 }
190 }
191
192 if (!filename) {
193 fprintf(stderr, help, pname);
194 return 0;
195 }
196
197 fp = fopen(filename, "rb");
198 if (!fp) {
199 fprintf(stderr, "%s: unable to open `%s': %s\n",
200 pname, filename, strerror(errno));
201 return 1;
202 }
203 if (initskip > 0)
204 skip (initskip, fp);
205
206 /*
207 * This main loop is really horrible, and wants rewriting with
208 * an axe. It'll stay the way it is for a while though, until I
209 * find the energy...
210 */
211
212 p = q = buffer;
213 nextsync = next_sync (offset, &synclen);
214 do {
215 unsigned long to_read = buffer+sizeof(buffer)-p;
216 if (to_read > nextsync-offset-(p-q))
217 to_read = nextsync-offset-(p-q);
218 lenread = fread (p, 1, to_read, fp);
219 if (lenread == 0)
220 eof = TRUE; /* help along systems with bad feof */
221 p += lenread;
222 if (offset == (long)nextsync) {
223 if (synclen) {
224 printf("%08lX skipping 0x%lX bytes\n", offset, synclen);
225 offset += synclen;
226 skip (synclen, fp);
227 }
228 p = q = buffer;
229 nextsync = next_sync (offset, &synclen);
230 }
231 while (p > q && (p - q >= INSN_MAX || lenread == 0)) {
232 lendis = disasm (q, outbuf, bits, offset, autosync);
233 if (!lendis || lendis > (p - q) ||
234 lendis > (int)(nextsync-offset))
235 lendis = eatbyte (q, outbuf);
236 output_ins (offset, q, lendis, outbuf);
237 q += lendis;
238 offset += lendis;
239 }
240 if (q >= buffer+INSN_MAX) {
241 unsigned char *r = buffer, *s = q;
242 int count = p - q;
243 while (count--)
244 *r++ = *s++;
245 p -= (q - buffer);
246 q = buffer;
247 }
248 } while (lenread > 0 || !(eof || feof(fp)));
249 fclose (fp);
250 return 0;
251 }
252
253 static void output_ins (unsigned long offset, unsigned char *data,
254 int datalen, char *insn) {
255 int bytes;
256 printf("%08lX ", offset);
257
258 bytes = 0;
259 while (datalen > 0 && bytes < BPL) {
260 printf("%02X", *data++);
261 bytes++;
262 datalen--;
263 }
264
265 printf("%*s%s\n", (BPL+1-bytes)*2, "", insn);
266
267 while (datalen > 0) {
268 printf(" -");
269 bytes = 0;
270 while (datalen > 0 && bytes < BPL) {
271 printf("%02X", *data++);
272 bytes++;
273 datalen--;
274 }
275 printf("\n");
276 }
277 }
278
279 /*
280 * Skip a certain amount of data in a file, either by seeking if
281 * possible, or if that fails then by reading and discarding.
282 */
283 static void skip (unsigned long dist, FILE *fp) {
284 char buffer[256]; /* should fit on most stacks :-) */
285
286 /*
287 * Got to be careful with fseek: at least one fseek I've tried
288 * doesn't approve of SEEK_CUR. So I'll use SEEK_SET and
289 * ftell... horrible but apparently necessary.
290 */
291 if (fseek (fp, dist+ftell(fp), SEEK_SET)) {
292 while (dist > 0) {
293 unsigned long len = (dist < sizeof(buffer) ?
294 dist : sizeof(buffer));
295 if (fread (buffer, 1, len, fp) < len) {
296 perror("fread");
297 exit(1);
298 }
299 dist -= len;
300 }
301 }
302 }