/** * Get function addr list from call search basic * @param file target file * @param addr address list */ int elfsh_addr_get_func_list(elfshobj_t *file, eresi_Addr **addr) { int ret; int index; asm_instr instr; elfsh_SAddr foffset; elfsh_Word len; char *base; asm_processor proc; eresi_Addr base_vaddr, caddr; u_char found = 0; elfshsect_t *text; eresi_Addr *vaddr; const int astep = 20; u_int apos = 0; btree_t *broot = NULL; u_int diff; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (!file || !addr) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid parameters", -1); /* Search entrypoint section, our address must be in this section */ text = elfsh_get_parent_section(file, elfsh_get_entrypoint(file->hdr), &foffset); if (!text) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot find parent section from entry point", -1); if (!elfsh_get_anonymous_section(file, text)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to get an anonymous section", -1); base = elfsh_readmem(text); len = text->shdr->sh_size; /* Get the virtual address */ base_vaddr = (elfsh_is_runtime_mode() && !elfsh_section_is_runtime(text) ? file->rhdr.base + elfsh_get_section_addr(text->shdr) : elfsh_get_section_addr(text->shdr)); /* Setup asm_processor structure */ if (etrace_setup_proc(file, &proc) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed during proc structure setup", -1); XALLOC(__FILE__, __FUNCTION__, __LINE__, vaddr, sizeof(eresi_Addr)*astep, -1); /* Despite the fact that we choose the right architecture to init asm, Our approach is totally architecture independant as we search using global type ASM_TYPE_CALLPROC and we know that op[0].imm will contain a relative value. */ for (index = 0; index < len; index += ret) { /* Read an instruction */ if ((ret = asm_read_instr(&instr, (u_char *) (base + index), len - index, &proc))) { /* Global assembler filter */ if ((instr.type & ASM_TYPE_CALLPROC) && instr.op[0].imm != 0) { caddr = base_vaddr + index + instr.op[0].imm + instr.len; /* Found a call check its local */ if (INTERVAL(base_vaddr, caddr, base_vaddr + len)) { found = 1; diff = (u_int) caddr; /* Avoid double entrie */ if (btree_get_elem(broot, diff) != NULL) goto next; btree_insert(&broot, diff, (void *)0x1); /* Next will be the last of the current list then realloc */ if ((apos+1) % astep == 0) { XREALLOC(__FILE__, __FUNCTION__, __LINE__, vaddr, vaddr, sizeof(eresi_Addr)*(apos+1+astep), -1); /* Blank new elements */ memset(&vaddr[apos], 0x00, astep*sizeof(eresi_Addr)); } vaddr[apos++] = caddr; } } } next: if (ret <= 0) ret = 1; } /* If nothing found we free allocated buffer and return an error */ if (!found) { XFREE(__FILE__, __FUNCTION__, __LINE__, vaddr); PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "No call internal found", -3); } btree_free(broot, 0); *addr = vaddr; PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Search a call for a given address * @param file target file * @param addr supose to be a function */ int elfsh_addr_is_called(elfshobj_t *file, eresi_Addr addr) { int ret; int index; asm_instr instr; elfsh_SAddr foffset; elfsh_Word len; char *base; asm_processor proc; eresi_Addr base_vaddr; u_char found = 0; elfshsect_t *text; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (!file) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid parameter", -1); /* Search entrypoint section, our address must be in this section */ text = elfsh_get_parent_section(file, elfsh_get_entrypoint(file->hdr), &foffset); if (!text) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot find parent section from entry point", -1); if (!elfsh_get_anonymous_section(file, text)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to get an anonymous section", -1); base = elfsh_readmem(text); len = text->shdr->sh_size; /* Get the virtual address */ base_vaddr = (elfsh_is_runtime_mode() && !elfsh_section_is_runtime(text) ? file->rhdr.base + elfsh_get_section_addr(text->shdr) : elfsh_get_section_addr(text->shdr)); /* Our address is valid ? */ if (!INTERVAL(base_vaddr, addr, (base_vaddr + len))) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Not in entrypoint section", -4); /* Setup asm_processor structure */ if (etrace_setup_proc(file, &proc) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed during proc structure setup", -1); /* Despite the fact that we choose the right architecture to init asm, Our approach is totally architecture independant as we search using global type ASM_TYPE_CALLPROC and we know that op[0].imm will contain a relative value. */ for (index = 0; index < len; index += ret) { /* Read an instruction */ if ((ret = asm_read_instr(&instr, (u_char *) (base + index), len - index, &proc))) { /* Global assembler filter */ if ((instr.type & ASM_TYPE_CALLPROC) && instr.op[0].imm != 0) { /* Found the correct call */ if (base_vaddr + index + instr.op[0].imm + instr.len == addr) { found = 1; break; } } } if (ret <= 0) ret = 1; } if (!found) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "No call found", -3); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Reflect command disassemble the block cache of the parameter and create a list of instr exprs */ int cmd_reflect() { container_t *container; container_t *instrcontainer; mjrblock_t *curblock; asm_instr cur; elfsh_Half machine; char logbuf[BUFSIZ]; char logbuf2[BUFSIZ]; eresi_Addr addr; eresi_Addr daddr; u_int off; int ret; aspectype_t *curtype; void *blocdata; int fileoff; list_t *instrlist; revmexpr_t *expr; u_int insnbr; u_int reqnbr; u_int readsize; revmexpr_t *immed; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); curtype = aspect_type_get_by_name("instr"); if (!curtype) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed reflection : unknown type : instr", -1); /* Validate parameters */ if (world.curjob->curcmd->argc != 1 && world.curjob->curcmd->argc != 2) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Command expect one or two parameters \n", -1); /* Init proc */ if (!world.curjob->proc) { switch (machine = elfsh_get_arch(world.curjob->curfile->hdr)) { case EM_386: world.curjob->proc = &world.proc_ia32; break; case EM_SPARC: case EM_SPARC32PLUS: case EM_SPARCV9: world.curjob->proc = &world.proc_sparc; break; case EM_ARM: world.curjob->proc = &world.proc_arm; break; case EM_MIPS: case EM_MIPS_RS3_LE: world.curjob->proc = &world.proc_mips; break; default: snprintf(logbuf, sizeof (logbuf), "Architecture %s not supported. No disassembly available\n", elfsh_get_machine_string(machine)); revm_output(logbuf); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); } } /* Now lookup the block by its addr or symbol */ immed = revm_lookup_param(world.curjob->curcmd->param[0], 1); if (!immed) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to lookup parameter address expr", -1); if (revm_convert_object(immed, ASPECT_TYPE_CADDR) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid address parameter", 0); addr = (immed->value->immed ? immed->value->immed_val.ent : immed->value->get_obj(immed->value->parent)); /* Analyse the binary if not already done */ /* if (!world.mjr_session.cur->analysed) { maxdepth = (int) config_get_data(CONFIG_CFGDEPTH); ret = mjr_analyse(&world.mjr_session, world.curjob->curfile->hdr->e_entry, maxdepth, 0); if (ret < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed analyzing current object", -1); } */ /* One more param enables lightweight mode: lookup data from a binary file section - no CFG needed */ if (world.curjob->curcmd->argc == 2) { immed = revm_lookup_param(world.curjob->curcmd->param[1], 1); if (revm_convert_object(immed, ASPECT_TYPE_INT) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid size parameter", 0); reqnbr = (immed->value->immed ? (u_int) immed->value->immed_val.ent : (u_int) immed->value->get_obj(immed->value->parent)); if (reqnbr <= 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid instruction number to reflect", -1); readsize = 16 * reqnbr; blocdata = alloca(readsize); } /* Only one param (an addr/symbol) --> Lookup data from a basic block on the CFG */ else { container = mjr_block_get_by_vaddr(world.mjr_session.cur, addr, MJR_BLOCK_GET_STRICT); if (!container) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to find bloc at this virtual address", -1); curblock = (mjrblock_t *) container->data; readsize = curblock->size; blocdata = alloca(readsize); reqnbr = 0; } /* Read data -- could be imported from a remote process, so needs to copy buffer */ fileoff = elfsh_get_foffset_from_vaddr(world.curjob->curfile, addr); if (elfsh_readmemf(world.curjob->curfile, fileoff, blocdata, readsize) != readsize) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to read data to reflect", -1); /* Create the new list of instructions in expression form */ XALLOC(__FILE__, __FUNCTION__, __LINE__, instrlist, sizeof(list_t), -1); snprintf(logbuf2, sizeof(logbuf2), AFMT, addr); elist_init(instrlist, strdup(logbuf2), ASPECT_TYPE_EXPR); /* Reflection all instructions of the basic bloc in the list */ for (insnbr = off = 0; off < readsize; off += ret, insnbr++) { /* If reached the number of requested instruction, stop now even without reaching buffer end */ if (reqnbr && insnbr == reqnbr) break; /* Fetch the current instruction */ ret = asm_read_instr(&cur, (u_char *) blocdata + off, readsize - off + 10, world.curjob->proc); if (ret < 0) { elist_destroy(instrlist); PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to fetch code for basic bloc", -1); } /* Also add the instruction to the current reflected list for this block */ instrcontainer = container_create(curtype->type, (void *) &cur, NULL, NULL, 0); snprintf(logbuf, sizeof (logbuf), "$instr-"XFMT, addr + off); daddr = (eresi_Addr) instrcontainer; expr = revm_inform_type_addr(curtype->name, strdup(logbuf), daddr, NULL, 0, 1); elist_add(instrlist, strdup(logbuf), expr); } /* Reverse instrlist and add it to the hash of lists */ instrlist = elist_reverse(instrlist); hash_add(&instrlists_hash, strdup(logbuf2), instrlist); /* Printing message if we are not in quiet mode */ if (!world.state.revm_quiet) { snprintf(logbuf, sizeof(logbuf), " [*] Code at address " AFMT " reflected succesfully (%u instrs) \n\n", addr, insnbr); revm_output(logbuf); } /* Put the current bloc in the last result variable */ /* revm_expr_destroy_by_name(REVM_VAR_RESULT); revm_expr_copy(expr, REVM_VAR_RESULT); */ PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * @brief Search main function from binary entry point. * * This function inspect the code at entry point and inject the resolved * symbol for the main function. This is a separate function so that it * can be called from the tracer and benefit from the main symbol presence */ eresi_Addr mjr_find_main(elfshobj_t *obj, asm_processor *proc, u_char *buf, u_int len, eresi_Addr vaddr, u_int *dis) { int stop; elfsh_Sym *sym; u_int ilen,done; eresi_Addr init_addr; asm_instr ins; int arch_bin; int fetch_next = 0; eresi_Addr main_addr; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); done = 0; for (*dis = stop = 0; !stop; *dis += ilen) { ilen = asm_read_instr(&ins, (u_char *) buf + *dis, len - *dis, proc); if (!*dis) { if (proc->type == ASM_PROC_IA32) { switch (ins.instr) { case ASM_XOR: arch_bin = MJR_BIN_LINUX; break; case ASM_PUSH: arch_bin = MJR_BIN_FREEBSD; sym = elfsh_get_metasym_by_name(obj, ELFSH_SECTION_NAME_INIT); init_addr = sym->st_value; fprintf(stderr, " [*] locating call to .init: %lx\n", (unsigned long) init_addr); break; } } else if (proc->type == ASM_PROC_SPARC) { switch (ins.instr) { case ASM_SP_MOV: arch_bin = MJR_BIN_LINUX; break; } } else if (proc->type == ASM_PROC_MIPS) { // FIXME: this should be expanded arch_bin = MJR_BIN_LINUX; } else PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Architecture not supported", -1); // FIXME: This should go to librevm fprintf(stderr, " [*] %s-like start\n", arch_bin ? "FreeBSD" : "Linux"); } /* Now fingerprint depending on the architecture */ if (proc->type == ASM_PROC_IA32) { switch (ins.instr) { case ASM_PUSH: if (*dis && (arch_bin == MJR_BIN_LINUX) && ins.op[0].type == ASM_OTYPE_IMMEDIATE) asm_operand_get_immediate(&ins, 1, 0, &main_addr); break; case ASM_CALL: if (arch_bin == MJR_BIN_FREEBSD) { asm_operand_get_immediate(&ins, 1, 0, &main_addr); if (fetch_next) stop = 1; main_addr += vaddr + *dis + ilen; if (main_addr == init_addr) fetch_next = 1; break; } else if ((arch_bin == MJR_BIN_LINUX)) { stop = 1; break; } } } else if (proc->type == ASM_PROC_SPARC) { switch (ins.instr) { case ASM_SP_SETHI: if (ins.op[0].baser == ASM_REG_O0) main_addr = ins.op[1].imm << 10; break; case ASM_SP_OR: if (ins.op[0].baser == ASM_REG_O0 && ins.op[2].baser == ASM_REG_O0 && ins.op[1].type == ASM_SP_OTYPE_IMMEDIATE) main_addr |= ins.op[1].imm; break; case ASM_SP_CALL: stop = 1; break; } } else if (proc->type == ASM_PROC_MIPS) { // FIXME: this should be expanded (WIP) main_addr = vaddr; stop = 1; } else PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Architecture not supported", -1); done += ilen; /* If we reached this point it probably means that we analyse self made software, written in asm and compiled with nasm */ if (done >= len) { main_addr = vaddr; stop = 1; } } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, main_addr); }
/** * The Real routine that handles each thread-specific breakpoint state machine. * * breakpoint case: * * 0-1: restore old instr, enable step, set bp addr in ->past, reset pc to orig bp addr * 1-2: do nothing (just executed instr) * 2-3: reinstall, resetstep, thread_contall, curthread->was_step = 0, * stoppedthread->count = NONE; e2dbgworld.curbp = NULL; stoppedthread = RUNNING * * stepping case: * * 0-1: print current instr; reinstall * stoppedthread->state = BREAKING; thread_contall; * was_step = 0; count = NONE; curbp = NULL; stoppedthread->state = RUNNING */ void e2dbg_breakpoint_process() { char buf[32]; elfshbp_t *bp; int prot; char *name; elfsh_SAddr off; int ret; asm_instr ptr; char *s; eresi_Addr *pc; eresi_Addr savedpc; u_int bpsz; elfshsect_t *sect; elfshobj_t *parent; elfsh_Sym *sym; #if __DEBUG_BP__ fprintf(stderr, " [D] Entering breakpoint handler\n"); #endif /* Set all registers as variables and get PC */ e2dbg_user_hooks_install(); e2dbg_getregs(); pc = e2dbg_getpc(); parent = e2dbg_get_parent_object((eresi_Addr) *pc); bpsz = elfsh_get_breaksize(parent); /* Print variables and registers on breakpoints */ //if (!world.state.revm_quiet) //cmd_vlist(); /* Try to find the breakpoint at current instruction pointer */ #if __DEBUG_BP__ fprintf(stderr, " [D] At PC = %08X : Trying to find breakpoint at addr %08X (bpsize = %u)\n", *pc, *pc - bpsz, bpsz); #endif snprintf(buf, sizeof(buf), XFMT, *pc - bpsz); bp = hash_get(&e2dbgworld.bp, buf); #if __DEBUG_BP__ if (bp) fprintf(stderr, " [D] Saved instruction BYTE = %02X and PC-BPSZ BYTE = %02X \n", bp->savedinstr[0], *((u_char *) *pc - bpsz)); else fprintf(stderr, " [D] No BP found at %08X ! \n", *pc); #endif /* Case of processing breakpoint, or if we are single-stepping */ if (!bp || (bp->savedinstr[0] == *((u_char *) *pc - bpsz))) { /* We are single-stepping, display the instruction at $pc */ if (e2dbgworld.stoppedthread->step) { #if __DEBUG_BP__ fprintf(stderr, " [D] Single-stepping -IS- enabled \n"); #endif ret = asm_read_instr(&ptr, (u_char *) *pc, 16, world.curjob->proc); if (!ret) ret++; sect = elfsh_get_parent_section(parent, (eresi_Addr) *pc, NULL); name = revm_resolve(parent, (eresi_Addr) *pc, &off); off = 0; sym = elfsh_get_metasym_by_value(parent, (eresi_Addr) *pc, &off, ELFSH_LOWSYM); #if __DEBUG_BP__ fprintf(stderr, " [D] Found parent = %08X (%s) in step (name = %s, parentsect = %s) off = %u\n", (eresi_Addr) parent, parent->name, name, sect->name, off); #endif revm_instr_display(-1, *pc, 0, 20, name, off, (char *) *pc); e2dbg_display(e2dbgworld.displaycmd, e2dbgworld.displaynbr); if (!e2dbgworld.stoppedthread->trace) e2dbg_entry(NULL); else e2dbg_watch(); e2dbg_breakpoint_reinstall(); return; } #if __DEBUG_BP__ fprintf(stderr, " [D] Single-stepping is -NOT- enabled \n"); #endif /* Here starts the real stuff ** ** count == E2DBG_BREAK_EXEC -> execute restored instruction ** count == E2DBG_BREAK_FINISHED -> restore breakpoint ** count > E2DBG_BREAK_MAX -> e2dbg is getting debugged by a third party debugger */ e2dbgworld.stoppedthread->count++; #if __DEBUG_BP__ fprintf(stderr, " [C] Count %u -> %u for thread ID %u \n", e2dbgworld.stoppedthread->count - 1, e2dbgworld.stoppedthread->count, ((unsigned int) e2dbgworld.stoppedthread->tid)); #endif /* execute the previously restored instruction */ if (e2dbgworld.stoppedthread->count == E2DBG_BREAK_EXEC) { #if __DEBUG_BP__ printf(" [D] At PC = 0x%X : Debuggee executed restored instruction \n", *pc); #endif return; } /* Suggested by andrewg, useful when debugging valgrind */ if (e2dbgworld.stoppedthread->count > E2DBG_BREAK_MAX) { printf(".::- E2DBG WARNING -::.\n" "Breakpoint triggered at location " AFMT " which we don't know about.\n\n" "This may be an anti-debug trick or the program may be inside another\n" "debugger. Exiting (DEBUG: count = " UFMT ", step is off)\n\n", *pc - bpsz, e2dbgworld.stoppedthread->count); return; } e2dbg_breakpoint_reinstall(); /* remove trace flag */ #if __DEBUG_BP__ fprintf(stderr, " [D] At PC = " AFMT " Resetting STEP mode\n", *pc); #endif e2dbg_resetstep(); return; } /* Case of newly hit breakpoint */ else { name = revm_resolve(parent, (eresi_Addr) *pc - bpsz, &off); s = (e2dbg_is_watchpoint(bp) ? "Watch" : "Break"); #if __DEBUG_BP__ fprintf(stderr, " [C] Count set to 1 (HIT) for thread ID %u \n", (unsigned int) e2dbgworld.stoppedthread->tid); #endif if (off) printf(" [*] %spoint found at " XFMT " <%s + " DFMT "> in thread %u \n\n", s, *pc - bpsz, name, off, (unsigned int) e2dbgworld.stoppedthread->tid); else printf(" [*] %spoint found at " XFMT " <%s> in thread %u \n\n", s, *pc - bpsz, name, (unsigned int) e2dbgworld.stoppedthread->tid); revm_doswitch(parent->id); mjr_set_current_context(&world.mjr_session, parent->name); *pc -= bpsz; prot = elfsh_munprotect(bp->obj, *pc, bpsz); memcpy((u_char *) *pc, bp->savedinstr, bpsz); elfsh_mprotect(bp->obj, *pc, bpsz, prot); e2dbg_setstep(); #if __DEBUG_BP__ fprintf(stderr, " [D] Setting Step mode \n"); #endif e2dbgworld.stoppedthread->past = *pc; e2dbgworld.stoppedthread->count = E2DBG_BREAK_HIT; e2dbgworld.curbp = bp; bp->tid = (uint32_t) e2dbgworld.stoppedthread->tid; #if __DEBUG_BP__ fprintf(stderr, " [D] Reset break \n"); #endif if (bp->cmdnbr) e2dbg_display(bp->cmd, bp->cmdnbr); else e2dbg_display(e2dbgworld.displaycmd, e2dbgworld.displaynbr); #if __DEBUG_BP__ fprintf(stderr, " [D] After BP display \n"); #endif #if __DEBUG_BP__ fprintf(stderr, " [D] PC before entry is addr 0x%X \n", *pc); #endif savedpc = *pc; e2dbg_entry(NULL); *pc = savedpc; #if __DEBUG_BP__ fprintf(stderr, " [D] At PC = 0x%X : returned from BP handler with step enabled\n", *pc); #endif } }
/** * Display An instruction. * Runtime compatible * @param fd * @param index * @param vaddr * @param foffset * @param size * @param name * @param nindex * @param buff */ int revm_instr_display(int fd, eresi_Addr vaddr, u_int foffset, u_int size, char *name, u_int symoff, char *buff) { char *s; char buf[256]; u_int idx_bytes; int ret; asm_instr ptr; char base[16] = "0123456789ABCDEF"; char logbuf[BUFSIZ]; char c1[2]; char c2[2]; u_int strsz; int err; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (!buff) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid argument", (-1)); revm_proc_init(); err = 0; /* Print the instr. itself : vaddr and relative symbol resolution */ ret = asm_read_instr(&ptr, (u_char *) buff, size, world.curjob->proc); if (ret == -1) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to read instruction", ESTD_DISASM_FAILED); s = (!ret ? "(bad)" : asm_display_instr_att(&ptr, vaddr)); /* Libasm test */ if (fd == -1) { /* Are we in quiet mode ? */ if (world.state.revm_quiet) { snprintf(buf, sizeof(buf), " %s %s + %s", revm_coloraddress(XFMT, vaddr), revm_colorstr(name), revm_colornumber("%u", symoff)); size = snprintf(logbuf, BUFSIZ, "%-40s %-30s ", buf, revm_colorinstr(s)); } else { size = snprintf(buf, sizeof(buf), " %s [%s %s] %s + %s", revm_coloraddress(XFMT, vaddr), revm_colorfieldstr("foff:"), revm_colornumber("%u", foffset), revm_colorstr(name), revm_colornumber("%u", symoff)); strsz = strlen(s); size = snprintf(logbuf, BUFSIZ, "%-*s %-*s ", (size > 95 ? 125 : size > 87 ? 100 : size > 75 ? 108 : size > 50 ? 88 : 55), buf, (strsz > 95 ? 125 : strsz > 87 ? 100 : strsz > 75 ? 108 : strsz > 50 ? 88 : 55), revm_colorinstr(s)); } /* Print bytes in hexa for this instruction */ ret = asm_instr_len(&ptr); if (!ret) ret++; if (!world.state.revm_quiet) for (idx_bytes = 0; idx_bytes < (u_int) ret; idx_bytes++) { c1[0] = base[(buff[idx_bytes] >> 4) & 0x0F]; c2[0] = base[buff[idx_bytes] & 0x0F]; c1[1] = c2[1] = 0x00; size += snprintf(logbuf + size, sizeof(logbuf) - size, "%s%s ", revm_colorfieldstr(c1), revm_colorfieldstr(c2)); } if (!world.curjob->curcmd || !world.curjob->curcmd->use_regx[1] || !regexec(&second->name, logbuf, 0, 0, 0)) { snprintf(logbuf + size, sizeof(logbuf) - size, "\n"); err = revm_output(logbuf); } revm_endline(); if (err < 0) PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, err); } else