Home | History | Annotate | Download | only in libudis86
      1 /* udis86 - libudis86/syn.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 #include "types.h"
     27 #include "decode.h"
     28 #include "syn.h"
     29 #include "udint.h"
     30 
     31 /* -----------------------------------------------------------------------------
     32  * Intel Register Table - Order Matters (types.h)!
     33  * -----------------------------------------------------------------------------
     34  */
     35 const char* ud_reg_tab[] =
     36 {
     37   "al",   "cl",   "dl",   "bl",
     38   "ah",   "ch",   "dh",   "bh",
     39   "spl",  "bpl",    "sil",    "dil",
     40   "r8b",  "r9b",    "r10b",   "r11b",
     41   "r12b", "r13b",   "r14b",   "r15b",
     42 
     43   "ax",   "cx",   "dx",   "bx",
     44   "sp",   "bp",   "si",   "di",
     45   "r8w",  "r9w",    "r10w",   "r11w",
     46   "r12w", "r13w"  , "r14w",   "r15w",
     47 
     48   "eax",  "ecx",    "edx",    "ebx",
     49   "esp",  "ebp",    "esi",    "edi",
     50   "r8d",  "r9d",    "r10d",   "r11d",
     51   "r12d", "r13d",   "r14d",   "r15d",
     52 
     53   "rax",  "rcx",    "rdx",    "rbx",
     54   "rsp",  "rbp",    "rsi",    "rdi",
     55   "r8",   "r9",   "r10",    "r11",
     56   "r12",  "r13",    "r14",    "r15",
     57 
     58   "es",   "cs",   "ss",   "ds",
     59   "fs",   "gs",
     60 
     61   "cr0",  "cr1",    "cr2",    "cr3",
     62   "cr4",  "cr5",    "cr6",    "cr7",
     63   "cr8",  "cr9",    "cr10",   "cr11",
     64   "cr12", "cr13",   "cr14",   "cr15",
     65 
     66   "dr0",  "dr1",    "dr2",    "dr3",
     67   "dr4",  "dr5",    "dr6",    "dr7",
     68   "dr8",  "dr9",    "dr10",   "dr11",
     69   "dr12", "dr13",   "dr14",   "dr15",
     70 
     71   "mm0",  "mm1",    "mm2",    "mm3",
     72   "mm4",  "mm5",    "mm6",    "mm7",
     73 
     74   "st0",  "st1",    "st2",    "st3",
     75   "st4",  "st5",    "st6",    "st7",
     76 
     77   "xmm0", "xmm1",   "xmm2",   "xmm3",
     78   "xmm4", "xmm5",   "xmm6",   "xmm7",
     79   "xmm8", "xmm9",   "xmm10",  "xmm11",
     80   "xmm12",  "xmm13",  "xmm14",  "xmm15",
     81 
     82   "rip"
     83 };
     84 
     85 
     86 uint64_t
     87 ud_syn_rel_target(struct ud *u, struct ud_operand *opr)
     88 {
     89   const uint64_t trunc_mask = 0xffffffffffffffffull >> (64 - u->opr_mode);
     90   switch (opr->size) {
     91   case 8 : return (u->pc + opr->lval.sbyte)  & trunc_mask;
     92   case 16: return (u->pc + opr->lval.sword)  & trunc_mask;
     93   case 32: return (u->pc + opr->lval.sdword) & trunc_mask;
     94   default: UD_ASSERT(!"invalid relative offset size.");
     95   }
     96 }
     97 
     98 
     99 /*
    100  * asmprintf
    101  *    Printf style function for printing translated assembly
    102  *    output. Returns the number of characters written and
    103  *    moves the buffer pointer forward. On an overflow,
    104  *    returns a negative number and truncates the output.
    105  */
    106 int
    107 ud_asmprintf(struct ud *u, char *fmt, ...)
    108 {
    109   int ret;
    110   int avail;
    111   va_list ap;
    112   va_start(ap, fmt);
    113   avail = u->asm_buf_size - u->asm_buf_fill - 1 /* nullchar */;
    114   ret = vsnprintf((char*) u->asm_buf + u->asm_buf_fill, avail, fmt, ap);
    115   if (ret < 0 || ret > avail) {
    116       u->asm_buf_fill = u->asm_buf_size - 1;
    117   } else {
    118       u->asm_buf_fill += ret;
    119   }
    120   va_end(ap);
    121   return ret;
    122 }
    123 
    124 
    125 void
    126 ud_syn_print_addr(struct ud *u, uint64_t addr)
    127 {
    128   const char *name = NULL;
    129   if (u->sym_resolver) {
    130     int64_t offset = 0;
    131     name = u->sym_resolver(u, addr, &offset);
    132     if (name) {
    133       if (offset) {
    134         ud_asmprintf(u, "%s%+" FMT64 "d", name, offset);
    135       } else {
    136         ud_asmprintf(u, "%s", name);
    137       }
    138       return;
    139     }
    140   }
    141   ud_asmprintf(u, "0x%" FMT64 "x", addr);
    142 }
    143 
    144 
    145 void
    146 ud_syn_print_imm(struct ud* u, const struct ud_operand *op)
    147 {
    148   uint64_t v;
    149   if (op->_oprcode == OP_sI && op->size != u->opr_mode) {
    150     if (op->size == 8) {
    151       v = (int64_t)op->lval.sbyte;
    152     } else {
    153       UD_ASSERT(op->size == 32);
    154       v = (int64_t)op->lval.sdword;
    155     }
    156     if (u->opr_mode < 64) {
    157       v = v & ((1ull << u->opr_mode) - 1ull);
    158     }
    159   } else {
    160     switch (op->size) {
    161     case 8 : v = op->lval.ubyte;  break;
    162     case 16: v = op->lval.uword;  break;
    163     case 32: v = op->lval.udword; break;
    164     case 64: v = op->lval.uqword; break;
    165     default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
    166     }
    167   }
    168   ud_asmprintf(u, "0x%" FMT64 "x", v);
    169 }
    170 
    171 
    172 void
    173 ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign)
    174 {
    175   UD_ASSERT(op->offset != 0);
    176  if (op->base == UD_NONE && op->index == UD_NONE) {
    177     uint64_t v;
    178     UD_ASSERT(op->scale == UD_NONE && op->offset != 8);
    179     /* unsigned mem-offset */
    180     switch (op->offset) {
    181     case 16: v = op->lval.uword;  break;
    182     case 32: v = op->lval.udword; break;
    183     case 64: v = op->lval.uqword; break;
    184     default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
    185     }
    186     ud_asmprintf(u, "0x%" FMT64 "x", v);
    187   } else {
    188     int64_t v;
    189     UD_ASSERT(op->offset != 64);
    190     switch (op->offset) {
    191     case 8 : v = op->lval.sbyte;  break;
    192     case 16: v = op->lval.sword;  break;
    193     case 32: v = op->lval.sdword; break;
    194     default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
    195     }
    196     if (v < 0) {
    197       ud_asmprintf(u, "-0x%" FMT64 "x", -v);
    198     } else if (v > 0) {
    199       ud_asmprintf(u, "%s0x%" FMT64 "x", sign? "+" : "", v);
    200     }
    201   }
    202 }
    203 
    204 /*
    205 vim: set ts=2 sw=2 expandtab
    206 */
    207