├── Makefile ├── README.md ├── hello_core.c ├── inl_hook.c ├── inl_hook.h ├── udis86 ├── decode.c ├── decode.h ├── extern.h ├── itab.c ├── itab.h ├── syn-att.c ├── syn-intel.c ├── syn.c ├── syn.h ├── types.h ├── udint.h ├── udis86.c └── udis86.h ├── util.c └── util.h /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for the ipvs modules. 3 | # 4 | 5 | obj-m += hello.o 6 | 7 | KDIR := ~/linux-3.10.0-514.26.2.el7 8 | PWD := $(shell pwd) 9 | 10 | EXTRA_CFLAGS += -I$(shell pwd)/udis86/ 11 | EXTRA_CFLAGS += -O -g 12 | 13 | udis86_extra-objs-y := udis86/decode.o \ 14 | udis86/syn-intel.o \ 15 | udis86/itab.o \ 16 | udis86/syn-att.o \ 17 | udis86/syn.o \ 18 | udis86/udis86.o 19 | 20 | inl_hook-objs-y := util.o inl_hook.o 21 | 22 | hello-objs := hello_core.o $(inl_hook-objs-y) $(udis86_extra-objs-y) 23 | 24 | modules: 25 | make -C $(KDIR) M=$(PWD) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" modules 26 | 27 | clean: 28 | @find $(PWD) \ 29 | \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ 30 | -o -name '*.ko.*' \ 31 | -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ 32 | -o -name '*.symtypes' -o -name 'modules.order' \ 33 | -o -name 'Module.markers' -o -name '.tmp_*.o.*' \ 34 | -o -name '*.gcno' \) -type f -print | xargs rm -f 35 | 36 | .PHONY: modules clean 37 | 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### about inl_hook 2 | 3 | **inl_hook** is a linux kernel function inline hooking library. it is very easy to use. 4 | 5 | ### example 6 | 7 | in the hello_core.c 8 | 9 | ```c 10 | static void (*tcp_set_state_fn)(struct sock *sk, int state); 11 | 12 | static void my_tcp_set_state(struct sock *sk, int state); 13 | 14 | static struct hook_ops hello_hooks[] = { 15 | DECLARE_HOOK(&tcp_set_state_fn, my_tcp_set_state), 16 | }; 17 | 18 | 19 | static void 20 | my_tcp_set_state(struct sock *sk, int state) 21 | { 22 | // copy your origin code here, then write patch code. 23 | // You can refer to hello_core.c 24 | } 25 | 26 | // hooking 27 | ret = inl_sethook_ops(hello_hooks, ARRAY_SIZE(hello_hooks)); 28 | if (ret < 0) { 29 | pr_err("inl_sethook_ops hello_hooks fail.\n"); 30 | goto exit; 31 | } 32 | 33 | // unhook 34 | inl_unhook_ops(hello_hooks, ARRAY_SIZE(hello_hooks)); 35 | ``` 36 | 37 | ### thank 38 | 39 | udis86: https://github.com/vmt/udis86 40 | 41 | mhook: https://github.com/martona/mhook 42 | 43 | -------------------------------------------------------------------------------- /hello_core.c: -------------------------------------------------------------------------------- 1 | /* 2 | * inline hook usage example. 3 | */ 4 | 5 | #define KMSG_COMPONENT "HELLO" 6 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "util.h" 18 | 19 | 20 | /* variable */ 21 | static void (*tcp_set_state_fn)(struct sock *sk, int state); 22 | 23 | /* hook function */ 24 | static void my_tcp_set_state(struct sock *sk, int state); 25 | 26 | 27 | static struct symbol_ops hello_ops[] = { 28 | DECLARE_SYMBOL(&tcp_set_state_fn, "tcp_set_state"), 29 | }; 30 | 31 | 32 | static struct hook_ops hello_hooks[] = { 33 | DECLARE_HOOK(&tcp_set_state_fn, my_tcp_set_state), 34 | }; 35 | 36 | 37 | /* hook function */ 38 | static void 39 | my_tcp_set_state(struct sock *sk, int state) 40 | { 41 | ///////////////////////////////////////////////////////// 42 | // add patch code. 43 | static const char *my_state_name[]={ 44 | "Unused","Established","Syn Sent","Syn Recv", 45 | "Fin Wait 1","Fin Wait 2","Time Wait", "Close", 46 | "Close Wait","Last ACK","Listen","Closing" 47 | }; 48 | struct inet_sock *inet = inet_sk(sk); 49 | ///////////////////////////////////////////////////////// 50 | 51 | int oldstate = sk->sk_state; 52 | 53 | switch (state) { 54 | case TCP_ESTABLISHED: 55 | if (oldstate != TCP_ESTABLISHED) 56 | TCP_INC_STATS(sock_net(sk), TCP_MIB_CURRESTAB); 57 | break; 58 | 59 | case TCP_CLOSE: 60 | if (oldstate == TCP_CLOSE_WAIT || oldstate == TCP_ESTABLISHED) 61 | TCP_INC_STATS(sock_net(sk), TCP_MIB_ESTABRESETS); 62 | 63 | sk->sk_prot->unhash(sk); 64 | if (inet_csk(sk)->icsk_bind_hash && 65 | !(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) 66 | inet_put_port(sk); 67 | /* fall through */ 68 | default: 69 | if (oldstate == TCP_ESTABLISHED) 70 | TCP_DEC_STATS(sock_net(sk), TCP_MIB_CURRESTAB); 71 | } 72 | 73 | /* Change state AFTER socket is unhashed to avoid closed 74 | * socket sitting in hash tables. 75 | */ 76 | sk->sk_state = state; 77 | 78 | ///////////////////////////////////////////////////////// 79 | // add patch code. 80 | pr_info("TCP %pI4:%d -> %pI4:%d, State %s -> %s\n", 81 | &inet->inet_saddr, ntohs(inet->inet_sport), 82 | &inet->inet_daddr, ntohs(inet->inet_dport), 83 | my_state_name[oldstate], my_state_name[state]); 84 | ///////////////////////////////////////////////////////// 85 | 86 | #ifdef STATE_TRACE 87 | SOCK_DEBUG(sk, "TCP sk=%p, State %s -> %s\n", sk, statename[oldstate], statename[state]); 88 | #endif 89 | } 90 | 91 | 92 | static int __init hello_init(void) 93 | { 94 | if (!find_ksymbol(hello_ops, ARRAY_SIZE(hello_ops))) { 95 | pr_err("hello symbol table not find.\n"); 96 | return -1; 97 | } 98 | 99 | if (!inl_sethook_ops(hello_hooks, ARRAY_SIZE(hello_hooks))) { 100 | pr_err("hijack hello functions fail.\n"); 101 | return -1; 102 | } 103 | 104 | pr_info("hello loaded.\n"); 105 | return 0; 106 | } 107 | 108 | 109 | static void __exit hello_cleanup(void) 110 | { 111 | inl_unhook_ops(hello_hooks, ARRAY_SIZE(hello_hooks)); 112 | pr_info("hello unloaded.\n"); 113 | } 114 | 115 | 116 | module_init(hello_init); 117 | module_exit(hello_cleanup); 118 | MODULE_LICENSE("GPL"); 119 | 120 | -------------------------------------------------------------------------------- /inl_hook.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel function inline hook. 3 | */ 4 | #define KMSG_COMPONENT "KINL_HOOK" 5 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "udis86.h" 13 | #include "inl_hook.h" 14 | 15 | 16 | #define JMP_CODE_BYTES 5 17 | #define HOOK_MAX_CODE_BYTES 32 18 | #define MAX_DISASSEMBLE_BYTES 1024 19 | 20 | struct hook_item { 21 | void *orig_func; 22 | void *hook_func; 23 | int stolen; 24 | u8 *orig_inst[HOOK_MAX_CODE_BYTES]; 25 | 26 | // can execute page. 27 | u8 *trampoline; 28 | struct list_head list; 29 | }; 30 | 31 | LIST_HEAD(hook_list); 32 | 33 | 34 | inline unsigned long disable_wp(void) 35 | { 36 | unsigned long cr0; 37 | 38 | preempt_disable(); 39 | barrier(); 40 | 41 | cr0 = read_cr0(); 42 | write_cr0(cr0 & ~X86_CR0_WP); 43 | return cr0; 44 | } 45 | 46 | 47 | inline void restore_wp(unsigned long cr0) 48 | { 49 | write_cr0(cr0); 50 | 51 | barrier(); 52 | preempt_enable(); 53 | } 54 | 55 | 56 | static u8 *skip_jumps(u8 *pcode) 57 | { 58 | u8 *orig_code = pcode; 59 | 60 | #if defined(CONFIG_X86_32) || defined(CONFIG_X86_64) 61 | #if defined(CONFIG_X86_32) 62 | //mov edi,edi: hot patch point 63 | if (pcode[0] == 0x8b && pcode[1] == 0xff) { 64 | pcode += 2; 65 | } 66 | 67 | // push rbp; mov rsp, rbp; 68 | // 55 48 89 e5 69 | if (pcode[0] == 0x55 && pcode[1] == 0x48 && pcode[2] == 0x89 && pcode[3] == 0xe5) { 70 | pcode += 4; 71 | } 72 | #endif 73 | 74 | if (pcode[0] == 0xff && pcode[1] == 0x25) { 75 | #if defined(CONFIG_X86_32) 76 | // on x86 we have an absolute pointer... 77 | u8 *target = *(u8 **)&pcode[2]; 78 | // ... that shows us an absolute pointer. 79 | return skip_jumps(*(u8 **)target); 80 | #elif defined(CONFIG_X86_64) 81 | // on x64 we have a 32-bit offset... 82 | s32 offset = *(s32 *)&pcode[2]; 83 | // ... that shows us an absolute pointer 84 | return skip_jumps(*(u8 **)(pcode + 6 + offset)); 85 | } else if (pcode[0] == 0x48 && pcode[1] == 0xff && pcode[2] == 0x25) { 86 | // or we can have the same with a REX prefix 87 | s32 offset = *(s32 *)&pcode[3]; 88 | // ... that shows us an absolute pointer 89 | return skip_jumps(*(u8 **)(pcode + 7 + offset)); 90 | #endif 91 | } else if (pcode[0] == 0xe9) { 92 | // here the behavior is identical, we have... 93 | // ...a 32-bit offset to the destination. 94 | return skip_jumps(pcode + 5 + *(s32 *)&pcode[1]); 95 | } else if (pcode[0] == 0xeb) { 96 | // and finally an 8-bit offset to the destination 97 | return skip_jumps(pcode + 2 + *(u8 *)&pcode[1]); 98 | } 99 | #else 100 | #error unsupported platform 101 | #endif 102 | 103 | return orig_code; 104 | } 105 | 106 | 107 | static u8 *emit_jump(u8 *pcode, u8 *jumpto) 108 | { 109 | #if defined(CONFIG_X86_32) || defined(CONFIG_X86_64) 110 | u8 *jumpfrom = pcode + 5; 111 | size_t diff = jumpfrom > jumpto ? jumpfrom - jumpto : jumpto - jumpfrom; 112 | 113 | pr_debug("emit_jumps from %p to %p, diff is %ld", jumpfrom, jumpto, diff); 114 | 115 | if (diff <= 0x7fff0000) { 116 | pcode[0] = 0xe9; 117 | pcode += 1; 118 | *((u32 *)pcode) = (u32)(jumpto - jumpfrom); 119 | pcode += sizeof(u32); 120 | } else { 121 | pcode[0] = 0xff; 122 | pcode[1] = 0x25; 123 | pcode += 2; 124 | #if defined(CONFIG_X86_32) 125 | // on x86 we write an absolute address (just behind the instruction) 126 | *((u32 *)pcode) = (u32)(pcode + sizeof(u32)); 127 | pcode += sizeof(u32); 128 | *((u32 *)pcode) = (u32)jumpto; 129 | pcode += sizeof(u32); 130 | #elif defined(CONFIG_X86_64) 131 | // on x64 we write the relative address of the same location 132 | *((u32 *)pcode) = (u32)0; 133 | pcode += sizeof(u32); 134 | *((u64 *)pcode) = (u64)jumpto; 135 | pcode += sizeof(u64); 136 | #endif 137 | } 138 | #else 139 | #error unsupported platform 140 | #endif 141 | 142 | return pcode; 143 | } 144 | 145 | 146 | static u32 disassemble_skip(u8 *target, u32 min_len) 147 | { 148 | ud_t u; 149 | u32 ret = 0; 150 | 151 | ud_init(&u); 152 | ud_set_input_buffer(&u, target, MAX_DISASSEMBLE_BYTES); 153 | ud_set_mode(&u, 64); 154 | ud_set_syntax(&u, UD_SYN_INTEL); 155 | 156 | while (ret < min_len && ud_disassemble(&u)) { 157 | ret += ud_insn_len(&u); 158 | } 159 | 160 | return ret; 161 | } 162 | 163 | 164 | static struct hook_item *trampoline_alloc(void *target, u32 stolen) 165 | { 166 | struct hook_item *item; 167 | u32 bytes = stolen + HOOK_MAX_CODE_BYTES; 168 | 169 | item = vzalloc(sizeof(struct hook_item)); 170 | if (!item) { 171 | return NULL; 172 | } 173 | 174 | item->trampoline = __vmalloc(bytes, GFP_KERNEL, PAGE_KERNEL_EXEC); 175 | 176 | if (item->trampoline == NULL) { 177 | vfree(item); 178 | return NULL; 179 | } 180 | 181 | memset(item->trampoline, 0, bytes); 182 | 183 | return item; 184 | } 185 | 186 | 187 | static struct hook_item *trampoline_find(u8 *hook) 188 | { 189 | struct hook_item *item; 190 | 191 | list_for_each_entry(item, &hook_list, list) { 192 | if (hook == item->hook_func) { 193 | return item; 194 | } 195 | } 196 | 197 | return NULL; 198 | } 199 | 200 | 201 | static u8 *post_hook(struct hook_item *item, void *target, 202 | void *hook, u32 stolen) 203 | { 204 | unsigned long o_cr0; 205 | 206 | item->orig_func = target; 207 | item->hook_func = hook; 208 | item->stolen = stolen; 209 | 210 | memmove(item->orig_inst, target, stolen); 211 | memmove(item->trampoline, target, stolen); 212 | 213 | emit_jump(item->trampoline + stolen, target + stolen); 214 | 215 | o_cr0 = disable_wp(); 216 | emit_jump(target, hook); 217 | restore_wp(o_cr0); 218 | 219 | list_add(&item->list, &hook_list); 220 | 221 | return item->trampoline; 222 | } 223 | 224 | 225 | static void hook_restore(struct hook_item *item) 226 | { 227 | unsigned long o_cr0; 228 | 229 | o_cr0 = disable_wp(); 230 | memmove(item->orig_func, item->orig_inst, item->stolen); 231 | restore_wp(o_cr0); 232 | 233 | list_del(&item->list); 234 | 235 | vfree(item->trampoline); 236 | vfree(item); 237 | } 238 | 239 | 240 | int inl_within_trampoline(unsigned long address) 241 | { 242 | long bytes; 243 | struct hook_item *item; 244 | unsigned long start, end; 245 | 246 | list_for_each_entry(item, &hook_list, list) { 247 | bytes = item->stolen + HOOK_MAX_CODE_BYTES; 248 | start = (unsigned long)item->trampoline; 249 | end = (unsigned long)item->trampoline + bytes; 250 | 251 | if (address >= start && address < end) { 252 | return -EBUSY; 253 | } 254 | } 255 | 256 | return 0; 257 | } 258 | 259 | 260 | int inl_sethook(void **orig, void *hook) 261 | { 262 | u32 instr_len; 263 | struct hook_item *item; 264 | void *target = *orig; 265 | 266 | target = skip_jumps(target); 267 | 268 | pr_debug("Started on the job: %p / %p\n", target, hook); 269 | 270 | instr_len = disassemble_skip(target, JMP_CODE_BYTES); 271 | if (instr_len < JMP_CODE_BYTES) { 272 | pr_err("disassemble_skip invalid instruction length: %u\n", 273 | instr_len); 274 | return -1; 275 | } 276 | 277 | pr_debug("disassembly signals %d bytes.\n", instr_len); 278 | 279 | item = trampoline_alloc(target, instr_len); 280 | if (item == NULL) { 281 | pr_err("alloc trampoline fail, no memory.\n"); 282 | return -ENOMEM; 283 | } 284 | 285 | *orig = post_hook(item, target, hook, instr_len); 286 | 287 | return 0; 288 | } 289 | 290 | 291 | int inl_unhook(void *hook) 292 | { 293 | struct hook_item *item; 294 | 295 | item = trampoline_find(hook); 296 | if (item == NULL) { 297 | pr_info("no find hook function: %p\n", hook); 298 | return -1; 299 | } 300 | 301 | hook_restore(item); 302 | 303 | return 0; 304 | } 305 | 306 | -------------------------------------------------------------------------------- /inl_hook.h: -------------------------------------------------------------------------------- 1 | #ifndef _INL_HOOK_H 2 | #define _INL_HOOK_H 3 | 4 | int inl_sethook(void **orig, void *hook); 5 | int inl_unhook(void *hook); 6 | int inl_within_trampoline(unsigned long address); 7 | 8 | #endif 9 | 10 | -------------------------------------------------------------------------------- /udis86/decode.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/decode.c 2 | * 3 | * Copyright (c) 2002-2009 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 "udint.h" 27 | #include "types.h" 28 | #include "extern.h" 29 | #include "decode.h" 30 | 31 | #ifndef __UD_STANDALONE__ 32 | # include 33 | #endif /* __UD_STANDALONE__ */ 34 | 35 | /* The max number of prefixes to an instruction */ 36 | #define MAX_PREFIXES 15 37 | 38 | /* rex prefix bits */ 39 | #define REX_W(r) ( ( 0xF & ( r ) ) >> 3 ) 40 | #define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 ) 41 | #define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 ) 42 | #define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 ) 43 | #define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \ 44 | ( P_REXR(n) << 2 ) | \ 45 | ( P_REXX(n) << 1 ) | \ 46 | ( P_REXB(n) << 0 ) ) 47 | 48 | /* scable-index-base bits */ 49 | #define SIB_S(b) ( ( b ) >> 6 ) 50 | #define SIB_I(b) ( ( ( b ) >> 3 ) & 7 ) 51 | #define SIB_B(b) ( ( b ) & 7 ) 52 | 53 | /* modrm bits */ 54 | #define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 ) 55 | #define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 ) 56 | #define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 ) 57 | #define MODRM_RM(b) ( ( b ) & 7 ) 58 | 59 | static int decode_ext(struct ud *u, uint16_t ptr); 60 | static int decode_opcode(struct ud *u); 61 | 62 | enum reg_class { /* register classes */ 63 | REGCLASS_GPR, 64 | REGCLASS_MMX, 65 | REGCLASS_CR, 66 | REGCLASS_DB, 67 | REGCLASS_SEG, 68 | REGCLASS_XMM 69 | }; 70 | 71 | /* 72 | * inp_start 73 | * Should be called before each de-code operation. 74 | */ 75 | static void 76 | inp_start(struct ud *u) 77 | { 78 | u->inp_ctr = 0; 79 | } 80 | 81 | static uint8_t 82 | inp_peek(struct ud *u) 83 | { 84 | if (u->inp_end == 0) { 85 | if (u->inp_buf != NULL) { 86 | if (u->inp_buf_index < u->inp_buf_size) { 87 | return u->inp_buf[u->inp_buf_index]; 88 | } 89 | } else if (u->inp_peek != UD_EOI) { 90 | return u->inp_peek; 91 | } else { 92 | int c; 93 | if ((c = u->inp_hook(u)) != UD_EOI) { 94 | u->inp_peek = c; 95 | return u->inp_peek; 96 | } 97 | } 98 | } 99 | u->inp_end = 1; 100 | UDERR(u, "byte expected, eoi received\n"); 101 | return 0; 102 | } 103 | 104 | static uint8_t 105 | inp_next(struct ud *u) 106 | { 107 | if (u->inp_end == 0) { 108 | if (u->inp_buf != NULL) { 109 | if (u->inp_buf_index < u->inp_buf_size) { 110 | u->inp_ctr++; 111 | return (u->inp_curr = u->inp_buf[u->inp_buf_index++]); 112 | } 113 | } else { 114 | int c = u->inp_peek; 115 | if (c != UD_EOI || (c = u->inp_hook(u)) != UD_EOI) { 116 | u->inp_peek = UD_EOI; 117 | u->inp_curr = c; 118 | u->inp_sess[u->inp_ctr++] = u->inp_curr; 119 | return u->inp_curr; 120 | } 121 | } 122 | } 123 | u->inp_end = 1; 124 | UDERR(u, "byte expected, eoi received\n"); 125 | return 0; 126 | } 127 | 128 | static uint8_t 129 | inp_curr(struct ud *u) 130 | { 131 | return u->inp_curr; 132 | } 133 | 134 | 135 | /* 136 | * inp_uint8 137 | * int_uint16 138 | * int_uint32 139 | * int_uint64 140 | * Load little-endian values from input 141 | */ 142 | static uint8_t 143 | inp_uint8(struct ud* u) 144 | { 145 | return inp_next(u); 146 | } 147 | 148 | static uint16_t 149 | inp_uint16(struct ud* u) 150 | { 151 | uint16_t r, ret; 152 | 153 | ret = inp_next(u); 154 | r = inp_next(u); 155 | return ret | (r << 8); 156 | } 157 | 158 | static uint32_t 159 | inp_uint32(struct ud* u) 160 | { 161 | uint32_t r, ret; 162 | 163 | ret = inp_next(u); 164 | r = inp_next(u); 165 | ret = ret | (r << 8); 166 | r = inp_next(u); 167 | ret = ret | (r << 16); 168 | r = inp_next(u); 169 | return ret | (r << 24); 170 | } 171 | 172 | static uint64_t 173 | inp_uint64(struct ud* u) 174 | { 175 | uint64_t r, ret; 176 | 177 | ret = inp_next(u); 178 | r = inp_next(u); 179 | ret = ret | (r << 8); 180 | r = inp_next(u); 181 | ret = ret | (r << 16); 182 | r = inp_next(u); 183 | ret = ret | (r << 24); 184 | r = inp_next(u); 185 | ret = ret | (r << 32); 186 | r = inp_next(u); 187 | ret = ret | (r << 40); 188 | r = inp_next(u); 189 | ret = ret | (r << 48); 190 | r = inp_next(u); 191 | return ret | (r << 56); 192 | } 193 | 194 | 195 | static UD_INLINE int 196 | eff_opr_mode(int dis_mode, int rex_w, int pfx_opr) 197 | { 198 | if (dis_mode == 64) { 199 | return rex_w ? 64 : (pfx_opr ? 16 : 32); 200 | } else if (dis_mode == 32) { 201 | return pfx_opr ? 16 : 32; 202 | } else { 203 | UD_ASSERT(dis_mode == 16); 204 | return pfx_opr ? 32 : 16; 205 | } 206 | } 207 | 208 | 209 | static UD_INLINE int 210 | eff_adr_mode(int dis_mode, int pfx_adr) 211 | { 212 | if (dis_mode == 64) { 213 | return pfx_adr ? 32 : 64; 214 | } else if (dis_mode == 32) { 215 | return pfx_adr ? 16 : 32; 216 | } else { 217 | UD_ASSERT(dis_mode == 16); 218 | return pfx_adr ? 32 : 16; 219 | } 220 | } 221 | 222 | 223 | /* 224 | * decode_prefixes 225 | * 226 | * Extracts instruction prefixes. 227 | */ 228 | static int 229 | decode_prefixes(struct ud *u) 230 | { 231 | int done = 0; 232 | uint8_t curr = 0, last = 0; 233 | UD_RETURN_ON_ERROR(u); 234 | 235 | do { 236 | last = curr; 237 | curr = inp_next(u); 238 | UD_RETURN_ON_ERROR(u); 239 | if (u->inp_ctr == MAX_INSN_LENGTH) { 240 | UD_RETURN_WITH_ERROR(u, "max instruction length"); 241 | } 242 | 243 | switch (curr) 244 | { 245 | case 0x2E: 246 | u->pfx_seg = UD_R_CS; 247 | break; 248 | case 0x36: 249 | u->pfx_seg = UD_R_SS; 250 | break; 251 | case 0x3E: 252 | u->pfx_seg = UD_R_DS; 253 | break; 254 | case 0x26: 255 | u->pfx_seg = UD_R_ES; 256 | break; 257 | case 0x64: 258 | u->pfx_seg = UD_R_FS; 259 | break; 260 | case 0x65: 261 | u->pfx_seg = UD_R_GS; 262 | break; 263 | case 0x67: /* adress-size override prefix */ 264 | u->pfx_adr = 0x67; 265 | break; 266 | case 0xF0: 267 | u->pfx_lock = 0xF0; 268 | break; 269 | case 0x66: 270 | u->pfx_opr = 0x66; 271 | break; 272 | case 0xF2: 273 | u->pfx_str = 0xf2; 274 | break; 275 | case 0xF3: 276 | u->pfx_str = 0xf3; 277 | break; 278 | default: 279 | /* consume if rex */ 280 | done = (u->dis_mode == 64 && (curr & 0xF0) == 0x40) ? 0 : 1; 281 | break; 282 | } 283 | } while (!done); 284 | /* rex prefixes in 64bit mode, must be the last prefix */ 285 | if (u->dis_mode == 64 && (last & 0xF0) == 0x40) { 286 | u->pfx_rex = last; 287 | } 288 | return 0; 289 | } 290 | 291 | 292 | /* 293 | * vex_l, vex_w 294 | * Return the vex.L and vex.W bits 295 | */ 296 | static UD_INLINE uint8_t 297 | vex_l(const struct ud *u) 298 | { 299 | UD_ASSERT(u->vex_op != 0); 300 | return ((u->vex_op == 0xc4 ? u->vex_b2 : u->vex_b1) >> 2) & 1; 301 | } 302 | 303 | static UD_INLINE uint8_t 304 | vex_w(const struct ud *u) 305 | { 306 | UD_ASSERT(u->vex_op != 0); 307 | return u->vex_op == 0xc4 ? ((u->vex_b2 >> 7) & 1) : 0; 308 | } 309 | 310 | 311 | static UD_INLINE uint8_t 312 | modrm(struct ud * u) 313 | { 314 | if ( !u->have_modrm ) { 315 | u->modrm = inp_next( u ); 316 | u->modrm_offset = (uint8_t) (u->inp_ctr - 1); 317 | u->have_modrm = 1; 318 | } 319 | return u->modrm; 320 | } 321 | 322 | 323 | static unsigned int 324 | resolve_operand_size(const struct ud* u, ud_operand_size_t osize) 325 | { 326 | switch (osize) { 327 | case SZ_V: 328 | return u->opr_mode; 329 | case SZ_Z: 330 | return u->opr_mode == 16 ? 16 : 32; 331 | case SZ_Y: 332 | return u->opr_mode == 16 ? 32 : u->opr_mode; 333 | case SZ_RDQ: 334 | return u->dis_mode == 64 ? 64 : 32; 335 | case SZ_X: 336 | UD_ASSERT(u->vex_op != 0); 337 | return (P_VEXL(u->itab_entry->prefix) && vex_l(u)) ? SZ_QQ : SZ_DQ; 338 | default: 339 | return osize; 340 | } 341 | } 342 | 343 | 344 | static int resolve_mnemonic( struct ud* u ) 345 | { 346 | /* resolve 3dnow weirdness. */ 347 | if ( u->mnemonic == UD_I3dnow ) { 348 | u->mnemonic = ud_itab[ u->le->table[ inp_curr( u ) ] ].mnemonic; 349 | } 350 | /* SWAPGS is only valid in 64bits mode */ 351 | if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) { 352 | UDERR(u, "swapgs invalid in 64bits mode\n"); 353 | return -1; 354 | } 355 | 356 | if (u->mnemonic == UD_Ixchg) { 357 | if ((u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_AX && 358 | u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_AX) || 359 | (u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_EAX && 360 | u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_EAX)) { 361 | u->operand[0].type = UD_NONE; 362 | u->operand[1].type = UD_NONE; 363 | u->mnemonic = UD_Inop; 364 | } 365 | } 366 | 367 | if (u->mnemonic == UD_Inop && u->pfx_repe) { 368 | u->pfx_repe = 0; 369 | u->mnemonic = UD_Ipause; 370 | } 371 | return 0; 372 | } 373 | 374 | 375 | /* ----------------------------------------------------------------------------- 376 | * decode_a()- Decodes operands of the type seg:offset 377 | * ----------------------------------------------------------------------------- 378 | */ 379 | static void 380 | decode_a(struct ud* u, struct ud_operand *op) 381 | { 382 | if (u->opr_mode == 16) { 383 | /* seg16:off16 */ 384 | op->type = UD_OP_PTR; 385 | op->size = 32; 386 | op->lval.ptr.off = inp_uint16(u); 387 | op->lval.ptr.seg = inp_uint16(u); 388 | } else { 389 | /* seg16:off32 */ 390 | op->type = UD_OP_PTR; 391 | op->size = 48; 392 | op->lval.ptr.off = inp_uint32(u); 393 | op->lval.ptr.seg = inp_uint16(u); 394 | } 395 | } 396 | 397 | /* ----------------------------------------------------------------------------- 398 | * decode_gpr() - Returns decoded General Purpose Register 399 | * ----------------------------------------------------------------------------- 400 | */ 401 | static enum ud_type 402 | decode_gpr(register struct ud* u, unsigned int s, unsigned char rm) 403 | { 404 | switch (s) { 405 | case 64: 406 | return UD_R_RAX + rm; 407 | case 32: 408 | return UD_R_EAX + rm; 409 | case 16: 410 | return UD_R_AX + rm; 411 | case 8: 412 | if (u->dis_mode == 64 && u->pfx_rex) { 413 | if (rm >= 4) 414 | return UD_R_SPL + (rm-4); 415 | return UD_R_AL + rm; 416 | } else return UD_R_AL + rm; 417 | case 0: 418 | /* invalid size in case of a decode error */ 419 | UD_ASSERT(u->error); 420 | return UD_NONE; 421 | default: 422 | UD_ASSERT(!"invalid operand size"); 423 | return UD_NONE; 424 | } 425 | } 426 | 427 | static void 428 | decode_reg(struct ud *u, 429 | struct ud_operand *opr, 430 | int type, 431 | int num, 432 | int size) 433 | { 434 | int reg; 435 | size = resolve_operand_size(u, size); 436 | switch (type) { 437 | case REGCLASS_GPR : reg = decode_gpr(u, size, num); break; 438 | case REGCLASS_MMX : reg = UD_R_MM0 + (num & 7); break; 439 | case REGCLASS_XMM : 440 | reg = num + (size == SZ_QQ ? UD_R_YMM0 : UD_R_XMM0); 441 | break; 442 | case REGCLASS_CR : reg = UD_R_CR0 + num; break; 443 | case REGCLASS_DB : reg = UD_R_DR0 + num; break; 444 | case REGCLASS_SEG : { 445 | /* 446 | * Only 6 segment registers, anything else is an error. 447 | */ 448 | if ((num & 7) > 5) { 449 | UDERR(u, "invalid segment register value\n"); 450 | return; 451 | } else { 452 | reg = UD_R_ES + (num & 7); 453 | } 454 | break; 455 | } 456 | default: 457 | UD_ASSERT(!"invalid register type"); 458 | return; 459 | } 460 | opr->type = UD_OP_REG; 461 | opr->base = reg; 462 | opr->size = size; 463 | } 464 | 465 | 466 | /* 467 | * decode_imm 468 | * 469 | * Decode Immediate values. 470 | */ 471 | static void 472 | decode_imm(struct ud* u, unsigned int size, struct ud_operand *op) 473 | { 474 | op->size = resolve_operand_size(u, size); 475 | op->type = UD_OP_IMM; 476 | 477 | switch (op->size) { 478 | case 8: op->lval.sbyte = inp_uint8(u); break; 479 | case 16: op->lval.uword = inp_uint16(u); break; 480 | case 32: op->lval.udword = inp_uint32(u); break; 481 | case 64: op->lval.uqword = inp_uint64(u); break; 482 | default: return; 483 | } 484 | } 485 | 486 | 487 | /* 488 | * decode_mem_disp 489 | * 490 | * Decode mem address displacement. 491 | */ 492 | static void 493 | decode_mem_disp(struct ud* u, unsigned int size, struct ud_operand *op) 494 | { 495 | switch (size) { 496 | case 8: 497 | op->offset = 8; 498 | op->lval.ubyte = inp_uint8(u); 499 | break; 500 | case 16: 501 | op->offset = 16; 502 | op->lval.uword = inp_uint16(u); 503 | break; 504 | case 32: 505 | op->offset = 32; 506 | op->lval.udword = inp_uint32(u); 507 | break; 508 | case 64: 509 | op->offset = 64; 510 | op->lval.uqword = inp_uint64(u); 511 | break; 512 | default: 513 | return; 514 | } 515 | } 516 | 517 | 518 | /* 519 | * decode_modrm_reg 520 | * 521 | * Decodes reg field of mod/rm byte 522 | * 523 | */ 524 | static UD_INLINE void 525 | decode_modrm_reg(struct ud *u, 526 | struct ud_operand *operand, 527 | unsigned int type, 528 | unsigned int size) 529 | { 530 | uint8_t reg = (REX_R(u->_rex) << 3) | MODRM_REG(modrm(u)); 531 | decode_reg(u, operand, type, reg, size); 532 | } 533 | 534 | 535 | /* 536 | * decode_modrm_rm 537 | * 538 | * Decodes rm field of mod/rm byte 539 | * 540 | */ 541 | static void 542 | decode_modrm_rm(struct ud *u, 543 | struct ud_operand *op, 544 | unsigned char type, /* register type */ 545 | unsigned int size) /* operand size */ 546 | 547 | { 548 | size_t offset = 0; 549 | unsigned char mod, rm; 550 | 551 | /* get mod, r/m and reg fields */ 552 | mod = MODRM_MOD(modrm(u)); 553 | rm = (REX_B(u->_rex) << 3) | MODRM_RM(modrm(u)); 554 | 555 | /* 556 | * If mod is 11b, then the modrm.rm specifies a register. 557 | * 558 | */ 559 | if (mod == 3) { 560 | decode_reg(u, op, type, rm, size); 561 | return; 562 | } 563 | 564 | /* 565 | * !11b => Memory Address 566 | */ 567 | op->type = UD_OP_MEM; 568 | op->size = resolve_operand_size(u, size); 569 | 570 | if (u->adr_mode == 64) { 571 | op->base = UD_R_RAX + rm; 572 | if (mod == 1) { 573 | offset = 8; 574 | } else if (mod == 2) { 575 | offset = 32; 576 | } else if (mod == 0 && (rm & 7) == 5) { 577 | op->base = UD_R_RIP; 578 | offset = 32; 579 | } else { 580 | offset = 0; 581 | } 582 | /* 583 | * Scale-Index-Base (SIB) 584 | */ 585 | if ((rm & 7) == 4) { 586 | inp_next(u); 587 | 588 | op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->_rex) << 3)); 589 | op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->_rex) << 3)); 590 | /* special conditions for base reference */ 591 | if (op->index == UD_R_RSP) { 592 | op->index = UD_NONE; 593 | op->scale = UD_NONE; 594 | } else { 595 | op->scale = (1 << SIB_S(inp_curr(u))) & ~1; 596 | } 597 | 598 | if (op->base == UD_R_RBP || op->base == UD_R_R13) { 599 | if (mod == 0) { 600 | op->base = UD_NONE; 601 | } 602 | if (mod == 1) { 603 | offset = 8; 604 | } else { 605 | offset = 32; 606 | } 607 | } 608 | } else { 609 | op->scale = UD_NONE; 610 | op->index = UD_NONE; 611 | } 612 | } else if (u->adr_mode == 32) { 613 | op->base = UD_R_EAX + rm; 614 | if (mod == 1) { 615 | offset = 8; 616 | } else if (mod == 2) { 617 | offset = 32; 618 | } else if (mod == 0 && rm == 5) { 619 | op->base = UD_NONE; 620 | offset = 32; 621 | } else { 622 | offset = 0; 623 | } 624 | 625 | /* Scale-Index-Base (SIB) */ 626 | if ((rm & 7) == 4) { 627 | inp_next(u); 628 | 629 | op->scale = (1 << SIB_S(inp_curr(u))) & ~1; 630 | op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); 631 | op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); 632 | 633 | if (op->index == UD_R_ESP) { 634 | op->index = UD_NONE; 635 | op->scale = UD_NONE; 636 | } 637 | 638 | /* special condition for base reference */ 639 | if (op->base == UD_R_EBP) { 640 | if (mod == 0) { 641 | op->base = UD_NONE; 642 | } 643 | if (mod == 1) { 644 | offset = 8; 645 | } else { 646 | offset = 32; 647 | } 648 | } 649 | } else { 650 | op->scale = UD_NONE; 651 | op->index = UD_NONE; 652 | } 653 | } else { 654 | const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP, 655 | UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX }; 656 | const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI, 657 | UD_NONE, UD_NONE, UD_NONE, UD_NONE }; 658 | op->base = bases[rm & 7]; 659 | op->index = indices[rm & 7]; 660 | op->scale = UD_NONE; 661 | if (mod == 0 && rm == 6) { 662 | offset = 16; 663 | op->base = UD_NONE; 664 | } else if (mod == 1) { 665 | offset = 8; 666 | } else if (mod == 2) { 667 | offset = 16; 668 | } 669 | } 670 | 671 | if (offset) { 672 | decode_mem_disp(u, offset, op); 673 | } else { 674 | op->offset = 0; 675 | } 676 | } 677 | 678 | 679 | /* 680 | * decode_moffset 681 | * Decode offset-only memory operand 682 | */ 683 | static void 684 | decode_moffset(struct ud *u, unsigned int size, struct ud_operand *opr) 685 | { 686 | opr->type = UD_OP_MEM; 687 | opr->base = UD_NONE; 688 | opr->index = UD_NONE; 689 | opr->scale = UD_NONE; 690 | opr->size = resolve_operand_size(u, size); 691 | decode_mem_disp(u, u->adr_mode, opr); 692 | } 693 | 694 | 695 | static void 696 | decode_vex_vvvv(struct ud *u, struct ud_operand *opr, unsigned size) 697 | { 698 | uint8_t vvvv; 699 | UD_ASSERT(u->vex_op != 0); 700 | vvvv = ((u->vex_op == 0xc4 ? u->vex_b2 : u->vex_b1) >> 3) & 0xf; 701 | decode_reg(u, opr, REGCLASS_XMM, (0xf & ~vvvv), size); 702 | } 703 | 704 | 705 | /* 706 | * decode_vex_immreg 707 | * Decode source operand encoded in immediate byte [7:4] 708 | */ 709 | static int 710 | decode_vex_immreg(struct ud *u, struct ud_operand *opr, unsigned size) 711 | { 712 | uint8_t imm = inp_next(u); 713 | uint8_t mask = u->dis_mode == 64 ? 0xf : 0x7; 714 | UD_RETURN_ON_ERROR(u); 715 | UD_ASSERT(u->vex_op != 0); 716 | decode_reg(u, opr, REGCLASS_XMM, mask & (imm >> 4), size); 717 | return 0; 718 | } 719 | 720 | 721 | /* 722 | * decode_operand 723 | * 724 | * Decodes a single operand. 725 | * Returns the type of the operand (UD_NONE if none) 726 | */ 727 | static int 728 | decode_operand(struct ud *u, 729 | struct ud_operand *operand, 730 | enum ud_operand_code type, 731 | unsigned int size) 732 | { 733 | operand->type = UD_NONE; 734 | operand->_oprcode = type; 735 | 736 | switch (type) { 737 | case OP_A : 738 | decode_a(u, operand); 739 | break; 740 | case OP_MR: 741 | decode_modrm_rm(u, operand, REGCLASS_GPR, 742 | MODRM_MOD(modrm(u)) == 3 ? 743 | Mx_reg_size(size) : Mx_mem_size(size)); 744 | break; 745 | case OP_F: 746 | u->br_far = 1; 747 | /* intended fall through */ 748 | case OP_M: 749 | if (MODRM_MOD(modrm(u)) == 3) { 750 | UDERR(u, "expected modrm.mod != 3\n"); 751 | } 752 | /* intended fall through */ 753 | case OP_E: 754 | decode_modrm_rm(u, operand, REGCLASS_GPR, size); 755 | break; 756 | case OP_G: 757 | decode_modrm_reg(u, operand, REGCLASS_GPR, size); 758 | break; 759 | case OP_sI: 760 | case OP_I: 761 | decode_imm(u, size, operand); 762 | break; 763 | case OP_I1: 764 | operand->type = UD_OP_CONST; 765 | operand->lval.udword = 1; 766 | break; 767 | case OP_N: 768 | if (MODRM_MOD(modrm(u)) != 3) { 769 | UDERR(u, "expected modrm.mod == 3\n"); 770 | } 771 | /* intended fall through */ 772 | case OP_Q: 773 | decode_modrm_rm(u, operand, REGCLASS_MMX, size); 774 | break; 775 | case OP_P: 776 | decode_modrm_reg(u, operand, REGCLASS_MMX, size); 777 | break; 778 | case OP_U: 779 | if (MODRM_MOD(modrm(u)) != 3) { 780 | UDERR(u, "expected modrm.mod == 3\n"); 781 | } 782 | /* intended fall through */ 783 | case OP_W: 784 | decode_modrm_rm(u, operand, REGCLASS_XMM, size); 785 | break; 786 | case OP_V: 787 | decode_modrm_reg(u, operand, REGCLASS_XMM, size); 788 | break; 789 | case OP_H: 790 | decode_vex_vvvv(u, operand, size); 791 | break; 792 | case OP_MU: 793 | decode_modrm_rm(u, operand, REGCLASS_XMM, 794 | MODRM_MOD(modrm(u)) == 3 ? 795 | Mx_reg_size(size) : Mx_mem_size(size)); 796 | break; 797 | case OP_S: 798 | decode_modrm_reg(u, operand, REGCLASS_SEG, size); 799 | break; 800 | case OP_O: 801 | decode_moffset(u, size, operand); 802 | break; 803 | case OP_R0: 804 | case OP_R1: 805 | case OP_R2: 806 | case OP_R3: 807 | case OP_R4: 808 | case OP_R5: 809 | case OP_R6: 810 | case OP_R7: 811 | decode_reg(u, operand, REGCLASS_GPR, 812 | (REX_B(u->_rex) << 3) | (type - OP_R0), size); 813 | break; 814 | case OP_AL: 815 | case OP_AX: 816 | case OP_eAX: 817 | case OP_rAX: 818 | decode_reg(u, operand, REGCLASS_GPR, 0, size); 819 | break; 820 | case OP_CL: 821 | case OP_CX: 822 | case OP_eCX: 823 | decode_reg(u, operand, REGCLASS_GPR, 1, size); 824 | break; 825 | case OP_DL: 826 | case OP_DX: 827 | case OP_eDX: 828 | decode_reg(u, operand, REGCLASS_GPR, 2, size); 829 | break; 830 | case OP_ES: 831 | case OP_CS: 832 | case OP_DS: 833 | case OP_SS: 834 | case OP_FS: 835 | case OP_GS: 836 | /* in 64bits mode, only fs and gs are allowed */ 837 | if (u->dis_mode == 64) { 838 | if (type != OP_FS && type != OP_GS) { 839 | UDERR(u, "invalid segment register in 64bits\n"); 840 | } 841 | } 842 | operand->type = UD_OP_REG; 843 | operand->base = (type - OP_ES) + UD_R_ES; 844 | operand->size = 16; 845 | break; 846 | case OP_J : 847 | decode_imm(u, size, operand); 848 | operand->type = UD_OP_JIMM; 849 | break ; 850 | case OP_R : 851 | if (MODRM_MOD(modrm(u)) != 3) { 852 | UDERR(u, "expected modrm.mod == 3\n"); 853 | } 854 | decode_modrm_rm(u, operand, REGCLASS_GPR, size); 855 | break; 856 | case OP_C: 857 | decode_modrm_reg(u, operand, REGCLASS_CR, size); 858 | break; 859 | case OP_D: 860 | decode_modrm_reg(u, operand, REGCLASS_DB, size); 861 | break; 862 | case OP_I3 : 863 | operand->type = UD_OP_CONST; 864 | operand->lval.sbyte = 3; 865 | break; 866 | case OP_ST0: 867 | case OP_ST1: 868 | case OP_ST2: 869 | case OP_ST3: 870 | case OP_ST4: 871 | case OP_ST5: 872 | case OP_ST6: 873 | case OP_ST7: 874 | operand->type = UD_OP_REG; 875 | operand->base = (type - OP_ST0) + UD_R_ST0; 876 | operand->size = 80; 877 | break; 878 | case OP_L: 879 | decode_vex_immreg(u, operand, size); 880 | break; 881 | default : 882 | operand->type = UD_NONE; 883 | break; 884 | } 885 | return operand->type; 886 | } 887 | 888 | 889 | /* 890 | * decode_operands 891 | * 892 | * Disassemble upto 3 operands of the current instruction being 893 | * disassembled. By the end of the function, the operand fields 894 | * of the ud structure will have been filled. 895 | */ 896 | static int 897 | decode_operands(struct ud* u) 898 | { 899 | decode_operand(u, &u->operand[0], 900 | u->itab_entry->operand1.type, 901 | u->itab_entry->operand1.size); 902 | if (u->operand[0].type != UD_NONE) { 903 | decode_operand(u, &u->operand[1], 904 | u->itab_entry->operand2.type, 905 | u->itab_entry->operand2.size); 906 | } 907 | if (u->operand[1].type != UD_NONE) { 908 | decode_operand(u, &u->operand[2], 909 | u->itab_entry->operand3.type, 910 | u->itab_entry->operand3.size); 911 | } 912 | if (u->operand[2].type != UD_NONE) { 913 | decode_operand(u, &u->operand[3], 914 | u->itab_entry->operand4.type, 915 | u->itab_entry->operand4.size); 916 | } 917 | return 0; 918 | } 919 | 920 | /* ----------------------------------------------------------------------------- 921 | * clear_insn() - clear instruction structure 922 | * ----------------------------------------------------------------------------- 923 | */ 924 | static void 925 | clear_insn(register struct ud* u) 926 | { 927 | u->error = 0; 928 | u->pfx_seg = 0; 929 | u->pfx_opr = 0; 930 | u->pfx_adr = 0; 931 | u->pfx_lock = 0; 932 | u->pfx_repne = 0; 933 | u->pfx_rep = 0; 934 | u->pfx_repe = 0; 935 | u->pfx_rex = 0; 936 | u->pfx_str = 0; 937 | u->mnemonic = UD_Inone; 938 | u->itab_entry = NULL; 939 | u->have_modrm = 0; 940 | u->br_far = 0; 941 | u->vex_op = 0; 942 | u->_rex = 0; 943 | u->operand[0].type = UD_NONE; 944 | u->operand[1].type = UD_NONE; 945 | u->operand[2].type = UD_NONE; 946 | u->operand[3].type = UD_NONE; 947 | } 948 | 949 | 950 | static UD_INLINE int 951 | resolve_pfx_str(struct ud* u) 952 | { 953 | if (u->pfx_str == 0xf3) { 954 | if (P_STR(u->itab_entry->prefix)) { 955 | u->pfx_rep = 0xf3; 956 | } else { 957 | u->pfx_repe = 0xf3; 958 | } 959 | } else if (u->pfx_str == 0xf2) { 960 | u->pfx_repne = 0xf3; 961 | } 962 | return 0; 963 | } 964 | 965 | 966 | static int 967 | resolve_mode( struct ud* u ) 968 | { 969 | int default64; 970 | /* if in error state, bail out */ 971 | if ( u->error ) return -1; 972 | 973 | /* propagate prefix effects */ 974 | if ( u->dis_mode == 64 ) { /* set 64bit-mode flags */ 975 | 976 | /* Check validity of instruction m64 */ 977 | if ( P_INV64( u->itab_entry->prefix ) ) { 978 | UDERR(u, "instruction invalid in 64bits\n"); 979 | return -1; 980 | } 981 | 982 | /* compute effective rex based on, 983 | * - vex prefix (if any) 984 | * - rex prefix (if any, and not vex) 985 | * - allowed prefixes specified by the opcode map 986 | */ 987 | if (u->vex_op == 0xc4) { 988 | /* vex has rex.rxb in 1's complement */ 989 | u->_rex = ((~(u->vex_b1 >> 5) & 0x7) /* rex.0rxb */ | 990 | ((u->vex_b2 >> 4) & 0x8) /* rex.w000 */); 991 | } else if (u->vex_op == 0xc5) { 992 | /* vex has rex.r in 1's complement */ 993 | u->_rex = (~(u->vex_b1 >> 5)) & 4; 994 | } else { 995 | UD_ASSERT(u->vex_op == 0); 996 | u->_rex = u->pfx_rex; 997 | } 998 | u->_rex &= REX_PFX_MASK(u->itab_entry->prefix); 999 | 1000 | /* whether this instruction has a default operand size of 1001 | * 64bit, also hardcoded into the opcode map. 1002 | */ 1003 | default64 = P_DEF64( u->itab_entry->prefix ); 1004 | /* calculate effective operand size */ 1005 | if (REX_W(u->_rex)) { 1006 | u->opr_mode = 64; 1007 | } else if ( u->pfx_opr ) { 1008 | u->opr_mode = 16; 1009 | } else { 1010 | /* unless the default opr size of instruction is 64, 1011 | * the effective operand size in the absence of rex.w 1012 | * prefix is 32. 1013 | */ 1014 | u->opr_mode = default64 ? 64 : 32; 1015 | } 1016 | 1017 | /* calculate effective address size */ 1018 | u->adr_mode = (u->pfx_adr) ? 32 : 64; 1019 | } else if ( u->dis_mode == 32 ) { /* set 32bit-mode flags */ 1020 | u->opr_mode = ( u->pfx_opr ) ? 16 : 32; 1021 | u->adr_mode = ( u->pfx_adr ) ? 16 : 32; 1022 | } else if ( u->dis_mode == 16 ) { /* set 16bit-mode flags */ 1023 | u->opr_mode = ( u->pfx_opr ) ? 32 : 16; 1024 | u->adr_mode = ( u->pfx_adr ) ? 32 : 16; 1025 | } 1026 | 1027 | return 0; 1028 | } 1029 | 1030 | 1031 | static UD_INLINE int 1032 | decode_insn(struct ud *u, uint16_t ptr) 1033 | { 1034 | UD_ASSERT((ptr & 0x8000) == 0); 1035 | u->itab_entry = &ud_itab[ ptr ]; 1036 | u->mnemonic = u->itab_entry->mnemonic; 1037 | return (resolve_pfx_str(u) == 0 && 1038 | resolve_mode(u) == 0 && 1039 | decode_operands(u) == 0 && 1040 | resolve_mnemonic(u) == 0) ? 0 : -1; 1041 | } 1042 | 1043 | 1044 | /* 1045 | * decode_3dnow() 1046 | * 1047 | * Decoding 3dnow is a little tricky because of its strange opcode 1048 | * structure. The final opcode disambiguation depends on the last 1049 | * byte that comes after the operands have been decoded. Fortunately, 1050 | * all 3dnow instructions have the same set of operand types. So we 1051 | * go ahead and decode the instruction by picking an arbitrarily chosen 1052 | * valid entry in the table, decode the operands, and read the final 1053 | * byte to resolve the menmonic. 1054 | */ 1055 | static UD_INLINE int 1056 | decode_3dnow(struct ud* u) 1057 | { 1058 | uint16_t ptr; 1059 | UD_ASSERT(u->le->type == UD_TAB__OPC_3DNOW); 1060 | UD_ASSERT(u->le->table[0xc] != 0); 1061 | decode_insn(u, u->le->table[0xc]); 1062 | inp_next(u); 1063 | if (u->error) { 1064 | return -1; 1065 | } 1066 | ptr = u->le->table[inp_curr(u)]; 1067 | UD_ASSERT((ptr & 0x8000) == 0); 1068 | u->mnemonic = ud_itab[ptr].mnemonic; 1069 | return 0; 1070 | } 1071 | 1072 | 1073 | static int 1074 | decode_ssepfx(struct ud *u) 1075 | { 1076 | uint8_t idx; 1077 | uint8_t pfx; 1078 | 1079 | /* 1080 | * String prefixes (f2, f3) take precedence over operand 1081 | * size prefix (66). 1082 | */ 1083 | pfx = u->pfx_str; 1084 | if (pfx == 0) { 1085 | pfx = u->pfx_opr; 1086 | } 1087 | idx = ((pfx & 0xf) + 1) / 2; 1088 | if (u->le->table[idx] == 0) { 1089 | idx = 0; 1090 | } 1091 | if (idx && u->le->table[idx] != 0) { 1092 | /* 1093 | * "Consume" the prefix as a part of the opcode, so it is no 1094 | * longer exported as an instruction prefix. 1095 | */ 1096 | u->pfx_str = 0; 1097 | if (pfx == 0x66) { 1098 | /* 1099 | * consume "66" only if it was used for decoding, leaving 1100 | * it to be used as an operands size override for some 1101 | * simd instructions. 1102 | */ 1103 | u->pfx_opr = 0; 1104 | } 1105 | } 1106 | return decode_ext(u, u->le->table[idx]); 1107 | } 1108 | 1109 | 1110 | static int 1111 | decode_vex(struct ud *u) 1112 | { 1113 | uint8_t index; 1114 | if (u->dis_mode != 64 && MODRM_MOD(inp_peek(u)) != 0x3) { 1115 | index = 0; 1116 | } else { 1117 | u->vex_op = inp_curr(u); 1118 | u->vex_b1 = inp_next(u); 1119 | if (u->vex_op == 0xc4) { 1120 | uint8_t pp, m; 1121 | /* 3-byte vex */ 1122 | u->vex_b2 = inp_next(u); 1123 | UD_RETURN_ON_ERROR(u); 1124 | m = u->vex_b1 & 0x1f; 1125 | if (m == 0 || m > 3) { 1126 | UD_RETURN_WITH_ERROR(u, "reserved vex.m-mmmm value"); 1127 | } 1128 | pp = u->vex_b2 & 0x3; 1129 | index = (pp << 2) | m; 1130 | } else { 1131 | /* 2-byte vex */ 1132 | UD_ASSERT(u->vex_op == 0xc5); 1133 | index = 0x1 | ((u->vex_b1 & 0x3) << 2); 1134 | } 1135 | } 1136 | return decode_ext(u, u->le->table[index]); 1137 | } 1138 | 1139 | 1140 | /* 1141 | * decode_ext() 1142 | * 1143 | * Decode opcode extensions (if any) 1144 | */ 1145 | static int 1146 | decode_ext(struct ud *u, uint16_t ptr) 1147 | { 1148 | uint8_t idx = 0; 1149 | if ((ptr & 0x8000) == 0) { 1150 | return decode_insn(u, ptr); 1151 | } 1152 | u->le = &ud_lookup_table_list[(~0x8000 & ptr)]; 1153 | if (u->le->type == UD_TAB__OPC_3DNOW) { 1154 | return decode_3dnow(u); 1155 | } 1156 | 1157 | switch (u->le->type) { 1158 | case UD_TAB__OPC_MOD: 1159 | /* !11 = 0, 11 = 1 */ 1160 | idx = (MODRM_MOD(modrm(u)) + 1) / 4; 1161 | break; 1162 | /* disassembly mode/operand size/address size based tables. 1163 | * 16 = 0,, 32 = 1, 64 = 2 1164 | */ 1165 | case UD_TAB__OPC_MODE: 1166 | idx = u->dis_mode != 64 ? 0 : 1; 1167 | break; 1168 | case UD_TAB__OPC_OSIZE: 1169 | idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32; 1170 | break; 1171 | case UD_TAB__OPC_ASIZE: 1172 | idx = eff_adr_mode(u->dis_mode, u->pfx_adr) / 32; 1173 | break; 1174 | case UD_TAB__OPC_X87: 1175 | idx = modrm(u) - 0xC0; 1176 | break; 1177 | case UD_TAB__OPC_VENDOR: 1178 | if (u->vendor == UD_VENDOR_ANY) { 1179 | /* choose a valid entry */ 1180 | idx = (u->le->table[idx] != 0) ? 0 : 1; 1181 | } else if (u->vendor == UD_VENDOR_AMD) { 1182 | idx = 0; 1183 | } else { 1184 | idx = 1; 1185 | } 1186 | break; 1187 | case UD_TAB__OPC_RM: 1188 | idx = MODRM_RM(modrm(u)); 1189 | break; 1190 | case UD_TAB__OPC_REG: 1191 | idx = MODRM_REG(modrm(u)); 1192 | break; 1193 | case UD_TAB__OPC_SSE: 1194 | return decode_ssepfx(u); 1195 | case UD_TAB__OPC_VEX: 1196 | return decode_vex(u); 1197 | case UD_TAB__OPC_VEX_W: 1198 | idx = vex_w(u); 1199 | break; 1200 | case UD_TAB__OPC_VEX_L: 1201 | idx = vex_l(u); 1202 | break; 1203 | case UD_TAB__OPC_TABLE: 1204 | inp_next(u); 1205 | return decode_opcode(u); 1206 | default: 1207 | UD_ASSERT(!"not reached"); 1208 | break; 1209 | } 1210 | 1211 | return decode_ext(u, u->le->table[idx]); 1212 | } 1213 | 1214 | 1215 | static int 1216 | decode_opcode(struct ud *u) 1217 | { 1218 | uint16_t ptr; 1219 | UD_ASSERT(u->le->type == UD_TAB__OPC_TABLE); 1220 | UD_RETURN_ON_ERROR(u); 1221 | ptr = u->le->table[inp_curr(u)]; 1222 | return decode_ext(u, ptr); 1223 | } 1224 | 1225 | 1226 | /* ============================================================================= 1227 | * ud_decode() - Instruction decoder. Returns the number of bytes decoded. 1228 | * ============================================================================= 1229 | */ 1230 | unsigned int 1231 | ud_decode(struct ud *u) 1232 | { 1233 | inp_start(u); 1234 | clear_insn(u); 1235 | u->le = &ud_lookup_table_list[0]; 1236 | u->error = decode_prefixes(u) == -1 || 1237 | decode_opcode(u) == -1 || 1238 | u->error; 1239 | /* Handle decode error. */ 1240 | if (u->error) { 1241 | /* clear out the decode data. */ 1242 | clear_insn(u); 1243 | /* mark the sequence of bytes as invalid. */ 1244 | u->itab_entry = &ud_itab[0]; /* entry 0 is invalid */ 1245 | u->mnemonic = u->itab_entry->mnemonic; 1246 | } 1247 | 1248 | /* maybe this stray segment override byte 1249 | * should be spewed out? 1250 | */ 1251 | if ( !P_SEG( u->itab_entry->prefix ) && 1252 | u->operand[0].type != UD_OP_MEM && 1253 | u->operand[1].type != UD_OP_MEM ) 1254 | u->pfx_seg = 0; 1255 | 1256 | u->insn_offset = u->pc; /* set offset of instruction */ 1257 | u->asm_buf_fill = 0; /* set translation buffer index to 0 */ 1258 | u->pc += u->inp_ctr; /* move program counter by bytes decoded */ 1259 | 1260 | /* return number of bytes disassembled. */ 1261 | return u->inp_ctr; 1262 | } 1263 | 1264 | /* 1265 | vim: set ts=2 sw=2 expandtab 1266 | */ 1267 | -------------------------------------------------------------------------------- /udis86/decode.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/decode.h 2 | * 3 | * Copyright (c) 2002-2009 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 | #ifndef UD_DECODE_H 27 | #define UD_DECODE_H 28 | 29 | #include "types.h" 30 | #include "udint.h" 31 | #include "itab.h" 32 | 33 | #define MAX_INSN_LENGTH 15 34 | 35 | /* itab prefix bits */ 36 | #define P_none ( 0 ) 37 | 38 | #define P_inv64 ( 1 << 0 ) 39 | #define P_INV64(n) ( ( n >> 0 ) & 1 ) 40 | #define P_def64 ( 1 << 1 ) 41 | #define P_DEF64(n) ( ( n >> 1 ) & 1 ) 42 | 43 | #define P_oso ( 1 << 2 ) 44 | #define P_OSO(n) ( ( n >> 2 ) & 1 ) 45 | #define P_aso ( 1 << 3 ) 46 | #define P_ASO(n) ( ( n >> 3 ) & 1 ) 47 | 48 | #define P_rexb ( 1 << 4 ) 49 | #define P_REXB(n) ( ( n >> 4 ) & 1 ) 50 | #define P_rexw ( 1 << 5 ) 51 | #define P_REXW(n) ( ( n >> 5 ) & 1 ) 52 | #define P_rexr ( 1 << 6 ) 53 | #define P_REXR(n) ( ( n >> 6 ) & 1 ) 54 | #define P_rexx ( 1 << 7 ) 55 | #define P_REXX(n) ( ( n >> 7 ) & 1 ) 56 | 57 | #define P_seg ( 1 << 8 ) 58 | #define P_SEG(n) ( ( n >> 8 ) & 1 ) 59 | 60 | #define P_vexl ( 1 << 9 ) 61 | #define P_VEXL(n) ( ( n >> 9 ) & 1 ) 62 | #define P_vexw ( 1 << 10 ) 63 | #define P_VEXW(n) ( ( n >> 10 ) & 1 ) 64 | 65 | #define P_str ( 1 << 11 ) 66 | #define P_STR(n) ( ( n >> 11 ) & 1 ) 67 | #define P_strz ( 1 << 12 ) 68 | #define P_STR_ZF(n) ( ( n >> 12 ) & 1 ) 69 | 70 | /* operand type constants -- order is important! */ 71 | 72 | enum ud_operand_code { 73 | OP_NONE, 74 | 75 | OP_A, OP_E, OP_M, OP_G, 76 | OP_I, OP_F, 77 | 78 | OP_R0, OP_R1, OP_R2, OP_R3, 79 | OP_R4, OP_R5, OP_R6, OP_R7, 80 | 81 | OP_AL, OP_CL, OP_DL, 82 | OP_AX, OP_CX, OP_DX, 83 | OP_eAX, OP_eCX, OP_eDX, 84 | OP_rAX, OP_rCX, OP_rDX, 85 | 86 | OP_ES, OP_CS, OP_SS, OP_DS, 87 | OP_FS, OP_GS, 88 | 89 | OP_ST0, OP_ST1, OP_ST2, OP_ST3, 90 | OP_ST4, OP_ST5, OP_ST6, OP_ST7, 91 | 92 | OP_J, OP_S, OP_O, 93 | OP_I1, OP_I3, OP_sI, 94 | 95 | OP_V, OP_W, OP_Q, OP_P, 96 | OP_U, OP_N, OP_MU, OP_H, 97 | OP_L, 98 | 99 | OP_R, OP_C, OP_D, 100 | 101 | OP_MR 102 | } UD_ATTR_PACKED; 103 | 104 | 105 | /* 106 | * Operand size constants 107 | * 108 | * Symbolic constants for various operand sizes. Some of these constants 109 | * are given a value equal to the width of the data (SZ_B == 8), such 110 | * that they maybe used interchangeably in the internals. Modifying them 111 | * will most certainly break things! 112 | */ 113 | typedef uint16_t ud_operand_size_t; 114 | 115 | #define SZ_NA 0 116 | #define SZ_Z 1 117 | #define SZ_V 2 118 | #define SZ_Y 3 119 | #define SZ_X 4 120 | #define SZ_RDQ 7 121 | #define SZ_B 8 122 | #define SZ_W 16 123 | #define SZ_D 32 124 | #define SZ_Q 64 125 | #define SZ_T 80 126 | #define SZ_O 12 127 | #define SZ_DQ 128 /* double quad */ 128 | #define SZ_QQ 256 /* quad quad */ 129 | 130 | /* 131 | * Complex size types; that encode sizes for operands of type MR (memory or 132 | * register); for internal use only. Id space above 256. 133 | */ 134 | #define SZ_BD ((SZ_B << 8) | SZ_D) 135 | #define SZ_BV ((SZ_B << 8) | SZ_V) 136 | #define SZ_WD ((SZ_W << 8) | SZ_D) 137 | #define SZ_WV ((SZ_W << 8) | SZ_V) 138 | #define SZ_WY ((SZ_W << 8) | SZ_Y) 139 | #define SZ_DY ((SZ_D << 8) | SZ_Y) 140 | #define SZ_WO ((SZ_W << 8) | SZ_O) 141 | #define SZ_DO ((SZ_D << 8) | SZ_O) 142 | #define SZ_QO ((SZ_Q << 8) | SZ_O) 143 | 144 | 145 | /* resolve complex size type. 146 | */ 147 | static UD_INLINE ud_operand_size_t 148 | Mx_mem_size(ud_operand_size_t size) 149 | { 150 | return (size >> 8) & 0xff; 151 | } 152 | 153 | static UD_INLINE ud_operand_size_t 154 | Mx_reg_size(ud_operand_size_t size) 155 | { 156 | return size & 0xff; 157 | } 158 | 159 | /* A single operand of an entry in the instruction table. 160 | * (internal use only) 161 | */ 162 | struct ud_itab_entry_operand 163 | { 164 | enum ud_operand_code type; 165 | ud_operand_size_t size; 166 | }; 167 | 168 | 169 | /* A single entry in an instruction table. 170 | *(internal use only) 171 | */ 172 | struct ud_itab_entry 173 | { 174 | enum ud_mnemonic_code mnemonic; 175 | struct ud_itab_entry_operand operand1; 176 | struct ud_itab_entry_operand operand2; 177 | struct ud_itab_entry_operand operand3; 178 | struct ud_itab_entry_operand operand4; 179 | uint32_t prefix; 180 | }; 181 | 182 | struct ud_lookup_table_list_entry { 183 | const uint16_t *table; 184 | enum ud_table_type type; 185 | const char *meta; 186 | }; 187 | 188 | extern struct ud_itab_entry ud_itab[]; 189 | extern struct ud_lookup_table_list_entry ud_lookup_table_list[]; 190 | 191 | #endif /* UD_DECODE_H */ 192 | 193 | /* vim:cindent 194 | * vim:expandtab 195 | * vim:ts=4 196 | * vim:sw=4 197 | */ 198 | -------------------------------------------------------------------------------- /udis86/extern.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/extern.h 2 | * 3 | * Copyright (c) 2002-2009, 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 | #ifndef UD_EXTERN_H 27 | #define UD_EXTERN_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | #include "types.h" 34 | 35 | #if defined(_MSC_VER) && defined(_USRDLL) 36 | # ifdef LIBUDIS86_EXPORTS 37 | # define LIBUDIS86_DLLEXTERN __declspec(dllexport) 38 | # else 39 | # define LIBUDIS86_DLLEXTERN __declspec(dllimport) 40 | # endif 41 | #else 42 | # define LIBUDIS86_DLLEXTERN 43 | #endif 44 | 45 | /* ============================= PUBLIC API ================================= */ 46 | 47 | extern LIBUDIS86_DLLEXTERN void ud_init(struct ud*); 48 | 49 | extern LIBUDIS86_DLLEXTERN void ud_set_mode(struct ud*, uint8_t); 50 | 51 | extern LIBUDIS86_DLLEXTERN void ud_set_pc(struct ud*, uint64_t); 52 | 53 | extern LIBUDIS86_DLLEXTERN void ud_set_input_hook(struct ud*, int (*)(struct ud*)); 54 | 55 | extern LIBUDIS86_DLLEXTERN void ud_set_input_buffer(struct ud*, const uint8_t*, size_t); 56 | 57 | #ifndef __UD_STANDALONE__ 58 | extern LIBUDIS86_DLLEXTERN void ud_set_input_file(struct ud*, FILE*); 59 | #endif /* __UD_STANDALONE__ */ 60 | 61 | extern LIBUDIS86_DLLEXTERN void ud_set_vendor(struct ud*, unsigned); 62 | 63 | extern LIBUDIS86_DLLEXTERN void ud_set_syntax(struct ud*, void (*)(struct ud*)); 64 | 65 | extern LIBUDIS86_DLLEXTERN void ud_input_skip(struct ud*, size_t); 66 | 67 | extern LIBUDIS86_DLLEXTERN int ud_input_end(const struct ud*); 68 | 69 | extern LIBUDIS86_DLLEXTERN unsigned int ud_decode(struct ud*); 70 | 71 | extern LIBUDIS86_DLLEXTERN unsigned int ud_disassemble(struct ud*); 72 | 73 | extern LIBUDIS86_DLLEXTERN void ud_translate_intel(struct ud*); 74 | 75 | extern LIBUDIS86_DLLEXTERN void ud_translate_att(struct ud*); 76 | 77 | extern LIBUDIS86_DLLEXTERN const char* ud_insn_asm(const struct ud* u); 78 | 79 | extern LIBUDIS86_DLLEXTERN const uint8_t* ud_insn_ptr(const struct ud* u); 80 | 81 | extern LIBUDIS86_DLLEXTERN uint64_t ud_insn_off(const struct ud*); 82 | 83 | extern LIBUDIS86_DLLEXTERN const char* ud_insn_hex(struct ud*); 84 | 85 | extern LIBUDIS86_DLLEXTERN unsigned int ud_insn_len(const struct ud* u); 86 | 87 | extern LIBUDIS86_DLLEXTERN const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n); 88 | 89 | extern LIBUDIS86_DLLEXTERN int ud_opr_is_sreg(const struct ud_operand *opr); 90 | 91 | extern LIBUDIS86_DLLEXTERN int ud_opr_is_gpr(const struct ud_operand *opr); 92 | 93 | extern LIBUDIS86_DLLEXTERN enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u); 94 | 95 | extern LIBUDIS86_DLLEXTERN const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); 96 | 97 | extern LIBUDIS86_DLLEXTERN void ud_set_user_opaque_data(struct ud*, void*); 98 | 99 | extern LIBUDIS86_DLLEXTERN void* ud_get_user_opaque_data(const struct ud*); 100 | 101 | extern LIBUDIS86_DLLEXTERN void ud_set_asm_buffer(struct ud *u, char *buf, size_t size); 102 | 103 | extern LIBUDIS86_DLLEXTERN void ud_set_sym_resolver(struct ud *u, 104 | const char* (*resolver)(struct ud*, 105 | uint64_t addr, 106 | int64_t *offset)); 107 | 108 | /* ========================================================================== */ 109 | 110 | #ifdef __cplusplus 111 | } 112 | #endif 113 | #endif /* UD_EXTERN_H */ 114 | -------------------------------------------------------------------------------- /udis86/itab.h: -------------------------------------------------------------------------------- 1 | #ifndef UD_ITAB_H 2 | #define UD_ITAB_H 3 | 4 | /* itab.h -- generated by udis86:scripts/ud_itab.py, do no edit */ 5 | 6 | /* ud_table_type -- lookup table types (see decode.c) */ 7 | enum ud_table_type { 8 | UD_TAB__OPC_VEX, 9 | UD_TAB__OPC_TABLE, 10 | UD_TAB__OPC_X87, 11 | UD_TAB__OPC_MOD, 12 | UD_TAB__OPC_RM, 13 | UD_TAB__OPC_OSIZE, 14 | UD_TAB__OPC_MODE, 15 | UD_TAB__OPC_VEX_L, 16 | UD_TAB__OPC_3DNOW, 17 | UD_TAB__OPC_REG, 18 | UD_TAB__OPC_ASIZE, 19 | UD_TAB__OPC_VEX_W, 20 | UD_TAB__OPC_SSE, 21 | UD_TAB__OPC_VENDOR 22 | }; 23 | 24 | /* ud_mnemonic -- mnemonic constants */ 25 | enum ud_mnemonic_code { 26 | UD_Iaaa, 27 | UD_Iaad, 28 | UD_Iaam, 29 | UD_Iaas, 30 | UD_Iadc, 31 | UD_Iadd, 32 | UD_Iaddpd, 33 | UD_Iaddps, 34 | UD_Iaddsd, 35 | UD_Iaddss, 36 | UD_Iaddsubpd, 37 | UD_Iaddsubps, 38 | UD_Iaesdec, 39 | UD_Iaesdeclast, 40 | UD_Iaesenc, 41 | UD_Iaesenclast, 42 | UD_Iaesimc, 43 | UD_Iaeskeygenassist, 44 | UD_Iand, 45 | UD_Iandnpd, 46 | UD_Iandnps, 47 | UD_Iandpd, 48 | UD_Iandps, 49 | UD_Iarpl, 50 | UD_Iblendpd, 51 | UD_Iblendps, 52 | UD_Iblendvpd, 53 | UD_Iblendvps, 54 | UD_Ibound, 55 | UD_Ibsf, 56 | UD_Ibsr, 57 | UD_Ibswap, 58 | UD_Ibt, 59 | UD_Ibtc, 60 | UD_Ibtr, 61 | UD_Ibts, 62 | UD_Icall, 63 | UD_Icbw, 64 | UD_Icdq, 65 | UD_Icdqe, 66 | UD_Iclc, 67 | UD_Icld, 68 | UD_Iclflush, 69 | UD_Iclgi, 70 | UD_Icli, 71 | UD_Iclts, 72 | UD_Icmc, 73 | UD_Icmova, 74 | UD_Icmovae, 75 | UD_Icmovb, 76 | UD_Icmovbe, 77 | UD_Icmovg, 78 | UD_Icmovge, 79 | UD_Icmovl, 80 | UD_Icmovle, 81 | UD_Icmovno, 82 | UD_Icmovnp, 83 | UD_Icmovns, 84 | UD_Icmovnz, 85 | UD_Icmovo, 86 | UD_Icmovp, 87 | UD_Icmovs, 88 | UD_Icmovz, 89 | UD_Icmp, 90 | UD_Icmppd, 91 | UD_Icmpps, 92 | UD_Icmpsb, 93 | UD_Icmpsd, 94 | UD_Icmpsq, 95 | UD_Icmpss, 96 | UD_Icmpsw, 97 | UD_Icmpxchg, 98 | UD_Icmpxchg16b, 99 | UD_Icmpxchg8b, 100 | UD_Icomisd, 101 | UD_Icomiss, 102 | UD_Icpuid, 103 | UD_Icqo, 104 | UD_Icrc32, 105 | UD_Icvtdq2pd, 106 | UD_Icvtdq2ps, 107 | UD_Icvtpd2dq, 108 | UD_Icvtpd2pi, 109 | UD_Icvtpd2ps, 110 | UD_Icvtpi2pd, 111 | UD_Icvtpi2ps, 112 | UD_Icvtps2dq, 113 | UD_Icvtps2pd, 114 | UD_Icvtps2pi, 115 | UD_Icvtsd2si, 116 | UD_Icvtsd2ss, 117 | UD_Icvtsi2sd, 118 | UD_Icvtsi2ss, 119 | UD_Icvtss2sd, 120 | UD_Icvtss2si, 121 | UD_Icvttpd2dq, 122 | UD_Icvttpd2pi, 123 | UD_Icvttps2dq, 124 | UD_Icvttps2pi, 125 | UD_Icvttsd2si, 126 | UD_Icvttss2si, 127 | UD_Icwd, 128 | UD_Icwde, 129 | UD_Idaa, 130 | UD_Idas, 131 | UD_Idec, 132 | UD_Idiv, 133 | UD_Idivpd, 134 | UD_Idivps, 135 | UD_Idivsd, 136 | UD_Idivss, 137 | UD_Idppd, 138 | UD_Idpps, 139 | UD_Iemms, 140 | UD_Ienter, 141 | UD_Iextractps, 142 | UD_If2xm1, 143 | UD_Ifabs, 144 | UD_Ifadd, 145 | UD_Ifaddp, 146 | UD_Ifbld, 147 | UD_Ifbstp, 148 | UD_Ifchs, 149 | UD_Ifclex, 150 | UD_Ifcmovb, 151 | UD_Ifcmovbe, 152 | UD_Ifcmove, 153 | UD_Ifcmovnb, 154 | UD_Ifcmovnbe, 155 | UD_Ifcmovne, 156 | UD_Ifcmovnu, 157 | UD_Ifcmovu, 158 | UD_Ifcom, 159 | UD_Ifcom2, 160 | UD_Ifcomi, 161 | UD_Ifcomip, 162 | UD_Ifcomp, 163 | UD_Ifcomp3, 164 | UD_Ifcomp5, 165 | UD_Ifcompp, 166 | UD_Ifcos, 167 | UD_Ifdecstp, 168 | UD_Ifdiv, 169 | UD_Ifdivp, 170 | UD_Ifdivr, 171 | UD_Ifdivrp, 172 | UD_Ifemms, 173 | UD_Iffree, 174 | UD_Iffreep, 175 | UD_Ifiadd, 176 | UD_Ificom, 177 | UD_Ificomp, 178 | UD_Ifidiv, 179 | UD_Ifidivr, 180 | UD_Ifild, 181 | UD_Ifimul, 182 | UD_Ifincstp, 183 | UD_Ifist, 184 | UD_Ifistp, 185 | UD_Ifisttp, 186 | UD_Ifisub, 187 | UD_Ifisubr, 188 | UD_Ifld, 189 | UD_Ifld1, 190 | UD_Ifldcw, 191 | UD_Ifldenv, 192 | UD_Ifldl2e, 193 | UD_Ifldl2t, 194 | UD_Ifldlg2, 195 | UD_Ifldln2, 196 | UD_Ifldpi, 197 | UD_Ifldz, 198 | UD_Ifmul, 199 | UD_Ifmulp, 200 | UD_Ifndisi, 201 | UD_Ifneni, 202 | UD_Ifninit, 203 | UD_Ifnop, 204 | UD_Ifnsave, 205 | UD_Ifnsetpm, 206 | UD_Ifnstcw, 207 | UD_Ifnstenv, 208 | UD_Ifnstsw, 209 | UD_Ifpatan, 210 | UD_Ifprem, 211 | UD_Ifprem1, 212 | UD_Ifptan, 213 | UD_Ifrndint, 214 | UD_Ifrstor, 215 | UD_Ifrstpm, 216 | UD_Ifscale, 217 | UD_Ifsin, 218 | UD_Ifsincos, 219 | UD_Ifsqrt, 220 | UD_Ifst, 221 | UD_Ifstp, 222 | UD_Ifstp1, 223 | UD_Ifstp8, 224 | UD_Ifstp9, 225 | UD_Ifsub, 226 | UD_Ifsubp, 227 | UD_Ifsubr, 228 | UD_Ifsubrp, 229 | UD_Iftst, 230 | UD_Ifucom, 231 | UD_Ifucomi, 232 | UD_Ifucomip, 233 | UD_Ifucomp, 234 | UD_Ifucompp, 235 | UD_Ifxam, 236 | UD_Ifxch, 237 | UD_Ifxch4, 238 | UD_Ifxch7, 239 | UD_Ifxrstor, 240 | UD_Ifxsave, 241 | UD_Ifxtract, 242 | UD_Ifyl2x, 243 | UD_Ifyl2xp1, 244 | UD_Igetsec, 245 | UD_Ihaddpd, 246 | UD_Ihaddps, 247 | UD_Ihlt, 248 | UD_Ihsubpd, 249 | UD_Ihsubps, 250 | UD_Iidiv, 251 | UD_Iimul, 252 | UD_Iin, 253 | UD_Iinc, 254 | UD_Iinsb, 255 | UD_Iinsd, 256 | UD_Iinsertps, 257 | UD_Iinsw, 258 | UD_Iint, 259 | UD_Iint1, 260 | UD_Iint3, 261 | UD_Iinto, 262 | UD_Iinvd, 263 | UD_Iinvept, 264 | UD_Iinvlpg, 265 | UD_Iinvlpga, 266 | UD_Iinvvpid, 267 | UD_Iiretd, 268 | UD_Iiretq, 269 | UD_Iiretw, 270 | UD_Ija, 271 | UD_Ijae, 272 | UD_Ijb, 273 | UD_Ijbe, 274 | UD_Ijcxz, 275 | UD_Ijecxz, 276 | UD_Ijg, 277 | UD_Ijge, 278 | UD_Ijl, 279 | UD_Ijle, 280 | UD_Ijmp, 281 | UD_Ijno, 282 | UD_Ijnp, 283 | UD_Ijns, 284 | UD_Ijnz, 285 | UD_Ijo, 286 | UD_Ijp, 287 | UD_Ijrcxz, 288 | UD_Ijs, 289 | UD_Ijz, 290 | UD_Ilahf, 291 | UD_Ilar, 292 | UD_Ilddqu, 293 | UD_Ildmxcsr, 294 | UD_Ilds, 295 | UD_Ilea, 296 | UD_Ileave, 297 | UD_Iles, 298 | UD_Ilfence, 299 | UD_Ilfs, 300 | UD_Ilgdt, 301 | UD_Ilgs, 302 | UD_Ilidt, 303 | UD_Illdt, 304 | UD_Ilmsw, 305 | UD_Ilock, 306 | UD_Ilodsb, 307 | UD_Ilodsd, 308 | UD_Ilodsq, 309 | UD_Ilodsw, 310 | UD_Iloop, 311 | UD_Iloope, 312 | UD_Iloopne, 313 | UD_Ilsl, 314 | UD_Ilss, 315 | UD_Iltr, 316 | UD_Imaskmovdqu, 317 | UD_Imaskmovq, 318 | UD_Imaxpd, 319 | UD_Imaxps, 320 | UD_Imaxsd, 321 | UD_Imaxss, 322 | UD_Imfence, 323 | UD_Iminpd, 324 | UD_Iminps, 325 | UD_Iminsd, 326 | UD_Iminss, 327 | UD_Imonitor, 328 | UD_Imontmul, 329 | UD_Imov, 330 | UD_Imovapd, 331 | UD_Imovaps, 332 | UD_Imovbe, 333 | UD_Imovd, 334 | UD_Imovddup, 335 | UD_Imovdq2q, 336 | UD_Imovdqa, 337 | UD_Imovdqu, 338 | UD_Imovhlps, 339 | UD_Imovhpd, 340 | UD_Imovhps, 341 | UD_Imovlhps, 342 | UD_Imovlpd, 343 | UD_Imovlps, 344 | UD_Imovmskpd, 345 | UD_Imovmskps, 346 | UD_Imovntdq, 347 | UD_Imovntdqa, 348 | UD_Imovnti, 349 | UD_Imovntpd, 350 | UD_Imovntps, 351 | UD_Imovntq, 352 | UD_Imovq, 353 | UD_Imovq2dq, 354 | UD_Imovsb, 355 | UD_Imovsd, 356 | UD_Imovshdup, 357 | UD_Imovsldup, 358 | UD_Imovsq, 359 | UD_Imovss, 360 | UD_Imovsw, 361 | UD_Imovsx, 362 | UD_Imovsxd, 363 | UD_Imovupd, 364 | UD_Imovups, 365 | UD_Imovzx, 366 | UD_Impsadbw, 367 | UD_Imul, 368 | UD_Imulpd, 369 | UD_Imulps, 370 | UD_Imulsd, 371 | UD_Imulss, 372 | UD_Imwait, 373 | UD_Ineg, 374 | UD_Inop, 375 | UD_Inot, 376 | UD_Ior, 377 | UD_Iorpd, 378 | UD_Iorps, 379 | UD_Iout, 380 | UD_Ioutsb, 381 | UD_Ioutsd, 382 | UD_Ioutsw, 383 | UD_Ipabsb, 384 | UD_Ipabsd, 385 | UD_Ipabsw, 386 | UD_Ipackssdw, 387 | UD_Ipacksswb, 388 | UD_Ipackusdw, 389 | UD_Ipackuswb, 390 | UD_Ipaddb, 391 | UD_Ipaddd, 392 | UD_Ipaddq, 393 | UD_Ipaddsb, 394 | UD_Ipaddsw, 395 | UD_Ipaddusb, 396 | UD_Ipaddusw, 397 | UD_Ipaddw, 398 | UD_Ipalignr, 399 | UD_Ipand, 400 | UD_Ipandn, 401 | UD_Ipavgb, 402 | UD_Ipavgusb, 403 | UD_Ipavgw, 404 | UD_Ipblendvb, 405 | UD_Ipblendw, 406 | UD_Ipclmulqdq, 407 | UD_Ipcmpeqb, 408 | UD_Ipcmpeqd, 409 | UD_Ipcmpeqq, 410 | UD_Ipcmpeqw, 411 | UD_Ipcmpestri, 412 | UD_Ipcmpestrm, 413 | UD_Ipcmpgtb, 414 | UD_Ipcmpgtd, 415 | UD_Ipcmpgtq, 416 | UD_Ipcmpgtw, 417 | UD_Ipcmpistri, 418 | UD_Ipcmpistrm, 419 | UD_Ipextrb, 420 | UD_Ipextrd, 421 | UD_Ipextrq, 422 | UD_Ipextrw, 423 | UD_Ipf2id, 424 | UD_Ipf2iw, 425 | UD_Ipfacc, 426 | UD_Ipfadd, 427 | UD_Ipfcmpeq, 428 | UD_Ipfcmpge, 429 | UD_Ipfcmpgt, 430 | UD_Ipfmax, 431 | UD_Ipfmin, 432 | UD_Ipfmul, 433 | UD_Ipfnacc, 434 | UD_Ipfpnacc, 435 | UD_Ipfrcp, 436 | UD_Ipfrcpit1, 437 | UD_Ipfrcpit2, 438 | UD_Ipfrsqit1, 439 | UD_Ipfrsqrt, 440 | UD_Ipfsub, 441 | UD_Ipfsubr, 442 | UD_Iphaddd, 443 | UD_Iphaddsw, 444 | UD_Iphaddw, 445 | UD_Iphminposuw, 446 | UD_Iphsubd, 447 | UD_Iphsubsw, 448 | UD_Iphsubw, 449 | UD_Ipi2fd, 450 | UD_Ipi2fw, 451 | UD_Ipinsrb, 452 | UD_Ipinsrd, 453 | UD_Ipinsrq, 454 | UD_Ipinsrw, 455 | UD_Ipmaddubsw, 456 | UD_Ipmaddwd, 457 | UD_Ipmaxsb, 458 | UD_Ipmaxsd, 459 | UD_Ipmaxsw, 460 | UD_Ipmaxub, 461 | UD_Ipmaxud, 462 | UD_Ipmaxuw, 463 | UD_Ipminsb, 464 | UD_Ipminsd, 465 | UD_Ipminsw, 466 | UD_Ipminub, 467 | UD_Ipminud, 468 | UD_Ipminuw, 469 | UD_Ipmovmskb, 470 | UD_Ipmovsxbd, 471 | UD_Ipmovsxbq, 472 | UD_Ipmovsxbw, 473 | UD_Ipmovsxdq, 474 | UD_Ipmovsxwd, 475 | UD_Ipmovsxwq, 476 | UD_Ipmovzxbd, 477 | UD_Ipmovzxbq, 478 | UD_Ipmovzxbw, 479 | UD_Ipmovzxdq, 480 | UD_Ipmovzxwd, 481 | UD_Ipmovzxwq, 482 | UD_Ipmuldq, 483 | UD_Ipmulhrsw, 484 | UD_Ipmulhrw, 485 | UD_Ipmulhuw, 486 | UD_Ipmulhw, 487 | UD_Ipmulld, 488 | UD_Ipmullw, 489 | UD_Ipmuludq, 490 | UD_Ipop, 491 | UD_Ipopa, 492 | UD_Ipopad, 493 | UD_Ipopcnt, 494 | UD_Ipopfd, 495 | UD_Ipopfq, 496 | UD_Ipopfw, 497 | UD_Ipor, 498 | UD_Iprefetch, 499 | UD_Iprefetchnta, 500 | UD_Iprefetcht0, 501 | UD_Iprefetcht1, 502 | UD_Iprefetcht2, 503 | UD_Ipsadbw, 504 | UD_Ipshufb, 505 | UD_Ipshufd, 506 | UD_Ipshufhw, 507 | UD_Ipshuflw, 508 | UD_Ipshufw, 509 | UD_Ipsignb, 510 | UD_Ipsignd, 511 | UD_Ipsignw, 512 | UD_Ipslld, 513 | UD_Ipslldq, 514 | UD_Ipsllq, 515 | UD_Ipsllw, 516 | UD_Ipsrad, 517 | UD_Ipsraw, 518 | UD_Ipsrld, 519 | UD_Ipsrldq, 520 | UD_Ipsrlq, 521 | UD_Ipsrlw, 522 | UD_Ipsubb, 523 | UD_Ipsubd, 524 | UD_Ipsubq, 525 | UD_Ipsubsb, 526 | UD_Ipsubsw, 527 | UD_Ipsubusb, 528 | UD_Ipsubusw, 529 | UD_Ipsubw, 530 | UD_Ipswapd, 531 | UD_Iptest, 532 | UD_Ipunpckhbw, 533 | UD_Ipunpckhdq, 534 | UD_Ipunpckhqdq, 535 | UD_Ipunpckhwd, 536 | UD_Ipunpcklbw, 537 | UD_Ipunpckldq, 538 | UD_Ipunpcklqdq, 539 | UD_Ipunpcklwd, 540 | UD_Ipush, 541 | UD_Ipusha, 542 | UD_Ipushad, 543 | UD_Ipushfd, 544 | UD_Ipushfq, 545 | UD_Ipushfw, 546 | UD_Ipxor, 547 | UD_Ircl, 548 | UD_Ircpps, 549 | UD_Ircpss, 550 | UD_Ircr, 551 | UD_Irdmsr, 552 | UD_Irdpmc, 553 | UD_Irdrand, 554 | UD_Irdtsc, 555 | UD_Irdtscp, 556 | UD_Irep, 557 | UD_Irepne, 558 | UD_Iret, 559 | UD_Iretf, 560 | UD_Irol, 561 | UD_Iror, 562 | UD_Iroundpd, 563 | UD_Iroundps, 564 | UD_Iroundsd, 565 | UD_Iroundss, 566 | UD_Irsm, 567 | UD_Irsqrtps, 568 | UD_Irsqrtss, 569 | UD_Isahf, 570 | UD_Isalc, 571 | UD_Isar, 572 | UD_Isbb, 573 | UD_Iscasb, 574 | UD_Iscasd, 575 | UD_Iscasq, 576 | UD_Iscasw, 577 | UD_Iseta, 578 | UD_Isetae, 579 | UD_Isetb, 580 | UD_Isetbe, 581 | UD_Isetg, 582 | UD_Isetge, 583 | UD_Isetl, 584 | UD_Isetle, 585 | UD_Isetno, 586 | UD_Isetnp, 587 | UD_Isetns, 588 | UD_Isetnz, 589 | UD_Iseto, 590 | UD_Isetp, 591 | UD_Isets, 592 | UD_Isetz, 593 | UD_Isfence, 594 | UD_Isgdt, 595 | UD_Ishl, 596 | UD_Ishld, 597 | UD_Ishr, 598 | UD_Ishrd, 599 | UD_Ishufpd, 600 | UD_Ishufps, 601 | UD_Isidt, 602 | UD_Iskinit, 603 | UD_Isldt, 604 | UD_Ismsw, 605 | UD_Isqrtpd, 606 | UD_Isqrtps, 607 | UD_Isqrtsd, 608 | UD_Isqrtss, 609 | UD_Istc, 610 | UD_Istd, 611 | UD_Istgi, 612 | UD_Isti, 613 | UD_Istmxcsr, 614 | UD_Istosb, 615 | UD_Istosd, 616 | UD_Istosq, 617 | UD_Istosw, 618 | UD_Istr, 619 | UD_Isub, 620 | UD_Isubpd, 621 | UD_Isubps, 622 | UD_Isubsd, 623 | UD_Isubss, 624 | UD_Iswapgs, 625 | UD_Isyscall, 626 | UD_Isysenter, 627 | UD_Isysexit, 628 | UD_Isysret, 629 | UD_Itest, 630 | UD_Iucomisd, 631 | UD_Iucomiss, 632 | UD_Iud2, 633 | UD_Iunpckhpd, 634 | UD_Iunpckhps, 635 | UD_Iunpcklpd, 636 | UD_Iunpcklps, 637 | UD_Ivaddpd, 638 | UD_Ivaddps, 639 | UD_Ivaddsd, 640 | UD_Ivaddss, 641 | UD_Ivaddsubpd, 642 | UD_Ivaddsubps, 643 | UD_Ivaesdec, 644 | UD_Ivaesdeclast, 645 | UD_Ivaesenc, 646 | UD_Ivaesenclast, 647 | UD_Ivaesimc, 648 | UD_Ivaeskeygenassist, 649 | UD_Ivandnpd, 650 | UD_Ivandnps, 651 | UD_Ivandpd, 652 | UD_Ivandps, 653 | UD_Ivblendpd, 654 | UD_Ivblendps, 655 | UD_Ivblendvpd, 656 | UD_Ivblendvps, 657 | UD_Ivbroadcastsd, 658 | UD_Ivbroadcastss, 659 | UD_Ivcmppd, 660 | UD_Ivcmpps, 661 | UD_Ivcmpsd, 662 | UD_Ivcmpss, 663 | UD_Ivcomisd, 664 | UD_Ivcomiss, 665 | UD_Ivcvtdq2pd, 666 | UD_Ivcvtdq2ps, 667 | UD_Ivcvtpd2dq, 668 | UD_Ivcvtpd2ps, 669 | UD_Ivcvtps2dq, 670 | UD_Ivcvtps2pd, 671 | UD_Ivcvtsd2si, 672 | UD_Ivcvtsd2ss, 673 | UD_Ivcvtsi2sd, 674 | UD_Ivcvtsi2ss, 675 | UD_Ivcvtss2sd, 676 | UD_Ivcvtss2si, 677 | UD_Ivcvttpd2dq, 678 | UD_Ivcvttps2dq, 679 | UD_Ivcvttsd2si, 680 | UD_Ivcvttss2si, 681 | UD_Ivdivpd, 682 | UD_Ivdivps, 683 | UD_Ivdivsd, 684 | UD_Ivdivss, 685 | UD_Ivdppd, 686 | UD_Ivdpps, 687 | UD_Iverr, 688 | UD_Iverw, 689 | UD_Ivextractf128, 690 | UD_Ivextractps, 691 | UD_Ivhaddpd, 692 | UD_Ivhaddps, 693 | UD_Ivhsubpd, 694 | UD_Ivhsubps, 695 | UD_Ivinsertf128, 696 | UD_Ivinsertps, 697 | UD_Ivlddqu, 698 | UD_Ivmaskmovdqu, 699 | UD_Ivmaskmovpd, 700 | UD_Ivmaskmovps, 701 | UD_Ivmaxpd, 702 | UD_Ivmaxps, 703 | UD_Ivmaxsd, 704 | UD_Ivmaxss, 705 | UD_Ivmcall, 706 | UD_Ivmclear, 707 | UD_Ivminpd, 708 | UD_Ivminps, 709 | UD_Ivminsd, 710 | UD_Ivminss, 711 | UD_Ivmlaunch, 712 | UD_Ivmload, 713 | UD_Ivmmcall, 714 | UD_Ivmovapd, 715 | UD_Ivmovaps, 716 | UD_Ivmovd, 717 | UD_Ivmovddup, 718 | UD_Ivmovdqa, 719 | UD_Ivmovdqu, 720 | UD_Ivmovhlps, 721 | UD_Ivmovhpd, 722 | UD_Ivmovhps, 723 | UD_Ivmovlhps, 724 | UD_Ivmovlpd, 725 | UD_Ivmovlps, 726 | UD_Ivmovmskpd, 727 | UD_Ivmovmskps, 728 | UD_Ivmovntdq, 729 | UD_Ivmovntdqa, 730 | UD_Ivmovntpd, 731 | UD_Ivmovntps, 732 | UD_Ivmovq, 733 | UD_Ivmovsd, 734 | UD_Ivmovshdup, 735 | UD_Ivmovsldup, 736 | UD_Ivmovss, 737 | UD_Ivmovupd, 738 | UD_Ivmovups, 739 | UD_Ivmpsadbw, 740 | UD_Ivmptrld, 741 | UD_Ivmptrst, 742 | UD_Ivmread, 743 | UD_Ivmresume, 744 | UD_Ivmrun, 745 | UD_Ivmsave, 746 | UD_Ivmulpd, 747 | UD_Ivmulps, 748 | UD_Ivmulsd, 749 | UD_Ivmulss, 750 | UD_Ivmwrite, 751 | UD_Ivmxoff, 752 | UD_Ivmxon, 753 | UD_Ivorpd, 754 | UD_Ivorps, 755 | UD_Ivpabsb, 756 | UD_Ivpabsd, 757 | UD_Ivpabsw, 758 | UD_Ivpackssdw, 759 | UD_Ivpacksswb, 760 | UD_Ivpackusdw, 761 | UD_Ivpackuswb, 762 | UD_Ivpaddb, 763 | UD_Ivpaddd, 764 | UD_Ivpaddq, 765 | UD_Ivpaddsb, 766 | UD_Ivpaddsw, 767 | UD_Ivpaddusb, 768 | UD_Ivpaddusw, 769 | UD_Ivpaddw, 770 | UD_Ivpalignr, 771 | UD_Ivpand, 772 | UD_Ivpandn, 773 | UD_Ivpavgb, 774 | UD_Ivpavgw, 775 | UD_Ivpblendvb, 776 | UD_Ivpblendw, 777 | UD_Ivpclmulqdq, 778 | UD_Ivpcmpeqb, 779 | UD_Ivpcmpeqd, 780 | UD_Ivpcmpeqq, 781 | UD_Ivpcmpeqw, 782 | UD_Ivpcmpestri, 783 | UD_Ivpcmpestrm, 784 | UD_Ivpcmpgtb, 785 | UD_Ivpcmpgtd, 786 | UD_Ivpcmpgtq, 787 | UD_Ivpcmpgtw, 788 | UD_Ivpcmpistri, 789 | UD_Ivpcmpistrm, 790 | UD_Ivperm2f128, 791 | UD_Ivpermilpd, 792 | UD_Ivpermilps, 793 | UD_Ivpextrb, 794 | UD_Ivpextrd, 795 | UD_Ivpextrq, 796 | UD_Ivpextrw, 797 | UD_Ivphaddd, 798 | UD_Ivphaddsw, 799 | UD_Ivphaddw, 800 | UD_Ivphminposuw, 801 | UD_Ivphsubd, 802 | UD_Ivphsubsw, 803 | UD_Ivphsubw, 804 | UD_Ivpinsrb, 805 | UD_Ivpinsrd, 806 | UD_Ivpinsrq, 807 | UD_Ivpinsrw, 808 | UD_Ivpmaddubsw, 809 | UD_Ivpmaddwd, 810 | UD_Ivpmaxsb, 811 | UD_Ivpmaxsd, 812 | UD_Ivpmaxsw, 813 | UD_Ivpmaxub, 814 | UD_Ivpmaxud, 815 | UD_Ivpmaxuw, 816 | UD_Ivpminsb, 817 | UD_Ivpminsd, 818 | UD_Ivpminsw, 819 | UD_Ivpminub, 820 | UD_Ivpminud, 821 | UD_Ivpminuw, 822 | UD_Ivpmovmskb, 823 | UD_Ivpmovsxbd, 824 | UD_Ivpmovsxbq, 825 | UD_Ivpmovsxbw, 826 | UD_Ivpmovsxwd, 827 | UD_Ivpmovsxwq, 828 | UD_Ivpmovzxbd, 829 | UD_Ivpmovzxbq, 830 | UD_Ivpmovzxbw, 831 | UD_Ivpmovzxdq, 832 | UD_Ivpmovzxwd, 833 | UD_Ivpmovzxwq, 834 | UD_Ivpmuldq, 835 | UD_Ivpmulhrsw, 836 | UD_Ivpmulhuw, 837 | UD_Ivpmulhw, 838 | UD_Ivpmulld, 839 | UD_Ivpmullw, 840 | UD_Ivpor, 841 | UD_Ivpsadbw, 842 | UD_Ivpshufb, 843 | UD_Ivpshufd, 844 | UD_Ivpshufhw, 845 | UD_Ivpshuflw, 846 | UD_Ivpsignb, 847 | UD_Ivpsignd, 848 | UD_Ivpsignw, 849 | UD_Ivpslld, 850 | UD_Ivpslldq, 851 | UD_Ivpsllq, 852 | UD_Ivpsllw, 853 | UD_Ivpsrad, 854 | UD_Ivpsraw, 855 | UD_Ivpsrld, 856 | UD_Ivpsrldq, 857 | UD_Ivpsrlq, 858 | UD_Ivpsrlw, 859 | UD_Ivpsubb, 860 | UD_Ivpsubd, 861 | UD_Ivpsubq, 862 | UD_Ivpsubsb, 863 | UD_Ivpsubsw, 864 | UD_Ivpsubusb, 865 | UD_Ivpsubusw, 866 | UD_Ivpsubw, 867 | UD_Ivptest, 868 | UD_Ivpunpckhbw, 869 | UD_Ivpunpckhdq, 870 | UD_Ivpunpckhqdq, 871 | UD_Ivpunpckhwd, 872 | UD_Ivpunpcklbw, 873 | UD_Ivpunpckldq, 874 | UD_Ivpunpcklqdq, 875 | UD_Ivpunpcklwd, 876 | UD_Ivpxor, 877 | UD_Ivrcpps, 878 | UD_Ivrcpss, 879 | UD_Ivroundpd, 880 | UD_Ivroundps, 881 | UD_Ivroundsd, 882 | UD_Ivroundss, 883 | UD_Ivrsqrtps, 884 | UD_Ivrsqrtss, 885 | UD_Ivshufpd, 886 | UD_Ivshufps, 887 | UD_Ivsqrtpd, 888 | UD_Ivsqrtps, 889 | UD_Ivsqrtsd, 890 | UD_Ivsqrtss, 891 | UD_Ivstmxcsr, 892 | UD_Ivsubpd, 893 | UD_Ivsubps, 894 | UD_Ivsubsd, 895 | UD_Ivsubss, 896 | UD_Ivtestpd, 897 | UD_Ivtestps, 898 | UD_Ivucomisd, 899 | UD_Ivucomiss, 900 | UD_Ivunpckhpd, 901 | UD_Ivunpckhps, 902 | UD_Ivunpcklpd, 903 | UD_Ivunpcklps, 904 | UD_Ivxorpd, 905 | UD_Ivxorps, 906 | UD_Ivzeroall, 907 | UD_Ivzeroupper, 908 | UD_Iwait, 909 | UD_Iwbinvd, 910 | UD_Iwrmsr, 911 | UD_Ixadd, 912 | UD_Ixchg, 913 | UD_Ixcryptcbc, 914 | UD_Ixcryptcfb, 915 | UD_Ixcryptctr, 916 | UD_Ixcryptecb, 917 | UD_Ixcryptofb, 918 | UD_Ixgetbv, 919 | UD_Ixlatb, 920 | UD_Ixor, 921 | UD_Ixorpd, 922 | UD_Ixorps, 923 | UD_Ixrstor, 924 | UD_Ixsave, 925 | UD_Ixsetbv, 926 | UD_Ixsha1, 927 | UD_Ixsha256, 928 | UD_Ixstore, 929 | UD_Iinvalid, 930 | UD_I3dnow, 931 | UD_Inone, 932 | UD_Idb, 933 | UD_Ipause, 934 | UD_MAX_MNEMONIC_CODE 935 | }; 936 | 937 | extern const char * ud_mnemonics_str[]; 938 | 939 | #endif /* UD_ITAB_H */ 940 | -------------------------------------------------------------------------------- /udis86/syn-att.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn-att.c 2 | * 3 | * Copyright (c) 2002-2009 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 "extern.h" 28 | #include "decode.h" 29 | #include "itab.h" 30 | #include "syn.h" 31 | #include "udint.h" 32 | 33 | /* ----------------------------------------------------------------------------- 34 | * opr_cast() - Prints an operand cast. 35 | * ----------------------------------------------------------------------------- 36 | */ 37 | static void 38 | opr_cast(struct ud* u, struct ud_operand* op) 39 | { 40 | switch(op->size) { 41 | case 16 : case 32 : 42 | ud_asmprintf(u, "*"); break; 43 | default: break; 44 | } 45 | } 46 | 47 | /* ----------------------------------------------------------------------------- 48 | * gen_operand() - Generates assembly output for each operand. 49 | * ----------------------------------------------------------------------------- 50 | */ 51 | static void 52 | gen_operand(struct ud* u, struct ud_operand* op) 53 | { 54 | switch(op->type) { 55 | case UD_OP_CONST: 56 | ud_asmprintf(u, "$0x%x", op->lval.udword); 57 | break; 58 | 59 | case UD_OP_REG: 60 | ud_asmprintf(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); 61 | break; 62 | 63 | case UD_OP_MEM: 64 | if (u->br_far) { 65 | opr_cast(u, op); 66 | } 67 | if (u->pfx_seg) { 68 | ud_asmprintf(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); 69 | } 70 | if (op->offset != 0) { 71 | ud_syn_print_mem_disp(u, op, 0); 72 | } 73 | if (op->base) { 74 | ud_asmprintf(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); 75 | } 76 | if (op->index) { 77 | if (op->base) { 78 | ud_asmprintf(u, ","); 79 | } else { 80 | ud_asmprintf(u, "("); 81 | } 82 | ud_asmprintf(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); 83 | } 84 | if (op->scale) { 85 | ud_asmprintf(u, ",%d", op->scale); 86 | } 87 | if (op->base || op->index) { 88 | ud_asmprintf(u, ")"); 89 | } 90 | break; 91 | 92 | case UD_OP_IMM: 93 | ud_asmprintf(u, "$"); 94 | ud_syn_print_imm(u, op); 95 | break; 96 | 97 | case UD_OP_JIMM: 98 | ud_syn_print_addr(u, ud_syn_rel_target(u, op)); 99 | break; 100 | 101 | case UD_OP_PTR: 102 | switch (op->size) { 103 | case 32: 104 | ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, 105 | op->lval.ptr.off & 0xFFFF); 106 | break; 107 | case 48: 108 | ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, 109 | op->lval.ptr.off); 110 | break; 111 | } 112 | break; 113 | 114 | default: return; 115 | } 116 | } 117 | 118 | /* ============================================================================= 119 | * translates to AT&T syntax 120 | * ============================================================================= 121 | */ 122 | extern void 123 | ud_translate_att(struct ud *u) 124 | { 125 | int size = 0; 126 | int star = 0; 127 | 128 | /* check if P_OSO prefix is used */ 129 | if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { 130 | switch (u->dis_mode) { 131 | case 16: 132 | ud_asmprintf(u, "o32 "); 133 | break; 134 | case 32: 135 | case 64: 136 | ud_asmprintf(u, "o16 "); 137 | break; 138 | } 139 | } 140 | 141 | /* check if P_ASO prefix was used */ 142 | if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { 143 | switch (u->dis_mode) { 144 | case 16: 145 | ud_asmprintf(u, "a32 "); 146 | break; 147 | case 32: 148 | ud_asmprintf(u, "a16 "); 149 | break; 150 | case 64: 151 | ud_asmprintf(u, "a32 "); 152 | break; 153 | } 154 | } 155 | 156 | if (u->pfx_lock) 157 | ud_asmprintf(u, "lock "); 158 | if (u->pfx_rep) { 159 | ud_asmprintf(u, "rep "); 160 | } else if (u->pfx_repe) { 161 | ud_asmprintf(u, "repe "); 162 | } else if (u->pfx_repne) { 163 | ud_asmprintf(u, "repne "); 164 | } 165 | 166 | /* special instructions */ 167 | switch (u->mnemonic) { 168 | case UD_Iretf: 169 | ud_asmprintf(u, "lret "); 170 | break; 171 | case UD_Idb: 172 | ud_asmprintf(u, ".byte 0x%x", u->operand[0].lval.ubyte); 173 | return; 174 | case UD_Ijmp: 175 | case UD_Icall: 176 | if (u->br_far) ud_asmprintf(u, "l"); 177 | if (u->operand[0].type == UD_OP_REG) { 178 | star = 1; 179 | } 180 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 181 | break; 182 | case UD_Ibound: 183 | case UD_Ienter: 184 | if (u->operand[0].type != UD_NONE) 185 | gen_operand(u, &u->operand[0]); 186 | if (u->operand[1].type != UD_NONE) { 187 | ud_asmprintf(u, ","); 188 | gen_operand(u, &u->operand[1]); 189 | } 190 | return; 191 | default: 192 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 193 | } 194 | 195 | if (size == 8) { 196 | ud_asmprintf(u, "b"); 197 | } else if (size == 16) { 198 | ud_asmprintf(u, "w"); 199 | } else if (size == 64) { 200 | ud_asmprintf(u, "q"); 201 | } 202 | 203 | if (star) { 204 | ud_asmprintf(u, " *"); 205 | } else { 206 | ud_asmprintf(u, " "); 207 | } 208 | 209 | if (u->operand[3].type != UD_NONE) { 210 | gen_operand(u, &u->operand[3]); 211 | ud_asmprintf(u, ", "); 212 | } 213 | if (u->operand[2].type != UD_NONE) { 214 | gen_operand(u, &u->operand[2]); 215 | ud_asmprintf(u, ", "); 216 | } 217 | if (u->operand[1].type != UD_NONE) { 218 | gen_operand(u, &u->operand[1]); 219 | ud_asmprintf(u, ", "); 220 | } 221 | if (u->operand[0].type != UD_NONE) { 222 | gen_operand(u, &u->operand[0]); 223 | } 224 | } 225 | 226 | /* 227 | vim: set ts=2 sw=2 expandtab 228 | */ 229 | -------------------------------------------------------------------------------- /udis86/syn-intel.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn-intel.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 "extern.h" 28 | #include "decode.h" 29 | #include "itab.h" 30 | #include "syn.h" 31 | #include "udint.h" 32 | 33 | /* ----------------------------------------------------------------------------- 34 | * opr_cast() - Prints an operand cast. 35 | * ----------------------------------------------------------------------------- 36 | */ 37 | static void 38 | opr_cast(struct ud* u, struct ud_operand* op) 39 | { 40 | if (u->br_far) { 41 | ud_asmprintf(u, "far "); 42 | } 43 | switch(op->size) { 44 | case 8: ud_asmprintf(u, "byte " ); break; 45 | case 16: ud_asmprintf(u, "word " ); break; 46 | case 32: ud_asmprintf(u, "dword "); break; 47 | case 64: ud_asmprintf(u, "qword "); break; 48 | case 80: ud_asmprintf(u, "tword "); break; 49 | case 128: ud_asmprintf(u, "oword "); break; 50 | case 256: ud_asmprintf(u, "yword "); break; 51 | default: break; 52 | } 53 | } 54 | 55 | /* ----------------------------------------------------------------------------- 56 | * gen_operand() - Generates assembly output for each operand. 57 | * ----------------------------------------------------------------------------- 58 | */ 59 | static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast) 60 | { 61 | switch(op->type) { 62 | case UD_OP_REG: 63 | ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); 64 | break; 65 | 66 | case UD_OP_MEM: 67 | if (syn_cast) { 68 | opr_cast(u, op); 69 | } 70 | ud_asmprintf(u, "["); 71 | if (u->pfx_seg) { 72 | ud_asmprintf(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); 73 | } 74 | if (op->base) { 75 | ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); 76 | } 77 | if (op->index) { 78 | ud_asmprintf(u, "%s%s", op->base != UD_NONE? "+" : "", 79 | ud_reg_tab[op->index - UD_R_AL]); 80 | if (op->scale) { 81 | ud_asmprintf(u, "*%d", op->scale); 82 | } 83 | } 84 | if (op->offset != 0) { 85 | ud_syn_print_mem_disp(u, op, (op->base != UD_NONE || 86 | op->index != UD_NONE) ? 1 : 0); 87 | } 88 | ud_asmprintf(u, "]"); 89 | break; 90 | 91 | case UD_OP_IMM: 92 | ud_syn_print_imm(u, op); 93 | break; 94 | 95 | 96 | case UD_OP_JIMM: 97 | ud_syn_print_addr(u, ud_syn_rel_target(u, op)); 98 | break; 99 | 100 | case UD_OP_PTR: 101 | switch (op->size) { 102 | case 32: 103 | ud_asmprintf(u, "word 0x%x:0x%x", op->lval.ptr.seg, 104 | op->lval.ptr.off & 0xFFFF); 105 | break; 106 | case 48: 107 | ud_asmprintf(u, "dword 0x%x:0x%x", op->lval.ptr.seg, 108 | op->lval.ptr.off); 109 | break; 110 | } 111 | break; 112 | 113 | case UD_OP_CONST: 114 | if (syn_cast) opr_cast(u, op); 115 | ud_asmprintf(u, "%d", op->lval.udword); 116 | break; 117 | 118 | default: return; 119 | } 120 | } 121 | 122 | /* ============================================================================= 123 | * translates to intel syntax 124 | * ============================================================================= 125 | */ 126 | extern void 127 | ud_translate_intel(struct ud* u) 128 | { 129 | /* check if P_OSO prefix is used */ 130 | if (!P_OSO(u->itab_entry->prefix) && u->pfx_opr) { 131 | switch (u->dis_mode) { 132 | case 16: ud_asmprintf(u, "o32 "); break; 133 | case 32: 134 | case 64: ud_asmprintf(u, "o16 "); break; 135 | } 136 | } 137 | 138 | /* check if P_ASO prefix was used */ 139 | if (!P_ASO(u->itab_entry->prefix) && u->pfx_adr) { 140 | switch (u->dis_mode) { 141 | case 16: ud_asmprintf(u, "a32 "); break; 142 | case 32: ud_asmprintf(u, "a16 "); break; 143 | case 64: ud_asmprintf(u, "a32 "); break; 144 | } 145 | } 146 | 147 | if (u->pfx_seg && 148 | u->operand[0].type != UD_OP_MEM && 149 | u->operand[1].type != UD_OP_MEM ) { 150 | ud_asmprintf(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]); 151 | } 152 | 153 | if (u->pfx_lock) { 154 | ud_asmprintf(u, "lock "); 155 | } 156 | if (u->pfx_rep) { 157 | ud_asmprintf(u, "rep "); 158 | } else if (u->pfx_repe) { 159 | ud_asmprintf(u, "repe "); 160 | } else if (u->pfx_repne) { 161 | ud_asmprintf(u, "repne "); 162 | } 163 | 164 | /* print the instruction mnemonic */ 165 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 166 | 167 | if (u->operand[0].type != UD_NONE) { 168 | int cast = 0; 169 | ud_asmprintf(u, " "); 170 | if (u->operand[0].type == UD_OP_MEM) { 171 | if (u->operand[1].type == UD_OP_IMM || 172 | u->operand[1].type == UD_OP_CONST || 173 | u->operand[1].type == UD_NONE || 174 | (u->operand[0].size != u->operand[1].size)) { 175 | cast = 1; 176 | } else if (u->operand[1].type == UD_OP_REG && 177 | u->operand[1].base == UD_R_CL) { 178 | switch (u->mnemonic) { 179 | case UD_Ircl: 180 | case UD_Irol: 181 | case UD_Iror: 182 | case UD_Ircr: 183 | case UD_Ishl: 184 | case UD_Ishr: 185 | case UD_Isar: 186 | cast = 1; 187 | break; 188 | default: break; 189 | } 190 | } 191 | } 192 | gen_operand(u, &u->operand[0], cast); 193 | } 194 | 195 | if (u->operand[1].type != UD_NONE) { 196 | int cast = 0; 197 | ud_asmprintf(u, ", "); 198 | if (u->operand[1].type == UD_OP_MEM && 199 | u->operand[0].size != u->operand[1].size && 200 | !ud_opr_is_sreg(&u->operand[0])) { 201 | cast = 1; 202 | } 203 | gen_operand(u, &u->operand[1], cast); 204 | } 205 | 206 | if (u->operand[2].type != UD_NONE) { 207 | int cast = 0; 208 | ud_asmprintf(u, ", "); 209 | if (u->operand[2].type == UD_OP_MEM && 210 | u->operand[2].size != u->operand[1].size) { 211 | cast = 1; 212 | } 213 | gen_operand(u, &u->operand[2], cast); 214 | } 215 | 216 | if (u->operand[3].type != UD_NONE) { 217 | ud_asmprintf(u, ", "); 218 | gen_operand(u, &u->operand[3], 0); 219 | } 220 | } 221 | 222 | /* 223 | vim: set ts=2 sw=2 expandtab 224 | */ 225 | -------------------------------------------------------------------------------- /udis86/syn.c: -------------------------------------------------------------------------------- 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 | * 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 | "ymm0", "ymm1", "ymm2", "ymm3", 83 | "ymm4", "ymm5", "ymm6", "ymm7", 84 | "ymm8", "ymm9", "ymm10", "ymm11", 85 | "ymm12", "ymm13", "ymm14", "ymm15", 86 | 87 | "rip" 88 | }; 89 | 90 | 91 | uint64_t 92 | ud_syn_rel_target(struct ud *u, struct ud_operand *opr) 93 | { 94 | const uint64_t trunc_mask = 0xffffffffffffffffull >> (64 - u->opr_mode); 95 | switch (opr->size) { 96 | case 8 : return (u->pc + opr->lval.sbyte) & trunc_mask; 97 | case 16: return (u->pc + opr->lval.sword) & trunc_mask; 98 | case 32: return (u->pc + opr->lval.sdword) & trunc_mask; 99 | default: UD_ASSERT(!"invalid relative offset size."); 100 | return 0ull; 101 | } 102 | } 103 | 104 | 105 | /* 106 | * asmprintf 107 | * Printf style function for printing translated assembly 108 | * output. Returns the number of characters written and 109 | * moves the buffer pointer forward. On an overflow, 110 | * returns a negative number and truncates the output. 111 | */ 112 | int 113 | ud_asmprintf(struct ud *u, const char *fmt, ...) 114 | { 115 | int ret; 116 | int avail; 117 | va_list ap; 118 | va_start(ap, fmt); 119 | avail = u->asm_buf_size - u->asm_buf_fill - 1 /* nullchar */; 120 | ret = vsnprintf((char*) u->asm_buf + u->asm_buf_fill, avail, fmt, ap); 121 | if (ret < 0 || ret > avail) { 122 | u->asm_buf_fill = u->asm_buf_size - 1; 123 | } else { 124 | u->asm_buf_fill += ret; 125 | } 126 | va_end(ap); 127 | return ret; 128 | } 129 | 130 | 131 | void 132 | ud_syn_print_addr(struct ud *u, uint64_t addr) 133 | { 134 | const char *name = NULL; 135 | if (u->sym_resolver) { 136 | int64_t offset = 0; 137 | name = u->sym_resolver(u, addr, &offset); 138 | if (name) { 139 | if (offset) { 140 | ud_asmprintf(u, "%s%+" FMT64 "d", name, offset); 141 | } else { 142 | ud_asmprintf(u, "%s", name); 143 | } 144 | return; 145 | } 146 | } 147 | ud_asmprintf(u, "0x%" FMT64 "x", addr); 148 | } 149 | 150 | 151 | void 152 | ud_syn_print_imm(struct ud* u, const struct ud_operand *op) 153 | { 154 | uint64_t v; 155 | if (op->_oprcode == OP_sI && op->size != u->opr_mode) { 156 | if (op->size == 8) { 157 | v = (int64_t)op->lval.sbyte; 158 | } else { 159 | UD_ASSERT(op->size == 32); 160 | v = (int64_t)op->lval.sdword; 161 | } 162 | if (u->opr_mode < 64) { 163 | v = v & ((1ull << u->opr_mode) - 1ull); 164 | } 165 | } else { 166 | switch (op->size) { 167 | case 8 : v = op->lval.ubyte; break; 168 | case 16: v = op->lval.uword; break; 169 | case 32: v = op->lval.udword; break; 170 | case 64: v = op->lval.uqword; break; 171 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ 172 | } 173 | } 174 | ud_asmprintf(u, "0x%" FMT64 "x", v); 175 | } 176 | 177 | 178 | void 179 | ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign) 180 | { 181 | UD_ASSERT(op->offset != 0); 182 | if (op->base == UD_NONE && op->index == UD_NONE) { 183 | uint64_t v; 184 | UD_ASSERT(op->scale == UD_NONE && op->offset != 8); 185 | /* unsigned mem-offset */ 186 | switch (op->offset) { 187 | case 16: v = op->lval.uword; break; 188 | case 32: v = op->lval.udword; break; 189 | case 64: v = op->lval.uqword; break; 190 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ 191 | } 192 | ud_asmprintf(u, "0x%" FMT64 "x", v); 193 | } else { 194 | int64_t v; 195 | UD_ASSERT(op->offset != 64); 196 | switch (op->offset) { 197 | case 8 : v = op->lval.sbyte; break; 198 | case 16: v = op->lval.sword; break; 199 | case 32: v = op->lval.sdword; break; 200 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ 201 | } 202 | if (v < 0) { 203 | ud_asmprintf(u, "-0x%" FMT64 "x", -v); 204 | } else if (v > 0) { 205 | ud_asmprintf(u, "%s0x%" FMT64 "x", sign? "+" : "", v); 206 | } 207 | } 208 | } 209 | 210 | /* 211 | vim: set ts=2 sw=2 expandtab 212 | */ 213 | -------------------------------------------------------------------------------- /udis86/syn.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn.h 2 | * 3 | * Copyright (c) 2002-2009 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 | #ifndef UD_SYN_H 27 | #define UD_SYN_H 28 | 29 | #include "types.h" 30 | #ifndef __UD_STANDALONE__ 31 | # include 32 | #endif /* __UD_STANDALONE__ */ 33 | 34 | extern const char* ud_reg_tab[]; 35 | 36 | uint64_t ud_syn_rel_target(struct ud*, struct ud_operand*); 37 | 38 | #ifdef __GNUC__ 39 | int ud_asmprintf(struct ud *u, const char *fmt, ...) 40 | __attribute__ ((format (printf, 2, 3))); 41 | #else 42 | int ud_asmprintf(struct ud *u, const char *fmt, ...); 43 | #endif 44 | 45 | void ud_syn_print_addr(struct ud *u, uint64_t addr); 46 | void ud_syn_print_imm(struct ud* u, const struct ud_operand *op); 47 | void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *, int sign); 48 | 49 | #endif /* UD_SYN_H */ 50 | 51 | /* 52 | vim: set ts=2 sw=2 expandtab 53 | */ 54 | -------------------------------------------------------------------------------- /udis86/types.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/types.h 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 | #ifndef UD_TYPES_H 27 | #define UD_TYPES_H 28 | 29 | #ifdef __KERNEL__ 30 | /* 31 | * -D__KERNEL__ is automatically passed on the command line when 32 | * building something as part of the Linux kernel. Assume standalone 33 | * mode. 34 | */ 35 | # include 36 | # include 37 | # ifndef __UD_STANDALONE__ 38 | # define __UD_STANDALONE__ 1 39 | # endif 40 | #endif /* __KERNEL__ */ 41 | 42 | #if !defined(__UD_STANDALONE__) 43 | # include 44 | # include 45 | #endif 46 | 47 | /* gcc specific extensions */ 48 | #ifdef __GNUC__ 49 | # define UD_ATTR_PACKED __attribute__((packed)) 50 | #else 51 | # define UD_ATTR_PACKED 52 | #endif /* UD_ATTR_PACKED */ 53 | 54 | 55 | /* ----------------------------------------------------------------------------- 56 | * All possible "types" of objects in udis86. Order is Important! 57 | * ----------------------------------------------------------------------------- 58 | */ 59 | enum ud_type 60 | { 61 | UD_NONE, 62 | 63 | /* 8 bit GPRs */ 64 | UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL, 65 | UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH, 66 | UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL, 67 | UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B, 68 | UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B, 69 | 70 | /* 16 bit GPRs */ 71 | UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX, 72 | UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI, 73 | UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W, 74 | UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W, 75 | 76 | /* 32 bit GPRs */ 77 | UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX, 78 | UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI, 79 | UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D, 80 | UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D, 81 | 82 | /* 64 bit GPRs */ 83 | UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX, 84 | UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI, 85 | UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11, 86 | UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15, 87 | 88 | /* segment registers */ 89 | UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS, 90 | UD_R_FS, UD_R_GS, 91 | 92 | /* control registers*/ 93 | UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3, 94 | UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7, 95 | UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11, 96 | UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15, 97 | 98 | /* debug registers */ 99 | UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3, 100 | UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7, 101 | UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11, 102 | UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15, 103 | 104 | /* mmx registers */ 105 | UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3, 106 | UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7, 107 | 108 | /* x87 registers */ 109 | UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3, 110 | UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7, 111 | 112 | /* extended multimedia registers */ 113 | UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3, 114 | UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7, 115 | UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11, 116 | UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15, 117 | 118 | /* 256B multimedia registers */ 119 | UD_R_YMM0, UD_R_YMM1, UD_R_YMM2, UD_R_YMM3, 120 | UD_R_YMM4, UD_R_YMM5, UD_R_YMM6, UD_R_YMM7, 121 | UD_R_YMM8, UD_R_YMM9, UD_R_YMM10, UD_R_YMM11, 122 | UD_R_YMM12, UD_R_YMM13, UD_R_YMM14, UD_R_YMM15, 123 | 124 | UD_R_RIP, 125 | 126 | /* Operand Types */ 127 | UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM, 128 | UD_OP_JIMM, UD_OP_CONST 129 | }; 130 | 131 | #include "itab.h" 132 | 133 | union ud_lval { 134 | int8_t sbyte; 135 | uint8_t ubyte; 136 | int16_t sword; 137 | uint16_t uword; 138 | int32_t sdword; 139 | uint32_t udword; 140 | int64_t sqword; 141 | uint64_t uqword; 142 | struct { 143 | uint16_t seg; 144 | uint32_t off; 145 | } ptr; 146 | }; 147 | 148 | /* ----------------------------------------------------------------------------- 149 | * struct ud_operand - Disassembled instruction Operand. 150 | * ----------------------------------------------------------------------------- 151 | */ 152 | struct ud_operand { 153 | enum ud_type type; 154 | uint16_t size; 155 | enum ud_type base; 156 | enum ud_type index; 157 | uint8_t scale; 158 | uint8_t offset; 159 | union ud_lval lval; 160 | /* 161 | * internal use only 162 | */ 163 | uint64_t _legacy; /* this will be removed in 1.8 */ 164 | uint8_t _oprcode; 165 | }; 166 | 167 | /* ----------------------------------------------------------------------------- 168 | * struct ud - The udis86 object. 169 | * ----------------------------------------------------------------------------- 170 | */ 171 | struct ud 172 | { 173 | /* 174 | * input buffering 175 | */ 176 | int (*inp_hook) (struct ud*); 177 | #ifndef __UD_STANDALONE__ 178 | FILE* inp_file; 179 | #endif 180 | const uint8_t* inp_buf; 181 | size_t inp_buf_size; 182 | size_t inp_buf_index; 183 | uint8_t inp_curr; 184 | size_t inp_ctr; 185 | uint8_t inp_sess[64]; 186 | int inp_end; 187 | int inp_peek; 188 | 189 | void (*translator)(struct ud*); 190 | uint64_t insn_offset; 191 | char insn_hexcode[64]; 192 | 193 | /* 194 | * Assembly output buffer 195 | */ 196 | char *asm_buf; 197 | size_t asm_buf_size; 198 | size_t asm_buf_fill; 199 | char asm_buf_int[128]; 200 | 201 | /* 202 | * Symbol resolver for use in the translation phase. 203 | */ 204 | const char* (*sym_resolver)(struct ud*, uint64_t addr, int64_t *offset); 205 | 206 | uint8_t dis_mode; 207 | uint64_t pc; 208 | uint8_t vendor; 209 | enum ud_mnemonic_code mnemonic; 210 | struct ud_operand operand[4]; 211 | uint8_t error; 212 | uint8_t _rex; 213 | uint8_t pfx_rex; 214 | uint8_t pfx_seg; 215 | uint8_t pfx_opr; 216 | uint8_t pfx_adr; 217 | uint8_t pfx_lock; 218 | uint8_t pfx_str; 219 | uint8_t pfx_rep; 220 | uint8_t pfx_repe; 221 | uint8_t pfx_repne; 222 | uint8_t opr_mode; 223 | uint8_t adr_mode; 224 | uint8_t br_far; 225 | uint8_t br_near; 226 | uint8_t have_modrm; 227 | uint8_t modrm; 228 | uint8_t modrm_offset; 229 | uint8_t vex_op; 230 | uint8_t vex_b1; 231 | uint8_t vex_b2; 232 | uint8_t primary_opcode; 233 | void * user_opaque_data; 234 | struct ud_itab_entry * itab_entry; 235 | struct ud_lookup_table_list_entry *le; 236 | }; 237 | 238 | /* ----------------------------------------------------------------------------- 239 | * Type-definitions 240 | * ----------------------------------------------------------------------------- 241 | */ 242 | typedef enum ud_type ud_type_t; 243 | typedef enum ud_mnemonic_code ud_mnemonic_code_t; 244 | 245 | typedef struct ud ud_t; 246 | typedef struct ud_operand ud_operand_t; 247 | 248 | #define UD_SYN_INTEL ud_translate_intel 249 | #define UD_SYN_ATT ud_translate_att 250 | #define UD_EOI (-1) 251 | #define UD_INP_CACHE_SZ 32 252 | #define UD_VENDOR_AMD 0 253 | #define UD_VENDOR_INTEL 1 254 | #define UD_VENDOR_ANY 2 255 | 256 | #endif 257 | 258 | /* 259 | vim: set ts=2 sw=2 expandtab 260 | */ 261 | -------------------------------------------------------------------------------- /udis86/udint.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/udint.h -- definitions for internal use only 2 | * 3 | * Copyright (c) 2002-2009 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 | #ifndef _UDINT_H_ 27 | #define _UDINT_H_ 28 | 29 | #include "types.h" 30 | 31 | #ifdef HAVE_CONFIG_H 32 | # include 33 | #endif /* HAVE_CONFIG_H */ 34 | 35 | #if defined(UD_DEBUG) && HAVE_ASSERT_H 36 | # include 37 | # define UD_ASSERT(_x) assert(_x) 38 | #else 39 | # define UD_ASSERT(_x) 40 | #endif /* !HAVE_ASSERT_H */ 41 | 42 | #if defined(UD_DEBUG) 43 | #define UDERR(u, msg) \ 44 | do { \ 45 | (u)->error = 1; \ 46 | fprintf(stderr, "decode-error: %s:%d: %s", \ 47 | __FILE__, __LINE__, (msg)); \ 48 | } while (0) 49 | #else 50 | #define UDERR(u, m) \ 51 | do { \ 52 | (u)->error = 1; \ 53 | } while (0) 54 | #endif /* !LOGERR */ 55 | 56 | #define UD_RETURN_ON_ERROR(u) \ 57 | do { \ 58 | if ((u)->error != 0) { \ 59 | return (u)->error; \ 60 | } \ 61 | } while (0) 62 | 63 | #define UD_RETURN_WITH_ERROR(u, m) \ 64 | do { \ 65 | UDERR(u, m); \ 66 | return (u)->error; \ 67 | } while (0) 68 | 69 | #ifndef __UD_STANDALONE__ 70 | # define UD_NON_STANDALONE(x) x 71 | #else 72 | # define UD_NON_STANDALONE(x) 73 | #endif 74 | 75 | /* printf formatting int64 specifier */ 76 | #ifdef FMT64 77 | # undef FMT64 78 | #endif 79 | #if defined(_MSC_VER) || defined(__BORLANDC__) 80 | # define FMT64 "I64" 81 | #else 82 | # define FMT64 "ll" 83 | #endif 84 | 85 | /* define an inline macro */ 86 | #if defined(_MSC_VER) || defined(__BORLANDC__) 87 | # define UD_INLINE __inline /* MS Visual Studio requires __inline 88 | instead of inline for C code */ 89 | #else 90 | # define UD_INLINE inline 91 | #endif 92 | 93 | #endif /* _UDINT_H_ */ 94 | -------------------------------------------------------------------------------- /udis86/udis86.c: -------------------------------------------------------------------------------- 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 | #if !defined(__UD_STANDALONE__) 32 | # if HAVE_STRING_H 33 | # include 34 | # endif 35 | #endif /* !__UD_STANDALONE__ */ 36 | 37 | static void ud_inp_init(struct ud *u); 38 | 39 | /* ============================================================================= 40 | * ud_init 41 | * Initializes ud_t object. 42 | * ============================================================================= 43 | */ 44 | extern void 45 | ud_init(struct ud* u) 46 | { 47 | memset((void*)u, 0, sizeof(struct ud)); 48 | ud_set_mode(u, 16); 49 | u->mnemonic = UD_Iinvalid; 50 | ud_set_pc(u, 0); 51 | #ifndef __UD_STANDALONE__ 52 | ud_set_input_file(u, stdin); 53 | #endif /* __UD_STANDALONE__ */ 54 | 55 | ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); 56 | } 57 | 58 | 59 | /* ============================================================================= 60 | * ud_disassemble 61 | * Disassembles one instruction and returns the number of 62 | * bytes disassembled. A zero means end of disassembly. 63 | * ============================================================================= 64 | */ 65 | extern unsigned int 66 | ud_disassemble(struct ud* u) 67 | { 68 | int len; 69 | if (u->inp_end) { 70 | return 0; 71 | } 72 | if ((len = ud_decode(u)) > 0) { 73 | if (u->translator != NULL) { 74 | u->asm_buf[0] = '\0'; 75 | u->translator(u); 76 | } 77 | } 78 | return len; 79 | } 80 | 81 | 82 | /* ============================================================================= 83 | * ud_set_mode() - Set Disassemly Mode. 84 | * ============================================================================= 85 | */ 86 | extern void 87 | ud_set_mode(struct ud* u, uint8_t m) 88 | { 89 | switch(m) { 90 | case 16: 91 | case 32: 92 | case 64: u->dis_mode = m ; return; 93 | default: u->dis_mode = 16; return; 94 | } 95 | } 96 | 97 | /* ============================================================================= 98 | * ud_set_vendor() - Set vendor. 99 | * ============================================================================= 100 | */ 101 | extern void 102 | ud_set_vendor(struct ud* u, unsigned v) 103 | { 104 | switch(v) { 105 | case UD_VENDOR_INTEL: 106 | u->vendor = v; 107 | break; 108 | case UD_VENDOR_ANY: 109 | u->vendor = v; 110 | break; 111 | default: 112 | u->vendor = UD_VENDOR_AMD; 113 | } 114 | } 115 | 116 | /* ============================================================================= 117 | * ud_set_pc() - Sets code origin. 118 | * ============================================================================= 119 | */ 120 | extern void 121 | ud_set_pc(struct ud* u, uint64_t o) 122 | { 123 | u->pc = o; 124 | } 125 | 126 | /* ============================================================================= 127 | * ud_set_syntax() - Sets the output syntax. 128 | * ============================================================================= 129 | */ 130 | extern void 131 | ud_set_syntax(struct ud* u, void (*t)(struct ud*)) 132 | { 133 | u->translator = t; 134 | } 135 | 136 | /* ============================================================================= 137 | * ud_insn() - returns the disassembled instruction 138 | * ============================================================================= 139 | */ 140 | const char* 141 | ud_insn_asm(const struct ud* u) 142 | { 143 | return u->asm_buf; 144 | } 145 | 146 | /* ============================================================================= 147 | * ud_insn_offset() - Returns the offset. 148 | * ============================================================================= 149 | */ 150 | uint64_t 151 | ud_insn_off(const struct ud* u) 152 | { 153 | return u->insn_offset; 154 | } 155 | 156 | 157 | /* ============================================================================= 158 | * ud_insn_hex() - Returns hex form of disassembled instruction. 159 | * ============================================================================= 160 | */ 161 | const char* 162 | ud_insn_hex(struct ud* u) 163 | { 164 | u->insn_hexcode[0] = 0; 165 | if (!u->error) { 166 | unsigned int i; 167 | const unsigned char *src_ptr = ud_insn_ptr(u); 168 | char* src_hex; 169 | src_hex = (char*) u->insn_hexcode; 170 | /* for each byte used to decode instruction */ 171 | for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2; 172 | ++i, ++src_ptr) { 173 | sprintf(src_hex, "%02x", *src_ptr & 0xFF); 174 | src_hex += 2; 175 | } 176 | } 177 | return u->insn_hexcode; 178 | } 179 | 180 | 181 | /* ============================================================================= 182 | * ud_insn_ptr 183 | * Returns a pointer to buffer containing the bytes that were 184 | * disassembled. 185 | * ============================================================================= 186 | */ 187 | extern const uint8_t* 188 | ud_insn_ptr(const struct ud* u) 189 | { 190 | return (u->inp_buf == NULL) ? 191 | u->inp_sess : u->inp_buf + (u->inp_buf_index - u->inp_ctr); 192 | } 193 | 194 | 195 | /* ============================================================================= 196 | * ud_insn_len 197 | * Returns the count of bytes disassembled. 198 | * ============================================================================= 199 | */ 200 | extern unsigned int 201 | ud_insn_len(const struct ud* u) 202 | { 203 | return u->inp_ctr; 204 | } 205 | 206 | 207 | /* ============================================================================= 208 | * ud_insn_get_opr 209 | * Return the operand struct representing the nth operand of 210 | * the currently disassembled instruction. Returns NULL if 211 | * there's no such operand. 212 | * ============================================================================= 213 | */ 214 | const struct ud_operand* 215 | ud_insn_opr(const struct ud *u, unsigned int n) 216 | { 217 | if (n > 3 || u->operand[n].type == UD_NONE) { 218 | return NULL; 219 | } else { 220 | return &u->operand[n]; 221 | } 222 | } 223 | 224 | 225 | /* ============================================================================= 226 | * ud_opr_is_sreg 227 | * Returns non-zero if the given operand is of a segment register type. 228 | * ============================================================================= 229 | */ 230 | int 231 | ud_opr_is_sreg(const struct ud_operand *opr) 232 | { 233 | return opr->type == UD_OP_REG && 234 | opr->base >= UD_R_ES && 235 | opr->base <= UD_R_GS; 236 | } 237 | 238 | 239 | /* ============================================================================= 240 | * ud_opr_is_sreg 241 | * Returns non-zero if the given operand is of a general purpose 242 | * register type. 243 | * ============================================================================= 244 | */ 245 | int 246 | ud_opr_is_gpr(const struct ud_operand *opr) 247 | { 248 | return opr->type == UD_OP_REG && 249 | opr->base >= UD_R_AL && 250 | opr->base <= UD_R_R15; 251 | } 252 | 253 | 254 | /* ============================================================================= 255 | * ud_set_user_opaque_data 256 | * ud_get_user_opaque_data 257 | * Get/set user opaqute data pointer 258 | * ============================================================================= 259 | */ 260 | void 261 | ud_set_user_opaque_data(struct ud * u, void* opaque) 262 | { 263 | u->user_opaque_data = opaque; 264 | } 265 | 266 | void* 267 | ud_get_user_opaque_data(const struct ud *u) 268 | { 269 | return u->user_opaque_data; 270 | } 271 | 272 | 273 | /* ============================================================================= 274 | * ud_set_asm_buffer 275 | * Allow the user to set an assembler output buffer. If `buf` is NULL, 276 | * we switch back to the internal buffer. 277 | * ============================================================================= 278 | */ 279 | void 280 | ud_set_asm_buffer(struct ud *u, char *buf, size_t size) 281 | { 282 | if (buf == NULL) { 283 | ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); 284 | } else { 285 | u->asm_buf = buf; 286 | u->asm_buf_size = size; 287 | } 288 | } 289 | 290 | 291 | /* ============================================================================= 292 | * ud_set_sym_resolver 293 | * Set symbol resolver for relative targets used in the translation 294 | * phase. 295 | * 296 | * The resolver is a function that takes a uint64_t address and returns a 297 | * symbolic name for the that address. The function also takes a second 298 | * argument pointing to an integer that the client can optionally set to a 299 | * non-zero value for offsetted targets. (symbol+offset) The function may 300 | * also return NULL, in which case the translator only prints the target 301 | * address. 302 | * 303 | * The function pointer maybe NULL which resets symbol resolution. 304 | * ============================================================================= 305 | */ 306 | void 307 | ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*, 308 | uint64_t addr, 309 | int64_t *offset)) 310 | { 311 | u->sym_resolver = resolver; 312 | } 313 | 314 | 315 | /* ============================================================================= 316 | * ud_insn_mnemonic 317 | * Return the current instruction mnemonic. 318 | * ============================================================================= 319 | */ 320 | enum ud_mnemonic_code 321 | ud_insn_mnemonic(const struct ud *u) 322 | { 323 | return u->mnemonic; 324 | } 325 | 326 | 327 | /* ============================================================================= 328 | * ud_lookup_mnemonic 329 | * Looks up mnemonic code in the mnemonic string table. 330 | * Returns NULL if the mnemonic code is invalid. 331 | * ============================================================================= 332 | */ 333 | const char* 334 | ud_lookup_mnemonic(enum ud_mnemonic_code c) 335 | { 336 | if (c < UD_MAX_MNEMONIC_CODE) { 337 | return ud_mnemonics_str[c]; 338 | } else { 339 | return NULL; 340 | } 341 | } 342 | 343 | 344 | /* 345 | * ud_inp_init 346 | * Initializes the input system. 347 | */ 348 | static void 349 | ud_inp_init(struct ud *u) 350 | { 351 | u->inp_hook = NULL; 352 | u->inp_buf = NULL; 353 | u->inp_buf_size = 0; 354 | u->inp_buf_index = 0; 355 | u->inp_curr = 0; 356 | u->inp_ctr = 0; 357 | u->inp_end = 0; 358 | u->inp_peek = UD_EOI; 359 | UD_NON_STANDALONE(u->inp_file = NULL); 360 | } 361 | 362 | 363 | /* ============================================================================= 364 | * ud_inp_set_hook 365 | * Sets input hook. 366 | * ============================================================================= 367 | */ 368 | void 369 | ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) 370 | { 371 | ud_inp_init(u); 372 | u->inp_hook = hook; 373 | } 374 | 375 | /* ============================================================================= 376 | * ud_inp_set_buffer 377 | * Set buffer as input. 378 | * ============================================================================= 379 | */ 380 | void 381 | ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len) 382 | { 383 | ud_inp_init(u); 384 | u->inp_buf = buf; 385 | u->inp_buf_size = len; 386 | u->inp_buf_index = 0; 387 | } 388 | 389 | 390 | #ifndef __UD_STANDALONE__ 391 | /* ============================================================================= 392 | * ud_input_set_file 393 | * Set FILE as input. 394 | * ============================================================================= 395 | */ 396 | static int 397 | inp_file_hook(struct ud* u) 398 | { 399 | return fgetc(u->inp_file); 400 | } 401 | 402 | void 403 | ud_set_input_file(register struct ud* u, FILE* f) 404 | { 405 | ud_inp_init(u); 406 | u->inp_hook = inp_file_hook; 407 | u->inp_file = f; 408 | } 409 | #endif /* __UD_STANDALONE__ */ 410 | 411 | 412 | /* ============================================================================= 413 | * ud_input_skip 414 | * Skip n input bytes. 415 | * ============================================================================ 416 | */ 417 | void 418 | ud_input_skip(struct ud* u, size_t n) 419 | { 420 | if (u->inp_end) { 421 | return; 422 | } 423 | if (u->inp_buf == NULL) { 424 | while (n--) { 425 | int c = u->inp_hook(u); 426 | if (c == UD_EOI) { 427 | goto eoi; 428 | } 429 | } 430 | return; 431 | } else { 432 | if (n > u->inp_buf_size || 433 | u->inp_buf_index > u->inp_buf_size - n) { 434 | u->inp_buf_index = u->inp_buf_size; 435 | goto eoi; 436 | } 437 | u->inp_buf_index += n; 438 | return; 439 | } 440 | eoi: 441 | u->inp_end = 1; 442 | UDERR(u, "cannot skip, eoi received\b"); 443 | return; 444 | } 445 | 446 | 447 | /* ============================================================================= 448 | * ud_input_end 449 | * Returns non-zero on end-of-input. 450 | * ============================================================================= 451 | */ 452 | int 453 | ud_input_end(const struct ud *u) 454 | { 455 | return u->inp_end; 456 | } 457 | 458 | /* vim:set ts=2 sw=2 expandtab */ 459 | -------------------------------------------------------------------------------- /udis86/udis86.h: -------------------------------------------------------------------------------- 1 | /* udis86 - udis86.h 2 | * 3 | * Copyright (c) 2002-2009 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 | #ifndef UDIS86_H 27 | #define UDIS86_H 28 | 29 | #include "types.h" 30 | #include "extern.h" 31 | #include "itab.h" 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * inl_hook util. 3 | */ 4 | #define KMSG_COMPONENT "KINL_HOOK" 5 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "util.h" 17 | #include "inl_hook.h" 18 | 19 | 20 | struct instr_range { 21 | unsigned long start; 22 | unsigned long end; 23 | }; 24 | 25 | 26 | struct hook_cbdata { 27 | struct hook_ops *ops; 28 | int count; 29 | struct instr_range ir; 30 | }; 31 | 32 | 33 | #define MAX_HOOK_CODE_BYTES 32 34 | #define MAX_STACK_TRACE_DEPTH 64 35 | static unsigned long stack_entries[MAX_STACK_TRACE_DEPTH]; 36 | struct stack_trace trace = { 37 | .max_entries = ARRAY_SIZE(stack_entries), 38 | .entries = &stack_entries[0], 39 | }; 40 | 41 | 42 | static bool inline 43 | within_address(unsigned long address, struct instr_range *ir) 44 | { 45 | return address >= ir->start && address < ir->end; 46 | } 47 | 48 | 49 | bool find_ksymbol(struct symbol_ops *ops, int n) 50 | { 51 | int i; 52 | void **addr; 53 | const char *name; 54 | 55 | for (i = 0; i < n; i++) { 56 | addr = ops[i].addr; 57 | name = ops[i].symbol; 58 | 59 | *addr = (void *) kallsyms_lookup_name(name); 60 | if (*addr == NULL) { 61 | pr_err("not find %s.\n", name); 62 | return false; 63 | } 64 | } 65 | 66 | return true; 67 | } 68 | 69 | 70 | static int 71 | inl_sethook_safe_verify(struct hook_ops *ops, int count) 72 | { 73 | struct instr_range ir; 74 | struct task_struct *g, *t; 75 | int i, j; 76 | void *orig; 77 | int ret = 0; 78 | 79 | /* Check the stacks of all tasks. */ 80 | do_each_thread(g, t) { 81 | 82 | trace.nr_entries = 0; 83 | save_stack_trace_tsk(t, &trace); 84 | if (trace.nr_entries >= trace.max_entries) { 85 | ret = -EBUSY; 86 | pr_err("more than %u trace entries!\n", 87 | trace.max_entries); 88 | goto out; 89 | } 90 | 91 | for (i = 0; i < trace.nr_entries; i++) { 92 | if (trace.entries[i] == ULONG_MAX) 93 | break; 94 | 95 | for (j = 0; j < count; j++) { 96 | orig = *(ops[j].orig); 97 | 98 | ir.start = (unsigned long)orig; 99 | ir.end = (unsigned long)orig + MAX_HOOK_CODE_BYTES; 100 | 101 | if (within_address(trace.entries[i], &ir)) { 102 | ret = -EBUSY; 103 | goto out; 104 | } 105 | } 106 | } 107 | 108 | } while_each_thread(g, t); 109 | 110 | out: 111 | return ret; 112 | } 113 | 114 | 115 | /* Called from stop_machine */ 116 | static int 117 | inl_sethook_callback(void *data) 118 | { 119 | int i; 120 | int ret; 121 | struct hook_cbdata *cbdata = (struct hook_cbdata *)data; 122 | 123 | ret = inl_sethook_safe_verify(cbdata->ops, cbdata->count); 124 | if (ret != 0) { 125 | return ret; 126 | } 127 | 128 | for (i = 0; i < cbdata->count; i++) { 129 | if (inl_sethook((void **)cbdata->ops[i].orig, cbdata->ops[i].hook) < 0) { 130 | pr_err("sethook_ops hook %s fail.\n", cbdata->ops[i].name); 131 | return -EFAULT; 132 | } 133 | } 134 | 135 | return 0; 136 | } 137 | 138 | 139 | bool inl_sethook_ops(struct hook_ops *ops, int n) 140 | { 141 | int ret; 142 | struct hook_cbdata cbdata = { 143 | .ops = ops, 144 | .count = n, 145 | }; 146 | 147 | try_again_sethook: 148 | 149 | ret = stop_machine(inl_sethook_callback, &cbdata, NULL); 150 | 151 | if (ret == -EBUSY) { 152 | yield(); 153 | pr_info("kernel busy, retry again inl_sethook_ops.\n"); 154 | goto try_again_sethook; 155 | } 156 | 157 | return ret == 0; 158 | } 159 | 160 | 161 | static int 162 | inl_unhook_safe_verify(struct instr_range *ir) 163 | { 164 | unsigned long address; 165 | struct task_struct *g, *t; 166 | int i; 167 | int ret = 0; 168 | struct instr_range self_ir = { 169 | .start = (unsigned long)inl_unhook_safe_verify, 170 | .end = (unsigned long)&&label_unhook_verify_end, 171 | }; 172 | 173 | /* Check the stacks of all tasks. */ 174 | do_each_thread(g, t) { 175 | 176 | trace.nr_entries = 0; 177 | save_stack_trace_tsk(t, &trace); 178 | if (trace.nr_entries >= trace.max_entries) { 179 | ret = -EBUSY; 180 | pr_err("more than %u trace entries!\n", 181 | trace.max_entries); 182 | goto out; 183 | } 184 | 185 | for (i = 0; i < trace.nr_entries; i++) { 186 | if (trace.entries[i] == ULONG_MAX) 187 | break; 188 | 189 | address = trace.entries[i]; 190 | // within cleanup method. 191 | if (within_address(address, ir) 192 | || within_address(address, &self_ir)) { 193 | break; 194 | } 195 | 196 | if (inl_within_trampoline(address) 197 | || within_module_core(address, THIS_MODULE)) { 198 | ret = -EBUSY; 199 | goto out; 200 | } 201 | } 202 | 203 | } while_each_thread(g, t); 204 | 205 | out: 206 | if (ret) { 207 | pr_err("PID: %d Comm: %.20s\n", t->pid, t->comm); 208 | for (i = 0; i < trace.nr_entries; i++) { 209 | if (trace.entries[i] == ULONG_MAX) 210 | break; 211 | pr_err(" [<%pK>] %pB\n", 212 | (void *)trace.entries[i], 213 | (void *)trace.entries[i]); 214 | } 215 | } 216 | 217 | return ret; 218 | 219 | label_unhook_verify_end: ; 220 | } 221 | 222 | 223 | /* Called from stop_machine */ 224 | static int 225 | inl_unhook_callback(void *data) 226 | { 227 | int i; 228 | int ret; 229 | struct hook_cbdata *cbdata = (struct hook_cbdata *)data; 230 | 231 | ret = inl_unhook_safe_verify(&cbdata->ir); 232 | if (ret != 0) { 233 | return ret; 234 | } 235 | 236 | for (i = 0; i < cbdata->count; i++) { 237 | inl_unhook(cbdata->ops[i].hook); 238 | } 239 | 240 | return 0; 241 | } 242 | 243 | 244 | void inl_unhook_ops(struct hook_ops *ops, int n) 245 | { 246 | int ret; 247 | struct hook_cbdata cbdata = { 248 | .ops = ops, 249 | .count = n, 250 | .ir.start = (unsigned long)inl_unhook_ops, 251 | .ir.end = (unsigned long)&&label_unhook_end, 252 | }; 253 | 254 | try_again_unhook: 255 | 256 | ret = stop_machine(inl_unhook_callback, &cbdata, NULL); 257 | 258 | if (ret) { 259 | yield(); 260 | pr_info("module busy, retry again inl_unhook_ops.\n"); 261 | goto try_again_unhook; 262 | } 263 | 264 | label_unhook_end: ; 265 | } 266 | 267 | 268 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H_ 2 | #define _UTIL_H_ 3 | 4 | 5 | #define DECLARE_SYMBOL(addr, str) \ 6 | { (void **)addr, str } 7 | 8 | struct symbol_ops { 9 | void **addr; 10 | char *symbol; 11 | }; 12 | 13 | 14 | #define DECLARE_HOOK(orig, hook) \ 15 | { (void *)orig, (void *)hook, #hook } 16 | 17 | struct hook_ops { 18 | void **orig; 19 | void *hook; 20 | char *name; 21 | }; 22 | 23 | 24 | typedef bool initfn(void); 25 | typedef void cleanupfn(void); 26 | 27 | 28 | bool find_ksymbol(struct symbol_ops *ops, int n); 29 | bool inl_sethook_ops(struct hook_ops *ops, int n); 30 | void inl_unhook_ops(struct hook_ops *ops, int n); 31 | 32 | 33 | #endif 34 | 35 | --------------------------------------------------------------------------------