1
|
1 /* -----------------------------------------------------------------------------
|
|
2 * udcli.c - front end to udis86.
|
|
3 *
|
|
4 * Copyright (c) 2004, 2005, 2006 Vivek Mohan <vivek@sig9.com>
|
|
5 * All rights reserved.
|
|
6 * See (LICENSE)
|
|
7 * -----------------------------------------------------------------------------
|
|
8 */
|
|
9
|
|
10 #include <stdlib.h>
|
|
11 #include <stdio.h>
|
|
12 #include <string.h>
|
|
13 #include <ctype.h>
|
|
14 #include "../udis86.h"
|
|
15
|
|
16 #if defined(__amd64__) || defined(__x86_64__)
|
|
17 # define FMT "l"
|
|
18 #else
|
|
19 # define FMT "ll"
|
|
20 #endif
|
|
21
|
|
22 #ifdef _WIN32
|
|
23 # include <io.h>
|
|
24 # include <fcntl.h>
|
|
25 #endif
|
|
26
|
|
27 /* help string */
|
|
28 static char help[] =
|
|
29 {
|
|
30 "Usage: %s [-option[s]] file\n"
|
|
31 "Options:\n"
|
|
32 " -16 : Set the disassembly mode to 16 bits. \n"
|
|
33 " -32 : Set the disassembly mode to 32 bits. (default)\n"
|
|
34 " -64 : Set the disassembly mode to 64 bits.\n"
|
|
35 " -intel : Set the output to INTEL (NASM like) syntax. (default)\n"
|
|
36 " -att : Set the output to AT&T (GAS like) syntax.\n"
|
|
37 " -v <v> : Set vendor. <v> = {intel, amd}.\n"
|
|
38 " -o <pc> : Set the value of program counter to <pc>. (default = 0)\n"
|
|
39 " -s <n> : Set the number of bytes to skip before disassembly to <n>.\n"
|
|
40 " -c <n> : Set the number of bytes to disassemble to <n>.\n"
|
|
41 " -x : Set the input mode to whitespace seperated 8-bit numbers in\n"
|
|
42 " hexadecimal representation. Example: 0f 01 ae 00\n"
|
|
43 " -noff : Do not display the offset of instructions.\n"
|
|
44 " -nohex : Do not display the hexadecimal code of instructions.\n"
|
|
45 " -h : Display this help message.\n"
|
|
46 "\n"
|
|
47 "Udcli is a front-end to the Udis86 Disassembler Library.\n"
|
|
48 "http://udis86.sourceforge.net/\n"
|
|
49 };
|
|
50
|
|
51 FILE* fptr = NULL;
|
|
52 uint64_t o_skip = 0;
|
|
53 uint64_t o_count = 0;
|
|
54 unsigned char o_do_count= 0;
|
|
55 unsigned char o_do_off = 1;
|
|
56 unsigned char o_do_hex = 1;
|
|
57 unsigned char o_do_x = 0;
|
|
58 unsigned o_vendor = UD_VENDOR_AMD;
|
|
59
|
|
60 int input_hook_x(ud_t* u);
|
|
61 int input_hook_file(ud_t* u);
|
|
62
|
|
63 int main(int argc, char **argv)
|
|
64 {
|
|
65 char *prog_path = *argv;
|
|
66 char *s;
|
|
67 ud_t ud_obj;
|
|
68 int mode = 0;
|
|
69
|
|
70 /* initialize */
|
|
71 ud_init(&ud_obj);
|
|
72 ud_set_mode(&ud_obj, 32);
|
|
73 ud_set_syntax(&ud_obj, UD_SYN_INTEL);
|
|
74
|
|
75 #ifdef _WIN32
|
|
76 _setmode(_fileno(stdin), _O_BINARY);
|
|
77 #endif
|
|
78
|
|
79 fptr = stdin;
|
|
80
|
|
81 argv++;
|
|
82
|
|
83 /* loop through the args */
|
|
84 while(--argc > 0) {
|
|
85 if (strcmp(*argv,"-16") == 0) {
|
|
86 ud_set_mode(&ud_obj, 16);
|
|
87 mode = 16;
|
|
88 } else if (strcmp(*argv,"-32") == 0) {
|
|
89 ud_set_mode(&ud_obj, 32);
|
|
90 mode = 32;
|
|
91 } else if (strcmp(*argv,"-64") == 0) {
|
|
92 ud_set_mode(&ud_obj, 64);
|
|
93 mode = 64;
|
|
94 } else if (strcmp(*argv,"-intel") == 0)
|
|
95 ud_set_syntax(&ud_obj, UD_SYN_INTEL);
|
|
96 else if (strcmp(*argv,"-att") == 0)
|
|
97 ud_set_syntax(&ud_obj, UD_SYN_ATT);
|
|
98 else if (strcmp(*argv,"-noff") == 0)
|
|
99 o_do_off = 0;
|
|
100 else if (strcmp(*argv,"-nohex") == 0)
|
|
101 o_do_hex = 0;
|
|
102 else if (strcmp(*argv,"-x") == 0)
|
|
103 o_do_x = 1;
|
|
104 else if (strcmp(*argv,"-s") == 0)
|
|
105 if (--argc) {
|
|
106 s = *(++argv);
|
|
107 if (sscanf(s, "%" FMT "d", &o_skip) == 0)
|
|
108 fprintf(stderr, "Invalid value given for -s.\n");
|
|
109 } else {
|
|
110 fprintf(stderr, "No value given for -s.\n");
|
|
111 printf(help, prog_path);
|
|
112 exit(EXIT_FAILURE);
|
|
113 }
|
|
114 else if (strcmp(*argv,"-c") == 0)
|
|
115 if (--argc) {
|
|
116 o_do_count= 1;
|
|
117 s = *(++argv);
|
|
118 if (sscanf(s, "%" FMT "d", &o_count) == 0)
|
|
119 fprintf(stderr, "Invalid value given for -c.\n");
|
|
120 } else {
|
|
121 fprintf(stderr, "No value given for -c.\n");
|
|
122 printf(help, prog_path);
|
|
123 exit(EXIT_FAILURE);
|
|
124 }
|
|
125 else if (strcmp(*argv,"-v") == 0)
|
|
126 if (--argc) {
|
|
127 s = *(++argv);
|
|
128 if (*s == 'i')
|
|
129 ud_set_vendor(&ud_obj, UD_VENDOR_INTEL);
|
|
130 } else {
|
|
131 fprintf(stderr, "No value given for -v.\n");
|
|
132 printf(help, prog_path);
|
|
133 exit(EXIT_FAILURE);
|
|
134 }
|
|
135 else if (strcmp(*argv,"-o") == 0) {
|
|
136 if (--argc) {
|
|
137 uint64_t pc = 0;
|
|
138 s = *(++argv);
|
|
139 if (sscanf(s, "%" FMT "x", &pc) == 0)
|
|
140 fprintf(stderr, "Invalid value given for -o.\n");
|
|
141 ud_set_pc(&ud_obj, pc);
|
|
142 } else {
|
|
143 fprintf(stderr, "No value given for -o.\n");
|
|
144 printf(help, prog_path);
|
|
145 exit(EXIT_FAILURE);
|
|
146 }
|
|
147 } else if((*argv)[0] == '-') {
|
|
148 fprintf(stderr, "Invalid option %s.\n", *argv);
|
|
149 printf(help, prog_path);
|
|
150 exit(EXIT_FAILURE);
|
|
151 } else {
|
|
152 static int i = 0;
|
|
153 s = *argv;
|
|
154 if (i) {
|
|
155 fprintf(stderr, "Multiple files specified.\n");
|
|
156 exit(EXIT_FAILURE);
|
|
157 } else i = 1;
|
|
158 if ((fptr = fopen(s, "rb")) == NULL) {
|
|
159 fprintf(stderr, "Failed to open file: %s.\n", s);
|
|
160 exit(EXIT_FAILURE);
|
|
161 }
|
|
162 }
|
|
163 argv++;
|
|
164 }
|
|
165
|
|
166 if (o_do_x)
|
|
167 ud_set_input_hook(&ud_obj, input_hook_x);
|
|
168 else ud_set_input_hook(&ud_obj, input_hook_file);
|
|
169
|
|
170 if (o_skip) {
|
|
171 o_count += o_skip;
|
|
172 ud_input_skip(&ud_obj, o_skip);
|
|
173 }
|
|
174
|
|
175 /* disassembly loop */
|
|
176 while (ud_disassemble(&ud_obj)) {
|
|
177 if (o_do_off)
|
|
178 printf("%016" FMT "x ", ud_insn_off(&ud_obj));
|
|
179 if (o_do_hex) {
|
|
180 char* hex1, *hex2;
|
|
181 char c;
|
|
182 hex1 = ud_insn_hex(&ud_obj);
|
|
183 hex2 = hex1 + 16;
|
|
184 c = hex1[16];
|
|
185 hex1[16] = 0;
|
|
186 printf("%-16s %-24s", hex1, ud_insn_asm(&ud_obj));
|
|
187 hex1[16] = c;
|
|
188 if (strlen(hex1) > 16) {
|
|
189 printf("\n");
|
|
190 if (o_do_off)
|
|
191 printf("%15s -", "");
|
|
192 printf("%-16s", hex2);
|
|
193 }
|
|
194 }
|
|
195 else printf(" %-24s", ud_insn_asm(&ud_obj));
|
|
196
|
|
197 printf("\n");
|
|
198 }
|
|
199
|
|
200 exit(EXIT_SUCCESS);
|
|
201 return 0;
|
|
202 }
|
|
203
|
|
204 int input_hook_x(ud_t* u)
|
|
205 {
|
|
206 unsigned int c, i;
|
|
207
|
|
208 if (o_do_count) {
|
|
209 if (! o_count)
|
|
210 return UD_EOI;
|
|
211 else --o_count;
|
|
212 }
|
|
213
|
|
214 i = fscanf(fptr, "%x", &c);
|
|
215
|
|
216 if (i == EOF)
|
|
217 return UD_EOI;
|
|
218 if (i == 0) {
|
|
219 fprintf(stderr, "Error: Invalid input, should be in hexadecimal form (8-bit).\n");
|
|
220 return UD_EOI;
|
|
221 }
|
|
222 if (c > 0xFF)
|
|
223 fprintf(stderr, "Warning: Casting non-8-bit input (%x), to %x.\n", c, c & 0xFF);
|
|
224 return (int) (c & 0xFF);
|
|
225 }
|
|
226
|
|
227 int input_hook_file(ud_t* u)
|
|
228 {
|
|
229 int c;
|
|
230
|
|
231 if (o_do_count) {
|
|
232 if (! o_count) {
|
|
233 return -1;
|
|
234 } else o_count -- ;
|
|
235 }
|
|
236
|
|
237 if ((c = fgetc(fptr)) == EOF)
|
|
238 return UD_EOI;
|
|
239 return c;
|
|
240 }
|