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
39static void ud_inp_init(struct ud *u);
40
41/* =============================================================================
42 * ud_init
43 * Initializes ud_t object.
44 * =============================================================================
45 */
46extern void
47ud_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 */
67extern unsigned int
68ud_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 */
88extern void
89ud_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 */
103extern void
104ud_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 */
122extern void
123ud_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 */
132extern void
133ud_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 */
142const char*
143ud_insn_asm(const struct ud* u)
144{
145 return u->asm_buf;
146}
147
148/* =============================================================================
149 * ud_insn_offset() - Returns the offset.
150 * =============================================================================
151 */
152uint64_t
153ud_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 */
163const char*
164ud_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 */
189extern const uint8_t*
190ud_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 */
202extern unsigned int
203ud_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 */
216const struct ud_operand*
217ud_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 */
232int
233ud_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 */
247int
248ud_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 */
262void
263ud_set_user_opaque_data(struct ud * u, void* opaque)
264{
265 u->user_opaque_data = opaque;
266}
267
268void*
269ud_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 */
281void
282ud_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 */
308void
309ud_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 */
322enum ud_mnemonic_code
323ud_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 */
335const char*
336ud_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 */
350static void
351ud_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 */
370void
371ud_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 */
382void
383ud_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 */
398static int
399inp_file_hook(struct ud* u)
400{
401 return fgetc(u->inp_file);
402}
403
404void
405ud_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 */
419void
420ud_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 }
442eoi:
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 */
454int
455ud_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