static int my_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) { bfd_byte buffer[CGEN_MAX_INSN_SIZE]; bfd_byte *buf = buffer; int status; int buflen = (pc & 3) == 0 ? 4 : 2; int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG; bfd_byte *x; /* Read the base part of the insn. */ status = (*info->read_memory_func) (pc - ((!big_p && (pc & 3) != 0) ? 2 : 0), buf, buflen, info); if (status != 0) { (*info->memory_error_func) (status, pc, info); return -1; } /* 32 bit insn? */ x = (big_p ? &buf[0] : &buf[3]); if ((pc & 3) == 0 && (*x & 0x80) != 0) return print_insn (cd, pc, info, buf, buflen); /* Print the first insn. */ if ((pc & 3) == 0) { buf += (big_p ? 0 : 2); if (print_insn (cd, pc, info, buf, 2) == 0) (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); buf += (big_p ? 2 : -2); } x = (big_p ? &buf[0] : &buf[1]); if (*x & 0x80) { /* Parallel. */ (*info->fprintf_func) (info->stream, " || "); *x &= 0x7f; } else (*info->fprintf_func) (info->stream, " -> "); /* The "& 3" is to pass a consistent address. Parallel insns arguably both begin on the word boundary. Also, branch insns are calculated relative to the word boundary. */ if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0) (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); return (pc & 3) ? 2 : 4; }
static int epiphany_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) { bfd_byte buf[CGEN_MAX_INSN_SIZE]; int buflen; int status; info->bytes_per_chunk = 2; /* Attempt to read the base part of the insn. */ info->bytes_per_line = buflen = cd->base_insn_bitsize / 8; status = (*info->read_memory_func) (pc, buf, buflen, info); /* Try again with the minimum part, if min < base. */ if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize)) { info->bytes_per_line = buflen = cd->min_insn_bitsize / 8; status = (*info->read_memory_func) (pc, buf, buflen, info); } if (status != 0) { (*info->memory_error_func) (status, pc, info); return -1; } return print_insn (cd, pc, info, buf, buflen); }
/* Dump insn INSN honoring FLAGS. */ void dump_insn_rtx_1 (rtx insn, int flags) { int all; /* flags == -1 also means dumping all. */ all = (flags & 1);; if (all) flags |= DUMP_INSN_RTX_ALL; sel_print ("("); if (flags & DUMP_INSN_RTX_UID) sel_print ("%d;", INSN_UID (insn)); if (flags & DUMP_INSN_RTX_PATTERN) { char buf[2048]; print_insn (buf, insn, 0); sel_print ("%s;", buf); } if (flags & DUMP_INSN_RTX_BBN) { basic_block bb = BLOCK_FOR_INSN (insn); sel_print ("bb:%d;", bb != NULL ? bb->index : -1); } sel_print (")"); }
/* Function to apply to all instruction that need printing */ int process_insn(x86_inst_t * insn, void * ctx) { trace_interface_t * trace = (trace_interface_t *) ctx; /* Print analysis progress */ if ((insn->insn_ctr % PROGRESS_GAP) == 0) { int percent = (trace_get_curr_filepos(trace) * 101) / trace->trace_byte_size; print_percent(stderr, percent); } /* Print instruction */ print_insn(out_stream, insn, intel_format, verbose, print_counter); return 0; }
/* Emit a slim dump of X (an insn) to the file F, including any register note attached to the instruction. */ void dump_insn_slim (FILE *f, const_rtx x) { char t[BUF_LEN + 32]; rtx note; print_insn (t, x, 1); fputs (t, f); putc ('\n', f); if (INSN_P (x) && REG_NOTES (x)) for (note = REG_NOTES (x); note; note = XEXP (note, 1)) { print_value (t, XEXP (note, 0), 1); fprintf (f, " %s: %s\n", GET_REG_NOTE_NAME (REG_NOTE_KIND (note)), t); } }
static void print_insn_with_notes (pretty_printer *pp, const_rtx x) { pp_string (pp, print_rtx_head); print_insn (pp, x, 1); pp_newline (pp); if (INSN_P (x) && REG_NOTES (x)) for (rtx note = REG_NOTES (x); note; note = XEXP (note, 1)) { pp_printf (pp, "%s %s ", print_rtx_head, GET_REG_NOTE_NAME (REG_NOTE_KIND (note))); if (GET_CODE (note) == INT_LIST) pp_printf (pp, "%d", XINT (note, 0)); else print_pattern (pp, XEXP (note, 0), 1); pp_newline (pp); } }
void visualize_scheduled_insns (int clock) { int i, unit; /* If no more room, split table into two. */ if (n_visual_lines >= MAX_VISUAL_LINES) { print_block_visualization ("(incomplete)"); init_block_visualization (); } n_visual_lines++; sprintf (visual_tbl + strlen (visual_tbl), ";; %-8d", clock); for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++) if (function_units[unit].bitmask & target_units) for (i = 0; i < function_units[unit].multiplicity; i++) { int instance = unit + i * FUNCTION_UNITS_SIZE; rtx insn = get_unit_last_insn (instance); /* Print insns that still keep the unit busy. */ if (insn && actual_hazard_this_instance (unit, instance, insn, clock, 0)) { char str[BUF_LEN]; print_insn (str, insn, 0); str[INSN_LEN] = '\0'; sprintf (visual_tbl + strlen (visual_tbl), " %-33s", str); } else sprintf (visual_tbl + strlen (visual_tbl), " %-33s", "------------------------------"); } /* Print insns that are not assigned to any unit. */ for (i = 0; i < n_vis_no_unit; i++) sprintf (visual_tbl + strlen (visual_tbl), " %-8d", INSN_UID (vis_no_unit[i])); n_vis_no_unit = 0; sprintf (visual_tbl + strlen (visual_tbl), "\n"); }
bool stride_count_seq(const u_char *data, u_int length, double freq[], int pos){ if( counted[pos]){ return true; } u_int i = 0; while( i < length){ int ret = print_insn((bfd_vma)(data + i), &disasm_info); if( ret < 0) return false; int insn_size = (ret>>MOD); int insn_type = (ret & ((1<<MOD) - 1)); if( insn_type == INSTRUCTION_TYPE_PRIV || insn_type == INSTRUCTION_TYPE_INVL){ return false; } if( counted[pos + i]) return true; counted[pos + i] = true; freq[insn_type - 1]++; switch (insn_type) { case INSTRUCTION_TYPE_JMP: //fall through case INSTRUCTION_TYPE_JMPC: case INSTRUCTION_TYPE_LOOP: case INSTRUCTION_TYPE_CALL: case INSTRUCTION_TYPE_ENTER: case INSTRUCTION_TYPE_JECXZ: return true; break; default: break; } i += (u_int) insn_size; } return true; }
void target_disas(FILE *out, target_ulong code, target_ulong size, int flags) { target_ulong pc; int count; struct disassemble_info disasm_info; int (*print_insn)(bfd_vma pc, disassemble_info *info); INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf); disasm_info.read_memory_func = target_read_memory; disasm_info.buffer_vma = code; disasm_info.buffer_length = size; #ifdef TARGET_WORDS_BIGENDIAN disasm_info.endian = BFD_ENDIAN_BIG; #else disasm_info.endian = BFD_ENDIAN_LITTLE; #endif print_insn = print_insn_arm; for (pc = code; size > 0; pc += count, size -= count) { fprintf(out, "0x" TARGET_FMT_lx ": ", pc); count = print_insn(pc, &disasm_info); fprintf(out, "\n"); if (count < 0) break; if (size < count) { fprintf(out, "Disassembler disagrees with translator over instruction " "decoding\n" "Please report this to [email protected]\n"); break; } } }
static void disassemble_to_buffer(TranslationBlock *tb, DisasBuffer *str) { unsigned long pc; struct disassemble_info disasm_info; int (*print_insn)(bfd_vma pc, disassemble_info *info); INIT_DISASSEMBLE_INFO(disasm_info, (FILE *)str, disas_fprintf); disasm_info.buffer = tb->tc_ptr; disasm_info.buffer_vma = (unsigned long)tb->tc_ptr; disasm_info.buffer_length = tb->size; #ifdef HOST_WORDS_BIGENDIAN disasm_info.endian = BFD_ENDIAN_BIG; #else disasm_info.endian = BFD_ENDIAN_LITTLE; #endif #if defined(__i386__) disasm_info.mach = bfd_mach_i386_i386; print_insn = print_insn_i386; #elif defined(__x86_64__) disasm_info.mach = bfd_mach_x86_64; print_insn = print_insn_i386; #elif defined(_ARCH_PPC) print_insn = print_insn_ppc; #elif defined(__alpha__) print_insn = print_insn_alpha; #elif defined(__sparc__) print_insn = print_insn_sparc; #if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__) disasm_info.mach = bfd_mach_sparc_v9b; #endif #elif defined(__arm__) print_insn = print_insn_arm; #elif defined(__MIPSEB__) print_insn = print_insn_big_mips; #elif defined(__MIPSEL__) print_insn = print_insn_little_mips; #elif defined(__m68k__) print_insn = print_insn_m68k; #elif defined(__s390__) print_insn = print_insn_s390; #elif defined(__hppa__) print_insn = print_insn_hppa; #elif defined(__ia64__) print_insn = print_insn_ia64; #else fprintf(out, "0x%lx: Asm output not supported on this arch\n", (long) code); return; #endif int icount = 0; int count = 0; for (pc = (unsigned long)tb->tc_ptr; icount < tb->size && count < DISAS_BUFFER_SIZE; ) { int before = str->size; print_insn(pc, &disasm_info); int after = str->size; if (after == DISAS_BUFFER_SIZE) break; icount += after - before; str->buffer[after++] = '\n'; pc += after - before; count += after - before; } str->buffer[count] = 0; }
static void decode_insn(struct pt_insn_decoder *decoder, const struct ptxed_options *options, struct ptxed_stats *stats) { xed_state_t xed; uint64_t offset, sync, time; if (!options) { printf("[internal error]\n"); return; } xed_state_zero(&xed); offset = 0ull; sync = 0ull; time = 0ull; for (;;) { struct pt_insn insn; int errcode; /* Initialize the IP - we use it for error reporting. */ insn.ip = 0ull; errcode = pt_insn_sync_forward(decoder); if (errcode < 0) { uint64_t new_sync; if (errcode == -pte_eos) break; diagnose_insn("sync error", decoder, &insn, errcode); /* Let's see if we made any progress. If we haven't, * we likely never will. Bail out. * * We intentionally report the error twice to indicate * that we tried to re-sync. Maybe it even changed. */ errcode = pt_insn_get_offset(decoder, &new_sync); if (errcode < 0 || (new_sync <= sync)) break; sync = new_sync; continue; } for (;;) { if (options->print_offset) { errcode = pt_insn_get_offset(decoder, &offset); if (errcode < 0) break; } if (options->print_time) { errcode = pt_insn_time(decoder, &time, NULL, NULL); if (errcode < 0) break; } errcode = pt_insn_next(decoder, &insn, sizeof(insn)); if (errcode < 0) { /* Even in case of errors, we may have succeeded * in decoding the current instruction. */ if (insn.iclass != ptic_error) { if (!options->quiet) print_insn(&insn, &xed, options, offset, time); if (stats) stats->insn += 1; } break; } if (!options->quiet) print_insn(&insn, &xed, options, offset, time); if (stats) stats->insn += 1; if (errcode & pts_eos) { if (!insn.disabled && !options->quiet) printf("[end of trace]\n"); errcode = -pte_eos; break; } } /* We shouldn't break out of the loop without an error. */ if (!errcode) errcode = -pte_internal; /* We're done when we reach the end of the trace stream. */ if (errcode == -pte_eos) break; diagnose_insn("error", decoder, &insn, errcode); } }
/** * We try to decode from all arrays code, we keep track "pos" in the array scan_cache. * @param code array we need to decode. This array has size length * @param pos the position of "code" in array cached * @param length size of code we want to decode. * @return SCANNED_VALID if scan from pos to the end succesfully, otherwise SCANNED_INVALID */ static int racewalk_go(const u_char *code, u_int pos, u_int length) { if ( scan_cache[pos] != NOT_SCANNED) return scan_cache[pos]; if ( length < 1) return SCANNED_VALID; u_int npos = (pos + shift) >= the_sled_length ? (pos + shift - the_sled_length) : (pos + shift); bool jmp = false; if ( decode_cache[npos] != NOT_DECODED) { // We never decode an instruction twice jmp = decode_cache[npos] >= JMP ? 1 : 0; } else { int ret = print_insn((bfd_vma)code, &disasm_info); if ( ret < 0) { decode_cache[npos] = DECODED_INVALID; } else { int insn_size = (ret>>MOD); int insn_type = (ret & ((1<<MOD) - 1)); switch (insn_type) { case INSTRUCTION_TYPE_JMP: //fall through case INSTRUCTION_TYPE_JMPC: case INSTRUCTION_TYPE_LOOP: case INSTRUCTION_TYPE_CALL: case INSTRUCTION_TYPE_ENTER: case INSTRUCTION_TYPE_JECXZ: jmp = true; break; default: jmp = false; break; } switch (insn_type) { case INSTRUCTION_TYPE_INVL: //fall through case INSTRUCTION_TYPE_PRIV: decode_cache[npos] = DECODED_INVALID; break; default: decode_cache[npos] = insn_size + JMP * (int)(jmp ? 1 : 0); break; } } } if ( decode_cache[npos] == DECODED_INVALID) { return scan_cache[pos] = SCANNED_INVALID; } else { if ( jmp) { return scan_cache[pos] = SCANNED_VALID; } u_int res = (u_int) decode_cache[npos]; if ( res < length) { int cur = racewalk_go(code + res, pos + res, length - res); if ( cur == SCANNED_INVALID) { seq = seq & ~(1<<(pos & 0x3)); } return scan_cache[pos] = cur; } else { return scan_cache[pos] = SCANNED_VALID; } } }