ADDRINT GetInstructionLength (ADDRINT ip) { xed_state_t dstate; xed_error_enum_t xed_error; xed_decoded_inst_t xedd; ostringstream os; if (sizeof(ADDRINT) == 4) xed_state_init(&dstate, XED_MACHINE_MODE_LEGACY_32, XED_ADDRESS_WIDTH_32b, XED_ADDRESS_WIDTH_32b); else xed_state_init(&dstate, XED_MACHINE_MODE_LONG_64, XED_ADDRESS_WIDTH_64b, XED_ADDRESS_WIDTH_64b); xed_decoded_inst_zero_set_mode(&xedd, &dstate); UINT32 len = 15; xed_error = xed_decode(&xedd, reinterpret_cast<const UINT8*>(ip), len); if (xed_error != XED_ERROR_NONE) { printf ("Failure to decode at %p\n", (char *)ip); exit (1); } return xed_decoded_inst_get_length(&xedd); }
static XED_INLINE xed_error_enum_t decode_internal(xed_decoded_inst_t* xedd, const xed_uint8_t* itext, xed_uint_t max_bytes) { xed_error_enum_t err = xed_decode(xedd, itext, max_bytes); return err; }
xed_uint_t disas_decode_binary(const xed_state_t* dstate, const xed_uint8_t* hex_decode_text, const unsigned int bytes, xed_decoded_inst_t* xedd, xed_uint64_t runtime_address) { xed_uint64_t t1,t2; xed_error_enum_t xed_error; xed_bool_t okay; if (CLIENT_VERBOSE) { print_hex_line(hex_decode_text, bytes); } t1 = xed_get_time(); xed_error = xed_decode(xedd, hex_decode_text, bytes); t2 = xed_get_time(); okay = (xed_error == XED_ERROR_NONE); if (CLIENT_VERBOSE3) { xed_uint64_t delta = t2-t1; printf("Decode time = " XED_FMT_LU "\n", delta); } if (okay) { if (CLIENT_VERBOSE1) { char tbuf[XED_TMP_BUF_LEN]; xed_decoded_inst_dump(xedd,tbuf,XED_TMP_BUF_LEN); printf("%s\n",tbuf); } if (CLIENT_VERBOSE) { char buf[XED_TMP_BUF_LEN]; if (xed_decoded_inst_valid(xedd)) { printf( "ICLASS: %s CATEGORY: %s EXTENSION: %s IFORM: %s" " ISA_SET: %s\n", xed_iclass_enum_t2str(xed_decoded_inst_get_iclass(xedd)), xed_category_enum_t2str(xed_decoded_inst_get_category(xedd)), xed_extension_enum_t2str(xed_decoded_inst_get_extension(xedd)), xed_iform_enum_t2str(xed_decoded_inst_get_iform_enum(xedd)), xed_isa_set_enum_t2str(xed_decoded_inst_get_isa_set(xedd))); } memset(buf,0,XED_TMP_BUF_LEN); disassemble(buf,XED_TMP_BUF_LEN, xedd, runtime_address,0); printf("SHORT: %s\n", buf); } return 1; } else { xed_decode_error(0, 0, hex_decode_text, xed_error); return 0; } (void) dstate; // pacify compiler }
xed_iclass_enum_t xed_iclass(char* ins) { xed_decoded_inst_t xedd; xed_decoded_inst_t *xptr = &xedd; xed_decoded_inst_zero_set_mode(xptr, &dbg_xed_machine_state); xed_error_enum_t xed_error = xed_decode(xptr, (uint8_t*) ins, 15); if (xed_error != XED_ERROR_NONE) { fprintf(stderr, "!! XED decode failure of insruction @ %p", ins); return XED_ICLASS_INVALID; } return xed_decoded_inst_get_iclass(xptr); }
bool VariableRecovery(BYTE *startAddr, BYTE *endAddr, std::map<int, AbstractVariable*> &container) { const unsigned int maxInstructionLength = 15; // the max length of a x86 instruction is 15byte xed_decoded_inst_t xedd; int instLength, index; BYTE *currentAddr = startAddr; char buffer[1024]; VariableHunter *varHunter = new VariableHunter(); // initialize the variable hunter static const xed_state_t dstate = { XED_MACHINE_MODE_LEGACY_32, XED_ADDRESS_WIDTH_32b }; //currently, we only implement the 32bit machine index = 0; while(currentAddr < endAddr) // only small than, can't be equal. { memset(buffer, 0, sizeof(buffer)); xed_decoded_inst_zero_set_mode(&xedd, &dstate); xed_error_enum_t xedCode = xed_decode(&xedd, (uint8_t*)currentAddr, maxInstructionLength); if(xedCode == XED_ERROR_NONE) { instLength = xed_decoded_inst_get_length(&xedd); //get the length of the instruction in byte xed_uint64_t runtime_address = (xed_uint64_t)currentAddr; xed_decoded_inst_dump_intel_format(&xedd, buffer, 1024, runtime_address); printf("0x%x\t\t%s\n", index, buffer); varHunter -> findVariable(xedd); currentAddr += instLength; index += instLength; } else return false; } varHunter -> getResult(container); delete varHunter; return true; }
void print_trace_record(trace_record_t *rec) { xed_decoded_inst_t xDecode; char asm_buf[32]; int i; if(rec->is_new) { printf("NEW eip=%08x esp=%08x caller=%08x callee=%08x M[%08x]=%08x \n", rec->eip, rec->esp, rec->caller, rec->callee, rec->mem_addr, rec->mem_val); printf(" id=%08x", rec->define.dst_id[0]); for(i=1; rec->define.dst_id[i] && i<4; i++) printf(", %08x", rec->define.dst_id[i]); printf("\n"); } else { printf("OLD eip=%08x esp=%08x caller=%08x callee=%08x is_move=%d\n", rec->eip, rec->esp, rec->caller, rec->callee, rec->prop.is_move); if(rec->mem_addr) printf(" M[%08x]=%08x\n", rec->mem_addr, rec->mem_val); printf(" src_id=%08x", rec->prop.src_id[0]); for(i=1; rec->prop.src_id[i] !=0 && i<12; i++) printf(", %08x", rec->prop.src_id[i]); printf("\n"); printf(" dst_id=%08x", rec->prop.dst_id[0]); for(i=1; rec->prop.dst_id[i] !=0 && i<4; i++) printf(", %08x", rec->prop.dst_id[i]); printf("\n"); } if(rec->address_id) printf(" address_id=%08x\n", rec->address_id); /* printf(" raw_insn: "); for(i=0; i<16; i++) printf("%02x ", (uint8_t)rec->raw_insn[i]); */ xed_decoded_inst_zero_set_mode(&xDecode, &g_xState); xed_error_enum_t xed_error = xed_decode(&xDecode, rec->raw_insn, 16); if(xed_error == XED_ERROR_NONE) { xed_format_intel(&xDecode, asm_buf, sizeof(asm_buf), rec->eip); printf("%s\n", asm_buf); } }
VOID use_xed(ADDRINT pc) { #if defined(TARGET_IA32E) static const xed_state_t dstate = {XED_MACHINE_MODE_LONG_64, XED_ADDRESS_WIDTH_64b}; #else static const xed_state_t dstate = { XED_MACHINE_MODE_LEGACY_32, XED_ADDRESS_WIDTH_32b}; #endif xed_decoded_inst_t xedd; xed_decoded_inst_zero_set_mode(&xedd,&dstate); UINT64 ticks_start, ticks_stop, delta; //FIXME: pass in the proper length... const unsigned int max_inst_len = 15; ticks_start = get_time(); #define USE_DECODE_CACHE #if defined(USE_DECODE_CACHE) xed_error_enum_t xed_code = xed_decode_cache(&xedd, reinterpret_cast<UINT8*>(pc), max_inst_len, &cache); #else xed_error_enum_t xed_code = xed_decode(&xedd, reinterpret_cast<UINT8*>(pc), max_inst_len); #endif ticks_stop = get_time(); delta = ticks_stop - ticks_start; //cerr << ticks_start << " " << ticks_stop << " " << delta << endl; UINT64 bin = delta/50; if ((INT64)delta < 0) rejects++; else if (bin >= MAX_BINS) histo[MAX_BINS-1] += 1; else histo[bin] += 1; BOOL xed_ok = (xed_code == XED_ERROR_NONE); i++; if (i>(1024*1024) && xed_ok) { i=0; j++; *out << j*1024*1024 << endl; Fini(0,0); *out << hex << std::setw(8) << pc << " " << dec; char buf[2048]; xed_decoded_inst_dump_intel_format(&xedd, buf, 2048, 0); *out << buf << endl; } }
void x86_dump_ins(void *ins) { xed_decoded_inst_t xedd; xed_decoded_inst_t *xptr = &xedd; xed_error_enum_t xed_error; char inst_buf[1024]; char errbuf[2048]; xed_decoded_inst_zero_set_mode(xptr, &x86_decoder_settings.xed_settings); xed_error = xed_decode(xptr, (uint8_t*) ins, 15); if (xed_error == XED_ERROR_NONE) { xed_format_xed(xptr, inst_buf, sizeof(inst_buf), (xed_uint64_t)(uintptr_t)ins); sprintf(errbuf, "(%p, %d bytes, %s) %s \n" , ins, xed_decoded_inst_get_length(xptr), xed_iclass_enum_t2str(iclass(xptr)), inst_buf); } else { #if defined(ENABLE_XOP) && defined (HOST_CPU_x86_64) amd_decode_t decode_res; adv_amd_decode(&decode_res, ins); if (decode_res.success) { if (decode_res.weak) sprintf(errbuf, "(%p, %d bytes) weak AMD XOP \n", ins, (int) decode_res.len); else sprintf(errbuf, "(%p, %d bytes) robust AMD XOP \n", ins, (int) decode_res.len); } else #endif // ENABLE_XOP and HOST_CPU_x86_64 sprintf(errbuf, "x86_dump_ins: xed decode error addr=%p, code = %d\n", ins, (int) xed_error); } EMSG(errbuf); fprintf(stderr, errbuf); fflush(stderr); }
void Disasm::disasm(std::ostream& out, uint8_t* codeStartAddr, uint8_t* codeEndAddr) { #ifdef HAVE_LIBXED auto const endClr = m_opts.m_color.empty() ? "" : ANSI_COLOR_END; char codeStr[MAX_INSTR_ASM_LEN]; xed_uint8_t *frontier; xed_decoded_inst_t xedd; uint64_t codeBase = uint64_t(codeStartAddr); uint64_t ip; // Decode and print each instruction for (frontier = codeStartAddr, ip = (uint64_t)codeStartAddr; frontier < codeEndAddr; ) { xed_decoded_inst_zero_set_mode(&xedd, &m_xedState); xed_decoded_inst_set_input_chip(&xedd, XED_CHIP_INVALID); xed_error_enum_t xed_error = xed_decode(&xedd, frontier, 15); if (xed_error != XED_ERROR_NONE) error("disasm error: xed_decode failed"); // Get disassembled instruction in codeStr auto const syntax = m_opts.m_forceAttSyntax ? XED_SYNTAX_ATT : s_xed_syntax; if (!xed_format_context(syntax, &xedd, codeStr, MAX_INSTR_ASM_LEN, ip, nullptr)) { error("disasm error: xed_format_context failed"); } uint32_t instrLen = xed_decoded_inst_get_length(&xedd); // If it's a jump, we're printing relative offsets, and the dest // is within the range we're printing, add the dest as a relative // offset. std::string jmpComment; auto const cat = xed_decoded_inst_get_category(&xedd); if (cat == XED_CATEGORY_COND_BR || cat == XED_CATEGORY_UNCOND_BR) { if (m_opts.m_relativeOffset) { auto disp = uint64_t(frontier + instrLen + xed_decoded_inst_get_branch_displacement(&xedd) - codeBase); if (disp < uint64_t(codeEndAddr - codeStartAddr)) { jmpComment = folly::format(" # {:#x}", disp).str(); } } } for (int i = 0; i < m_opts.m_indentLevel; ++i) { out << ' '; } out << m_opts.m_color; if (m_opts.m_addresses) { const char* fmt = m_opts.m_relativeOffset ? "{:3x}: " : "{:#10x}: "; out << folly::format(fmt, ip - (m_opts.m_relativeOffset ? codeBase : 0)); } if (m_opts.m_printEncoding) { // print encoding, like in objdump unsigned posi = 0; for (; posi < instrLen; ++posi) { out << folly::format("{:02x} ", (uint8_t)frontier[posi]); } for (; posi < 16; ++posi) { out << " "; } } out << codeStr << jmpComment << endClr << '\n'; frontier += instrLen; ip += instrLen; } #else out << "This binary was compiled without disassembly support\n"; #endif // HAVE_LIBXED }
static string disassemble(UINT64 start, UINT64 stop) { UINT64 pc = start; xed_state_t dstate; xed_syntax_enum_t syntax = XED_SYNTAX_INTEL; xed_error_enum_t xed_error; xed_decoded_inst_t xedd; ostringstream os; if (sizeof(ADDRINT) == 4) xed_state_init(&dstate, XED_MACHINE_MODE_LEGACY_32, XED_ADDRESS_WIDTH_32b, XED_ADDRESS_WIDTH_32b); else xed_state_init(&dstate, XED_MACHINE_MODE_LONG_64, XED_ADDRESS_WIDTH_64b, XED_ADDRESS_WIDTH_64b); /*while( pc < stop )*/ { xed_decoded_inst_zero_set_mode(&xedd, &dstate); UINT32 len = 15; if (stop - pc < 15) len = stop-pc; xed_error = xed_decode(&xedd, reinterpret_cast<const UINT8*>(pc), len); bool okay = (xed_error == XED_ERROR_NONE); iostream::fmtflags fmt = os.flags(); os << std::setfill('0') << "XDIS " << std::hex << std::setw(sizeof(ADDRINT)*2) << pc << std::dec << ": " << std::setfill(' ') << std::setw(4); if (okay) { char buffer[200]; unsigned int dec_len, sp; os << xed_extension_enum_t2str(xed_decoded_inst_get_extension(&xedd)); dec_len = xed_decoded_inst_get_length(&xedd); print_hex_line(buffer, reinterpret_cast<UINT8*>(pc), dec_len); os << " " << buffer; for ( sp=dec_len; sp < 12; sp++) // pad out the instruction bytes os << " "; os << " "; memset(buffer,0,200); int dis_okay = xed_format(syntax, &xedd, buffer, 200, pc); if (dis_okay) os << buffer << endl; else os << "Error disasassembling pc 0x" << std::hex << pc << std::dec << endl; pc += dec_len; } else { // print the byte and keep going. UINT8 memval = *reinterpret_cast<UINT8*>(pc); os << "???? " // no extension << std::hex << std::setw(2) << std::setfill('0') << static_cast<UINT32>(memval) << std::endl; pc += 1; } os.flags(fmt); } return os.str(); }
static void print_block(struct pt_block *block, struct pt_image_section_cache *iscache, const struct ptxed_options *options, const struct ptxed_stats *stats, uint64_t offset, uint64_t time) { xed_machine_mode_enum_t mode; xed_state_t xed; uint64_t last_ip; if (!block || !options) { printf("[internal error]\n"); return; } if (block->resynced) printf("[overflow]\n"); if (block->enabled) printf("[enabled]\n"); if (block->resumed) printf("[resumed]\n"); if (options->track_blocks) { printf("[block"); if (stats) printf(" %" PRIx64, stats->blocks); printf("]\n"); } mode = translate_mode(block->mode); xed_state_init2(&xed, mode, XED_ADDRESS_WIDTH_INVALID); last_ip = 0ull; for (; block->ninsn; --block->ninsn) { xed_decoded_inst_t inst; xed_error_enum_t xederrcode; uint8_t raw[pt_max_insn_size], *praw; int size, errcode; /* For truncated block, the last instruction is provided in the * block since it can't be read entirely from the image section * cache. */ if (block->truncated && (block->ninsn == 1)) { praw = block->raw; size = block->size; } else { praw = raw; size = pt_iscache_read(iscache, raw, sizeof(raw), block->isid, block->ip); if (size < 0) { printf(" [error reading insn: (%d) %s]\n", size, pt_errstr(pt_errcode(size))); break; } } xed_decoded_inst_zero_set_mode(&inst, &xed); if (block->speculative) printf("? "); if (options->print_offset) printf("%016" PRIx64 " ", offset); if (options->print_time) printf("%016" PRIx64 " ", time); printf("%016" PRIx64, block->ip); xederrcode = xed_decode(&inst, praw, size); if (xederrcode != XED_ERROR_NONE) { printf(" [xed decode error: (%u) %s]\n", xederrcode, xed_error_enum_t2str(xederrcode)); break; } if (!options->dont_print_insn) xed_print_insn(&inst, block->ip, options); printf("\n"); last_ip = block->ip; errcode = xed_next_ip(&block->ip, &inst, last_ip); if (errcode < 0) { diagnose_block_at("reconstruct error", offset, block, errcode); break; } } /* Decode should have brought us to @block->end_ip. */ if (last_ip != block->end_ip) diagnose_block_at("reconstruct error", offset, block, -pte_nosync); if (block->interrupted) printf("[interrupt]\n"); if (block->aborted) printf("[aborted]\n"); if (block->committed) printf("[committed]\n"); if (block->disabled) printf("[disabled]\n"); if (block->stopped) printf("[stopped]\n"); }
static void print_insn(const struct pt_insn *insn, xed_state_t *xed, const struct ptxed_options *options, uint64_t offset, uint64_t time) { if (!insn || !options) { printf("[internal error]\n"); return; } if (insn->resynced) printf("[overflow]\n"); if (insn->enabled) printf("[enabled]\n"); if (insn->resumed) printf("[resumed]\n"); if (insn->speculative) printf("? "); if (options->print_offset) printf("%016" PRIx64 " ", offset); if (options->print_time) printf("%016" PRIx64 " ", time); printf("%016" PRIx64, insn->ip); if (!options->dont_print_insn) { xed_machine_mode_enum_t mode; xed_decoded_inst_t inst; xed_error_enum_t errcode; mode = translate_mode(insn->mode); xed_state_set_machine_mode(xed, mode); xed_decoded_inst_zero_set_mode(&inst, xed); errcode = xed_decode(&inst, insn->raw, insn->size); switch (errcode) { case XED_ERROR_NONE: xed_print_insn(&inst, insn->ip, options); break; default: printf(" [xed decode error: (%u) %s]", errcode, xed_error_enum_t2str(errcode)); break; } } printf("\n"); if (insn->interrupted) printf("[interrupt]\n"); if (insn->aborted) printf("[aborted]\n"); if (insn->committed) printf("[committed]\n"); if (insn->disabled) printf("[disabled]\n"); if (insn->stopped) printf("[stopped]\n"); }
void OfflineX86Code::disasm(FILE* file, TCA fileStartAddr, TCA codeStartAddr, uint64_t codeLen, const PerfEventsMap<TCA>& perfEvents, BCMappingInfo bcMappingInfo, bool printAddr /* =true */, bool printBinary /* =false */) { char codeStr[MAX_INSTR_ASM_LEN]; xed_uint8_t* code = (xed_uint8_t*) alloca(codeLen); xed_uint8_t* frontier; TCA ip; TCA r10val = 0; size_t currBC = 0; if (codeLen == 0) return; auto const offset = codeStartAddr - fileStartAddr; if (fseek(file, offset, SEEK_SET)) { error("disasm error: seeking file"); } size_t readLen = fread(code, codeLen, 1, file); if (readLen != 1) { error("Failed to read {} bytes at offset {} from code file due to {}", codeLen, offset, feof(file) ? "EOF" : "read error"); } xed_decoded_inst_t xedd; // Decode and print each instruction for (frontier = code, ip = codeStartAddr; frontier < code + codeLen; ) { xed_decoded_inst_zero_set_mode(&xedd, &xed_state); xed_decoded_inst_set_input_chip(&xedd, XED_CHIP_INVALID); xed_error_enum_t xed_error = xed_decode(&xedd, frontier, 15); if (xed_error != XED_ERROR_NONE) break; // Get disassembled instruction in codeStr if (!xed_format_context(xed_syntax, &xedd, codeStr, MAX_INSTR_ASM_LEN, (uint64_t)ip, nullptr #if XED_ENCODE_ORDER_MAX_ENTRIES != 28 // Newer version of XED library , 0 #endif )) { error("disasm error: xed_format_context failed"); } // Annotate the x86 with its bytecode. currBC = printBCMapping(bcMappingInfo, currBC, (TCA)ip); if (printAddr) printf("%14p: ", ip); uint32_t instrLen = xed_decoded_inst_get_length(&xedd); if (printBinary) { uint32_t i; for (i=0; i < instrLen; i++) { printf("%02X", frontier[i]); } for (; i < 16; i++) { printf(" "); } } // For calls, we try to figure out the destination symbol name. // We look both at relative branches and the pattern: // move r10, IMMEDIATE // call r10 xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xedd); string callDest = ""; if (iclass == XED_ICLASS_CALL_NEAR || iclass == XED_ICLASS_CALL_FAR) { const xed_inst_t *xi = xed_decoded_inst_inst(&xedd); always_assert(xed_inst_noperands(xi) >= 1); const xed_operand_t *opnd = xed_inst_operand(xi, 0); xed_operand_enum_t opndName = xed_operand_name(opnd); if (opndName == XED_OPERAND_RELBR) { if (xed_decoded_inst_get_branch_displacement_width(&xedd)) { xed_int32_t disp = xed_decoded_inst_get_branch_displacement(&xedd); TCA addr = ip + instrLen + disp; callDest = getSymbolName(addr); } } else if (opndName == XED_OPERAND_REG0) { if (xed_decoded_inst_get_reg(&xedd, opndName) == XED_REG_R10) { callDest = getSymbolName(r10val); } } } else if (iclass == XED_ICLASS_MOV) { // Look for moves into r10 and keep r10val updated const xed_inst_t* xi = xed_decoded_inst_inst(&xedd); always_assert(xed_inst_noperands(xi) >= 2); const xed_operand_t *destOpnd = xed_inst_operand(xi, 0); xed_operand_enum_t destOpndName = xed_operand_name(destOpnd); if (destOpndName == XED_OPERAND_REG0 && xed_decoded_inst_get_reg(&xedd, destOpndName) == XED_REG_R10) { const xed_operand_t *srcOpnd = xed_inst_operand(xi, 1); xed_operand_enum_t srcOpndName = xed_operand_name(srcOpnd); if (srcOpndName == XED_OPERAND_IMM0) { TCA addr = (TCA)xed_decoded_inst_get_unsigned_immediate(&xedd); r10val = addr; } } } if (!perfEvents.empty()) { printEventStats((TCA)ip, instrLen, perfEvents); } else { printf("%48s", ""); } printf("%s%s\n", codeStr, callDest.c_str()); frontier += instrLen; ip += instrLen; } }
TCA OfflineX86Code::collectJmpTargets(FILE *file, TCA fileStartAddr, TCA codeStartAddr, uint64_t codeLen, vector<TCA> *jmpTargets) { xed_uint8_t* code = (xed_uint8_t*) alloca(codeLen); xed_uint8_t* frontier; TCA ip; if (codeLen == 0) return 0; if (fseek(file, codeStartAddr - fileStartAddr, SEEK_SET)) { error("collectJmpTargets error: seeking file"); } size_t readLen = fread(code, codeLen, 1, file); if (readLen != 1) error("collectJmpTargets error: reading file"); xed_decoded_inst_t xedd; xed_iclass_enum_t iclass = XED_ICLASS_NOP; // Decode each instruction for (frontier = code, ip = codeStartAddr; frontier < code + codeLen; ) { xed_decoded_inst_zero_set_mode(&xedd, &xed_state); xed_decoded_inst_set_input_chip(&xedd, XED_CHIP_INVALID); xed_error_enum_t xed_error = xed_decode(&xedd, frontier, 15); if (xed_error != XED_ERROR_NONE) break; uint32_t instrLen = xed_decoded_inst_get_length(&xedd); iclass = xed_decoded_inst_get_iclass(&xedd); if (iclass >= XED_ICLASS_JB && iclass <= XED_ICLASS_JZ) { const xed_inst_t *xi = xed_decoded_inst_inst(&xedd); always_assert(xed_inst_noperands(xi) >= 1); const xed_operand_t *opnd = xed_inst_operand(xi, 0); xed_operand_enum_t opndName = xed_operand_name(opnd); if (opndName == XED_OPERAND_RELBR) { always_assert(xed_decoded_inst_get_branch_displacement_width(&xedd)); xed_int32_t disp = xed_decoded_inst_get_branch_displacement(&xedd); TCA addr = ip + instrLen + disp; jmpTargets->push_back(addr); } } frontier += instrLen; ip += instrLen; } // If the code sequence falls thru, then add the next instruction as a // possible target bool fallsThru = (iclass != XED_ICLASS_JMP && iclass != XED_ICLASS_JMP_FAR && iclass != XED_ICLASS_RET_NEAR && iclass != XED_ICLASS_RET_FAR); if (fallsThru) { jmpTargets->push_back(ip); return ip; } return 0; }