/** * SIGTRAP signal handler (The breakpoint routine). Save registers and callback. Multi-thread safe. * @param signum Received signal number. * @param info Signal info structure from breakpoint. * @param pcontext Context data pointer containing register values and more. * @return */ void e2dbg_generic_breakpoint(int signum, siginfo_t *info, void *pcontext) { ucontext_t *context; char key[15]; pthread_t stopped; /* Do not allow processing of 2 breakpoint at the same time */ /* We update the current thread information */ e2dbg_presence_set(); revm_proc_init(); if (!e2dbgworld.curbp || e2dbgworld.curbp->tid != e2dbg_self()) { e2dbg_mutex_lock(&e2dbgworld.dbgbp); #if (__DEBUG_THREADS__ || __DEBUG_E2DBG__ || __DEBUG_MUTEX__ || __DEBUG_BP__) //e2dbg_output("-------------- ON-BREAK REGISTERS ----------------------->\n"); //cmd_dumpregs(); //e2dbg_output("<------------------------------------------------------\n"); e2dbg_output("------------------------------------->\n"); e2dbg_output(" [*] BP MUTEX LOCKED [e2dbg_generic_breakpoint] \n"); //e2dbg_threads_print(); #endif } /* Get the current thread */ stopped = (pthread_t) e2dbg_self(); snprintf(key, sizeof(key), "%u", (unsigned int) stopped); e2dbgworld.curthread = hash_get(&e2dbgworld.threads, key); e2dbgworld.stoppedthread = e2dbgworld.curthread; #if (__DEBUG_THREADS__ || __DEBUG_E2DBG__ || __DEBUG_MUTEX__ || __DEBUG_BP__) fprintf(stderr, "\n [*] Thread entering generic breakpoint (ID %u) \n", (unsigned int) e2dbgworld.stoppedthread->tid); fflush(stdout); #endif e2dbgworld.stoppedthread->state = E2DBG_THREAD_BREAKING; context = (ucontext_t *) pcontext; e2dbgworld.stoppedthread->context = context; /* We first get contexts for all other threads (except debugger) using SIGUSR2 */ /* Then we stop all threads */ /* We do this only at the first state (count = 0) of the breakpoint */ if (!e2dbgworld.stoppedthread->count) { if (e2dbg_thread_stopall(SIGUSR2)) usleep(100000); } #if (__DEBUG_THREADS__ || __DEBUG_E2DBG__ || __DEBUG_MUTEX__ || __DEBUG_BP__) else fprintf(stderr, " NOT COLLECTING THREADS CONTEXTS (stopped thread %u state count = %u) \n", (u_int) e2dbgworld.stoppedthread->tid, e2dbgworld.stoppedthread->count); #endif /* Call the real breakpoint code */ e2dbg_breakpoint_process(); /* Continue all threads */ if (e2dbgworld.stoppedthread->count == E2DBG_BREAK_FINISHED || e2dbgworld.curthread->step || e2dbgworld.curthread->was_step) { e2dbg_thread_contall(); e2dbgworld.curthread->was_step = 0; e2dbgworld.stoppedthread->count = E2DBG_BREAK_NONE; e2dbgworld.curbp = NULL; fprintf(stderr, " [D] Thread ID %lu now has Count = 0 (NONE) \n", e2dbgworld.curthread->tid); /* Allow another breakpoint to be processed */ if (e2dbg_mutex_unlock(&e2dbgworld.dbgbp) != 0) e2dbg_output(" [*] Debuggee Cannot unlock breakpoint mutex ! \n"); #if (__DEBUG_THREADS__ || __DEBUG_E2DBG__ || __DEBUG_MUTEX__ || __DEBUG_BP__) else { e2dbg_output(" [*] BP MUTEX UNLOCKED [e2dbg_generic_breakpoint] \n"); e2dbg_output("<-------------------------------------\n"); } #endif } #if (__DEBUG_THREADS__ || __DEBUG_E2DBG__ || __DEBUG_MUTEX__ || __DEBUG_BP__) else fprintf(stderr, " [D] No SIGCONT as thread (%u) is stopped with state count = %u \n", (u_int) e2dbgworld.stoppedthread->tid, e2dbgworld.stoppedthread->count); #endif e2dbgworld.stoppedthread->state = E2DBG_THREAD_RUNNING; e2dbg_presence_reset(); SETSIG; #if __DEBUG_BP__ fprintf(stderr, " [D] Returning from generic signal handler\n"); #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