]>
Commit | Line | Data |
---|---|---|
bbe45369 | 1 | /* udis86 - udcli/udcli.c |
2 | * | |
3 | * Copyright (c) 2002-2009 Vivek Thampi | |
4 | * All rights reserved. | |
5 | * | |
6 | * Redistribution and use in source and binary forms, with or without modification, | |
7 | * are permitted provided that the following conditions are met: | |
8 | * | |
9 | * * Redistributions of source code must retain the above copyright notice, | |
10 | * this list of conditions and the following disclaimer. | |
11 | * * Redistributions in binary form must reproduce the above copyright notice, | |
12 | * this list of conditions and the following disclaimer in the documentation | |
13 | * and/or other materials provided with the distribution. | |
14 | * | |
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
25 | */ | |
26 | #include <stdlib.h> | |
27 | #include <stdio.h> | |
28 | #include <string.h> | |
29 | #include <ctype.h> | |
30 | #include <udis86.h> | |
31 | #include <config.h> | |
32 | ||
33 | #if defined(__amd64__) || defined(__x86_64__) | |
34 | # define FMT "l" | |
35 | #else | |
36 | # define FMT "ll" | |
37 | #endif | |
38 | ||
39 | #if defined(__DJGPP__) || defined(_WIN32) | |
40 | # include <io.h> | |
41 | # include <fcntl.h> | |
42 | #endif | |
43 | ||
44 | #ifdef __DJGPP__ | |
45 | # include <unistd.h> /* for isatty() */ | |
46 | # define _setmode setmode | |
47 | # define _fileno fileno | |
48 | # define _O_BINARY O_BINARY | |
49 | #endif | |
50 | ||
51 | /* help string */ | |
52 | static char help[] = | |
53 | { | |
54 | "Usage: %s [-option[s]] file\n" | |
55 | "Options:\n" | |
56 | " -16 : Set the disassembly mode to 16 bits. \n" | |
57 | " -32 : Set the disassembly mode to 32 bits. (default)\n" | |
58 | " -64 : Set the disassembly mode to 64 bits.\n" | |
59 | " -intel : Set the output to INTEL (NASM like) syntax. (default)\n" | |
60 | " -att : Set the output to AT&T (GAS like) syntax.\n" | |
61 | " -v <v> : Set vendor. <v> = {intel, amd}.\n" | |
62 | " -o <pc> : Set the value of program counter to <pc>. (default = 0)\n" | |
63 | " -s <n> : Set the number of bytes to skip before disassembly to <n>.\n" | |
64 | " -c <n> : Set the number of bytes to disassemble to <n>.\n" | |
65 | " -x : Set the input mode to whitespace seperated 8-bit numbers in\n" | |
66 | " hexadecimal representation. Example: 0f 01 ae 00\n" | |
67 | " -noff : Do not display the offset of instructions.\n" | |
68 | " -nohex : Do not display the hexadecimal code of instructions.\n" | |
69 | " -h : Display this help message.\n" | |
70 | " --version: Show version.\n" | |
71 | "\n" | |
72 | "Udcli is a front-end to the Udis86 Disassembler Library.\n" | |
73 | "http://udis86.sourceforge.net/\n" | |
74 | }; | |
75 | ||
76 | FILE* fptr = NULL; | |
77 | uint64_t o_skip = 0; | |
78 | uint64_t o_count = 0; | |
79 | unsigned char o_do_count= 0; | |
80 | unsigned char o_do_off = 1; | |
81 | unsigned char o_do_hex = 1; | |
82 | unsigned char o_do_x = 0; | |
83 | unsigned o_vendor = UD_VENDOR_AMD; | |
84 | ||
85 | int input_hook_x(ud_t* u); | |
86 | int input_hook_file(ud_t* u); | |
87 | ||
88 | int main(int argc, char **argv) | |
89 | { | |
90 | char *prog_path = *argv; | |
91 | char *s; | |
92 | ud_t ud_obj; | |
93 | int mode = 0; | |
94 | ||
95 | /* initialize */ | |
96 | ud_init(&ud_obj); | |
97 | ud_set_mode(&ud_obj, 32); | |
98 | ud_set_syntax(&ud_obj, UD_SYN_INTEL); | |
99 | ||
100 | #ifdef __DJGPP__ | |
101 | if ( !isatty( fileno( stdin ) ) ) | |
102 | #endif | |
103 | #if defined(__DJGPP) || defined(_WIN32) | |
104 | _setmode(_fileno(stdin), _O_BINARY); | |
105 | #endif | |
106 | ||
107 | fptr = stdin; | |
108 | ||
109 | argv++; | |
110 | ||
111 | /* loop through the args */ | |
112 | while(--argc > 0) { | |
113 | if (strcmp(*argv,"-16") == 0) { | |
114 | ud_set_mode(&ud_obj, 16); | |
115 | mode = 16; | |
116 | } else if (strcmp(*argv,"-32") == 0) { | |
117 | ud_set_mode(&ud_obj, 32); | |
118 | mode = 32; | |
119 | } else if (strcmp(*argv,"-64") == 0) { | |
120 | ud_set_mode(&ud_obj, 64); | |
121 | mode = 64; | |
122 | } else if (strcmp(*argv,"-intel") == 0) | |
123 | ud_set_syntax(&ud_obj, UD_SYN_INTEL); | |
124 | else if (strcmp(*argv,"-att") == 0) | |
125 | ud_set_syntax(&ud_obj, UD_SYN_ATT); | |
126 | else if (strcmp(*argv,"-noff") == 0) | |
127 | o_do_off = 0; | |
128 | else if (strcmp(*argv,"-nohex") == 0) | |
129 | o_do_hex = 0; | |
130 | else if (strcmp(*argv,"-x") == 0) | |
131 | o_do_x = 1; | |
132 | else if (strcmp(*argv,"-s") == 0) | |
133 | if (--argc) { | |
134 | s = *(++argv); | |
135 | if (sscanf(s, "%" FMT "d", &o_skip) == 0) | |
136 | fprintf(stderr, "Invalid value given for -s.\n"); | |
137 | } else { | |
138 | fprintf(stderr, "No value given for -s.\n"); | |
139 | printf(help, prog_path); | |
140 | exit(EXIT_FAILURE); | |
141 | } | |
142 | else if (strcmp(*argv,"-c") == 0) | |
143 | if (--argc) { | |
144 | o_do_count= 1; | |
145 | s = *(++argv); | |
146 | if (sscanf(s, "%" FMT "d", &o_count) == 0) | |
147 | fprintf(stderr, "Invalid value given for -c.\n"); | |
148 | } else { | |
149 | fprintf(stderr, "No value given for -c.\n"); | |
150 | printf(help, prog_path); | |
151 | exit(EXIT_FAILURE); | |
152 | } | |
153 | else if (strcmp(*argv,"-v") == 0) | |
154 | if (--argc) { | |
155 | s = *(++argv); | |
156 | if (*s == 'i') | |
157 | ud_set_vendor(&ud_obj, UD_VENDOR_INTEL); | |
158 | } else { | |
159 | fprintf(stderr, "No value given for -v.\n"); | |
160 | printf(help, prog_path); | |
161 | exit(EXIT_FAILURE); | |
162 | } | |
163 | else if (strcmp(*argv,"-o") == 0) { | |
164 | if (--argc) { | |
165 | uint64_t pc = 0; | |
166 | s = *(++argv); | |
167 | if (sscanf(s, "%" FMT "x", &pc) == 0) | |
168 | fprintf(stderr, "Invalid value given for -o.\n"); | |
169 | ud_set_pc(&ud_obj, pc); | |
170 | } else { | |
171 | fprintf(stderr, "No value given for -o.\n"); | |
172 | printf(help, prog_path); | |
173 | exit(EXIT_FAILURE); | |
174 | } | |
175 | } else if ( strcmp( *argv, "--version" ) == 0 ) { | |
176 | fprintf(stderr, "%s\n", PACKAGE_STRING ); | |
177 | exit(0); | |
178 | } else if((*argv)[0] == '-') { | |
179 | fprintf(stderr, "Invalid option %s.\n", *argv); | |
180 | printf(help, prog_path); | |
181 | exit(EXIT_FAILURE); | |
182 | } else { | |
183 | static int i = 0; | |
184 | s = *argv; | |
185 | if (i) { | |
186 | fprintf(stderr, "Multiple files specified.\n"); | |
187 | exit(EXIT_FAILURE); | |
188 | } else i = 1; | |
189 | if ((fptr = fopen(s, "rb")) == NULL) { | |
190 | fprintf(stderr, "Failed to open file: %s.\n", s); | |
191 | exit(EXIT_FAILURE); | |
192 | } | |
193 | } | |
194 | argv++; | |
195 | } | |
196 | ||
197 | if (o_do_x) | |
198 | ud_set_input_hook(&ud_obj, input_hook_x); | |
199 | else ud_set_input_hook(&ud_obj, input_hook_file); | |
200 | ||
201 | if (o_skip) { | |
202 | o_count += o_skip; | |
203 | ud_input_skip(&ud_obj, o_skip); | |
204 | } | |
205 | ||
206 | /* disassembly loop */ | |
207 | while (ud_disassemble(&ud_obj)) { | |
208 | if (o_do_off) | |
209 | printf("%016" FMT "x ", ud_insn_off(&ud_obj)); | |
210 | if (o_do_hex) { | |
211 | char* hex1, *hex2; | |
212 | char c; | |
213 | hex1 = ud_insn_hex(&ud_obj); | |
214 | hex2 = hex1 + 16; | |
215 | c = hex1[16]; | |
216 | hex1[16] = 0; | |
217 | printf("%-16s %-24s", hex1, ud_insn_asm(&ud_obj)); | |
218 | hex1[16] = c; | |
219 | if (strlen(hex1) > 16) { | |
220 | printf("\n"); | |
221 | if (o_do_off) | |
222 | printf("%15s -", ""); | |
223 | printf("%-16s", hex2); | |
224 | } | |
225 | } | |
226 | else printf(" %-24s", ud_insn_asm(&ud_obj)); | |
227 | ||
228 | printf("\n"); | |
229 | } | |
230 | ||
231 | exit(EXIT_SUCCESS); | |
232 | return 0; | |
233 | } | |
234 | ||
235 | int input_hook_x(ud_t* u) | |
236 | { | |
237 | unsigned int c, i; | |
238 | ||
239 | if (o_do_count) { | |
240 | if (! o_count) | |
241 | return UD_EOI; | |
242 | else --o_count; | |
243 | } | |
244 | ||
245 | i = fscanf(fptr, "%x", &c); | |
246 | ||
247 | if (i == EOF) | |
248 | return UD_EOI; | |
249 | if (i == 0) { | |
250 | fprintf(stderr, "Error: Invalid input, should be in hexadecimal form (8-bit).\n"); | |
251 | return UD_EOI; | |
252 | } | |
253 | if (c > 0xFF) | |
254 | fprintf(stderr, "Warning: Casting non-8-bit input (%x), to %x.\n", c, c & 0xFF); | |
255 | return (int) (c & 0xFF); | |
256 | } | |
257 | ||
258 | int input_hook_file(ud_t* u) | |
259 | { | |
260 | int c; | |
261 | ||
262 | if (o_do_count) { | |
263 | if (! o_count) { | |
264 | return -1; | |
265 | } else o_count -- ; | |
266 | } | |
267 | ||
268 | if ((c = fgetc(fptr)) == EOF) | |
269 | return UD_EOI; | |
270 | return c; | |
271 | } |