1 | /* udis86 - libudis86/udis86.c |
2 | * |
3 | * Copyright (c) 2002-2013 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 | |
27 | #include "config.h" |
28 | |
29 | #if USE(UDIS86) |
30 | |
31 | #include "udis86_udint.h" |
32 | #include "udis86_extern.h" |
33 | #include "udis86_decode.h" |
34 | |
35 | #if !defined(__UD_STANDALONE__) |
36 | #include <string.h> |
37 | #endif /* !__UD_STANDALONE__ */ |
38 | |
39 | static void ud_inp_init(struct ud *u); |
40 | |
41 | /* ============================================================================= |
42 | * ud_init |
43 | * Initializes ud_t object. |
44 | * ============================================================================= |
45 | */ |
46 | extern void |
47 | ud_init(struct ud* u) |
48 | { |
49 | memset((void*)u, 0, sizeof(struct ud)); |
50 | ud_set_mode(u, 16); |
51 | u->mnemonic = UD_Iinvalid; |
52 | ud_set_pc(u, 0); |
53 | #ifndef __UD_STANDALONE__ |
54 | ud_set_input_file(u, stdin); |
55 | #endif /* __UD_STANDALONE__ */ |
56 | |
57 | ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); |
58 | } |
59 | |
60 | |
61 | /* ============================================================================= |
62 | * ud_disassemble |
63 | * Disassembles one instruction and returns the number of |
64 | * bytes disassembled. A zero means end of disassembly. |
65 | * ============================================================================= |
66 | */ |
67 | extern unsigned int |
68 | ud_disassemble(struct ud* u) |
69 | { |
70 | int len; |
71 | if (u->inp_end) { |
72 | return 0; |
73 | } |
74 | if ((len = ud_decode(u)) > 0) { |
75 | if (u->translator != NULL) { |
76 | u->asm_buf[0] = '\0'; |
77 | u->translator(u); |
78 | } |
79 | } |
80 | return len; |
81 | } |
82 | |
83 | |
84 | /* ============================================================================= |
85 | * ud_set_mode() - Set Disassemly Mode. |
86 | * ============================================================================= |
87 | */ |
88 | extern void |
89 | ud_set_mode(struct ud* u, uint8_t m) |
90 | { |
91 | switch(m) { |
92 | case 16: |
93 | case 32: |
94 | case 64: u->dis_mode = m ; return; |
95 | default: u->dis_mode = 16; return; |
96 | } |
97 | } |
98 | |
99 | /* ============================================================================= |
100 | * ud_set_vendor() - Set vendor. |
101 | * ============================================================================= |
102 | */ |
103 | extern void |
104 | ud_set_vendor(struct ud* u, unsigned v) |
105 | { |
106 | switch(v) { |
107 | case UD_VENDOR_INTEL: |
108 | u->vendor = v; |
109 | break; |
110 | case UD_VENDOR_ANY: |
111 | u->vendor = v; |
112 | break; |
113 | default: |
114 | u->vendor = UD_VENDOR_AMD; |
115 | } |
116 | } |
117 | |
118 | /* ============================================================================= |
119 | * ud_set_pc() - Sets code origin. |
120 | * ============================================================================= |
121 | */ |
122 | extern void |
123 | ud_set_pc(struct ud* u, uint64_t o) |
124 | { |
125 | u->pc = o; |
126 | } |
127 | |
128 | /* ============================================================================= |
129 | * ud_set_syntax() - Sets the output syntax. |
130 | * ============================================================================= |
131 | */ |
132 | extern void |
133 | ud_set_syntax(struct ud* u, void (*t)(struct ud*)) |
134 | { |
135 | u->translator = t; |
136 | } |
137 | |
138 | /* ============================================================================= |
139 | * ud_insn() - returns the disassembled instruction |
140 | * ============================================================================= |
141 | */ |
142 | const char* |
143 | ud_insn_asm(const struct ud* u) |
144 | { |
145 | return u->asm_buf; |
146 | } |
147 | |
148 | /* ============================================================================= |
149 | * ud_insn_offset() - Returns the offset. |
150 | * ============================================================================= |
151 | */ |
152 | uint64_t |
153 | ud_insn_off(const struct ud* u) |
154 | { |
155 | return u->insn_offset; |
156 | } |
157 | |
158 | |
159 | /* ============================================================================= |
160 | * ud_insn_hex() - Returns hex form of disassembled instruction. |
161 | * ============================================================================= |
162 | */ |
163 | const char* |
164 | ud_insn_hex(struct ud* u) |
165 | { |
166 | u->insn_hexcode[0] = 0; |
167 | if (!u->error) { |
168 | unsigned int i; |
169 | const unsigned char *src_ptr = ud_insn_ptr(u); |
170 | char* src_hex = (char*) u->insn_hexcode; |
171 | char* const src_hex_base = src_hex; |
172 | /* for each byte used to decode instruction */ |
173 | for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2; |
174 | ++i, ++src_ptr) { |
175 | snprintf(src_hex, sizeof(u->insn_hexcode) - (src_hex - src_hex_base), "%02x" , *src_ptr & 0xFF); |
176 | src_hex += 2; |
177 | } |
178 | } |
179 | return u->insn_hexcode; |
180 | } |
181 | |
182 | |
183 | /* ============================================================================= |
184 | * ud_insn_ptr |
185 | * Returns a pointer to buffer containing the bytes that were |
186 | * disassembled. |
187 | * ============================================================================= |
188 | */ |
189 | extern const uint8_t* |
190 | ud_insn_ptr(const struct ud* u) |
191 | { |
192 | return (u->inp_buf == NULL) ? |
193 | u->inp_sess : u->inp_buf + (u->inp_buf_index - u->inp_ctr); |
194 | } |
195 | |
196 | |
197 | /* ============================================================================= |
198 | * ud_insn_len |
199 | * Returns the count of bytes disassembled. |
200 | * ============================================================================= |
201 | */ |
202 | extern unsigned int |
203 | ud_insn_len(const struct ud* u) |
204 | { |
205 | return u->inp_ctr; |
206 | } |
207 | |
208 | |
209 | /* ============================================================================= |
210 | * ud_insn_get_opr |
211 | * Return the operand struct representing the nth operand of |
212 | * the currently disassembled instruction. Returns NULL if |
213 | * there's no such operand. |
214 | * ============================================================================= |
215 | */ |
216 | const struct ud_operand* |
217 | ud_insn_opr(const struct ud *u, unsigned int n) |
218 | { |
219 | if (n > 3 || u->operand[n].type == UD_NONE) { |
220 | return NULL; |
221 | } else { |
222 | return &u->operand[n]; |
223 | } |
224 | } |
225 | |
226 | |
227 | /* ============================================================================= |
228 | * ud_opr_is_sreg |
229 | * Returns non-zero if the given operand is of a segment register type. |
230 | * ============================================================================= |
231 | */ |
232 | int |
233 | ud_opr_is_sreg(const struct ud_operand *opr) |
234 | { |
235 | return opr->type == UD_OP_REG && |
236 | opr->base >= UD_R_ES && |
237 | opr->base <= UD_R_GS; |
238 | } |
239 | |
240 | |
241 | /* ============================================================================= |
242 | * ud_opr_is_sreg |
243 | * Returns non-zero if the given operand is of a general purpose |
244 | * register type. |
245 | * ============================================================================= |
246 | */ |
247 | int |
248 | ud_opr_is_gpr(const struct ud_operand *opr) |
249 | { |
250 | return opr->type == UD_OP_REG && |
251 | opr->base >= UD_R_AL && |
252 | opr->base <= UD_R_R15; |
253 | } |
254 | |
255 | |
256 | /* ============================================================================= |
257 | * ud_set_user_opaque_data |
258 | * ud_get_user_opaque_data |
259 | * Get/set user opaqute data pointer |
260 | * ============================================================================= |
261 | */ |
262 | void |
263 | ud_set_user_opaque_data(struct ud * u, void* opaque) |
264 | { |
265 | u->user_opaque_data = opaque; |
266 | } |
267 | |
268 | void* |
269 | ud_get_user_opaque_data(const struct ud *u) |
270 | { |
271 | return u->user_opaque_data; |
272 | } |
273 | |
274 | |
275 | /* ============================================================================= |
276 | * ud_set_asm_buffer |
277 | * Allow the user to set an assembler output buffer. If `buf` is NULL, |
278 | * we switch back to the internal buffer. |
279 | * ============================================================================= |
280 | */ |
281 | void |
282 | ud_set_asm_buffer(struct ud *u, char *buf, size_t size) |
283 | { |
284 | if (buf == NULL) { |
285 | ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); |
286 | } else { |
287 | u->asm_buf = buf; |
288 | u->asm_buf_size = size; |
289 | } |
290 | } |
291 | |
292 | |
293 | /* ============================================================================= |
294 | * ud_set_sym_resolver |
295 | * Set symbol resolver for relative targets used in the translation |
296 | * phase. |
297 | * |
298 | * The resolver is a function that takes a uint64_t address and returns a |
299 | * symbolic name for the that address. The function also takes a second |
300 | * argument pointing to an integer that the client can optionally set to a |
301 | * non-zero value for offsetted targets. (symbol+offset) The function may |
302 | * also return NULL, in which case the translator only prints the target |
303 | * address. |
304 | * |
305 | * The function pointer maybe NULL which resets symbol resolution. |
306 | * ============================================================================= |
307 | */ |
308 | void |
309 | ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*, |
310 | uint64_t addr, |
311 | int64_t *offset)) |
312 | { |
313 | u->sym_resolver = resolver; |
314 | } |
315 | |
316 | |
317 | /* ============================================================================= |
318 | * ud_insn_mnemonic |
319 | * Return the current instruction mnemonic. |
320 | * ============================================================================= |
321 | */ |
322 | enum ud_mnemonic_code |
323 | ud_insn_mnemonic(const struct ud *u) |
324 | { |
325 | return u->mnemonic; |
326 | } |
327 | |
328 | |
329 | /* ============================================================================= |
330 | * ud_lookup_mnemonic |
331 | * Looks up mnemonic code in the mnemonic string table. |
332 | * Returns NULL if the mnemonic code is invalid. |
333 | * ============================================================================= |
334 | */ |
335 | const char* |
336 | ud_lookup_mnemonic(enum ud_mnemonic_code c) |
337 | { |
338 | if (c < UD_MAX_MNEMONIC_CODE) { |
339 | return ud_mnemonics_str[c]; |
340 | } else { |
341 | return NULL; |
342 | } |
343 | } |
344 | |
345 | |
346 | /* |
347 | * ud_inp_init |
348 | * Initializes the input system. |
349 | */ |
350 | static void |
351 | ud_inp_init(struct ud *u) |
352 | { |
353 | u->inp_hook = NULL; |
354 | u->inp_buf = NULL; |
355 | u->inp_buf_size = 0; |
356 | u->inp_buf_index = 0; |
357 | u->inp_curr = 0; |
358 | u->inp_ctr = 0; |
359 | u->inp_end = 0; |
360 | u->inp_peek = UD_EOI; |
361 | UD_NON_STANDALONE(u->inp_file = NULL); |
362 | } |
363 | |
364 | |
365 | /* ============================================================================= |
366 | * ud_inp_set_hook |
367 | * Sets input hook. |
368 | * ============================================================================= |
369 | */ |
370 | void |
371 | ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) |
372 | { |
373 | ud_inp_init(u); |
374 | u->inp_hook = hook; |
375 | } |
376 | |
377 | /* ============================================================================= |
378 | * ud_inp_set_buffer |
379 | * Set buffer as input. |
380 | * ============================================================================= |
381 | */ |
382 | void |
383 | ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len) |
384 | { |
385 | ud_inp_init(u); |
386 | u->inp_buf = buf; |
387 | u->inp_buf_size = len; |
388 | u->inp_buf_index = 0; |
389 | } |
390 | |
391 | |
392 | #ifndef __UD_STANDALONE__ |
393 | /* ============================================================================= |
394 | * ud_input_set_file |
395 | * Set FILE as input. |
396 | * ============================================================================= |
397 | */ |
398 | static int |
399 | inp_file_hook(struct ud* u) |
400 | { |
401 | return fgetc(u->inp_file); |
402 | } |
403 | |
404 | void |
405 | ud_set_input_file(register struct ud* u, FILE* f) |
406 | { |
407 | ud_inp_init(u); |
408 | u->inp_hook = inp_file_hook; |
409 | u->inp_file = f; |
410 | } |
411 | #endif /* __UD_STANDALONE__ */ |
412 | |
413 | |
414 | /* ============================================================================= |
415 | * ud_input_skip |
416 | * Skip n input bytes. |
417 | * ============================================================================ |
418 | */ |
419 | void |
420 | ud_input_skip(struct ud* u, size_t n) |
421 | { |
422 | if (u->inp_end) { |
423 | return; |
424 | } |
425 | if (u->inp_buf == NULL) { |
426 | while (n--) { |
427 | int c = u->inp_hook(u); |
428 | if (c == UD_EOI) { |
429 | goto eoi; |
430 | } |
431 | } |
432 | return; |
433 | } else { |
434 | if (n > u->inp_buf_size || |
435 | u->inp_buf_index > u->inp_buf_size - n) { |
436 | u->inp_buf_index = u->inp_buf_size; |
437 | goto eoi; |
438 | } |
439 | u->inp_buf_index += n; |
440 | return; |
441 | } |
442 | eoi: |
443 | u->inp_end = 1; |
444 | UDERR(u, "cannot skip, eoi received\b" ); |
445 | return; |
446 | } |
447 | |
448 | |
449 | /* ============================================================================= |
450 | * ud_input_end |
451 | * Returns non-zero on end-of-input. |
452 | * ============================================================================= |
453 | */ |
454 | int |
455 | ud_input_end(const struct ud *u) |
456 | { |
457 | return u->inp_end; |
458 | } |
459 | |
460 | #endif // USE(UDIS86) |
461 | |
462 | /* vim:set ts=2 sw=2 expandtab */ |
463 | |