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