static void dfs_node (RGraph *g, RGraphNode *n, RGraphVisitor *vis, int color[]) { RGraphEdge *edg; RStack *s = r_stack_new (2 * g->n_edges + 1); if (!s) { return; } edg = R_NEW0 (RGraphEdge); if (!edg) { r_stack_free (s); return; } edg->from = NULL; edg->to = n; r_stack_push (s, edg); while (!r_stack_is_empty (s)) { RGraphEdge *cur_edge = (RGraphEdge *)r_stack_pop (s); RGraphNode *v, *cur = cur_edge->to, *from = cur_edge->from; const RList *neighbours; RListIter *it; int i; if (from && cur) { if (color[cur->idx] == WHITE_COLOR && vis->tree_edge) vis->tree_edge (cur_edge, vis); else if (color[cur->idx] == GRAY_COLOR && vis->back_edge) vis->back_edge (cur_edge, vis); else if (color[cur->idx] == BLACK_COLOR && vis->fcross_edge) vis->fcross_edge (cur_edge, vis); } else if (!cur && from) { if (color[from->idx] != BLACK_COLOR && vis->finish_node) vis->finish_node (from, vis); color[from->idx] = BLACK_COLOR; } free (cur_edge); if (!cur || color[cur->idx] != WHITE_COLOR) { continue; } if (color[cur->idx] == WHITE_COLOR && vis->discover_node) { vis->discover_node (cur, vis); } color[cur->idx] = GRAY_COLOR; edg = R_NEW0 (RGraphEdge); edg->from = cur; r_stack_push (s, edg); i = 0; neighbours = r_graph_get_neighbours (g, cur); r_list_foreach (neighbours, it, v) { edg = R_NEW (RGraphEdge); edg->from = cur; edg->to = v; edg->nth = i++; r_stack_push (s, edg); } }
R_API void r_cons_break_end() { I.breaked = false; I.timeout = 0; r_print_set_interrupted (I.breaked); #if __UNIX__ || __CYGWIN__ signal (SIGINT, SIG_IGN); #endif if (!r_stack_is_empty (I.break_stack)) { //free all the stack r_stack_free (I.break_stack); //create another one I.break_stack = r_stack_newf (6, break_stack_free); I.data = NULL; I.event_interrupt = NULL; } }
R_API void r_cons_break_push(RConsBreak cb, void *user) { if (I.break_stack) { //if we don't have any element in the stack start the signal RConsBreakStack *b = R_NEW0 (RConsBreakStack); if (!b) return; if (r_stack_is_empty (I.break_stack)) { #if __UNIX__ || __CYGWIN__ signal (SIGINT, break_signal); #endif I.breaked = false; } //save the actual state b->event_interrupt = I.event_interrupt; b->data = I.data; r_stack_push (I.break_stack, b); //configure break I.event_interrupt = cb; I.data = user; } }
ut64 analyzeStackBased(RCore *core, Sdb *db, ut64 addr, RList *delayed_commands) { #define addCall(x) sdb_array_add_num (db, "calls", x, 0); #define addUcall(x) sdb_array_add_num (db, "ucalls", x, 0); #define addUjmp(x) sdb_array_add_num (db, "ujmps", x, 0); #define addCjmp(x) sdb_array_add_num (db, "cjmps", x, 0); #define addRet(x) sdb_array_add_num (db, "rets", x, 0); #define bbAddOpcode(x) sdb_array_insert_num (db, sdb_fmt ("bb.%"PFMT64x, addr+cur), -1, x, 0); ut64 oaddr = addr; ut64 *value = NULL; RAnalOp *op; int cur = 0; bool block_end = false; RStack *stack = r_stack_newf (10, free); addTarget (core, stack, db, addr); while (!r_stack_is_empty (stack)) { block_end = false; value = (ut64*) r_stack_pop (stack); if (!value) { eprintf ("Failed to pop next address from stack\n"); break; } addr = *value; free (value); cur = 0; while (!block_end) { op = r_core_anal_op (core, addr + cur, R_ANAL_OP_MASK_BASIC); if (!op || !op->mnemonic) { eprintf ("Cannot analyze opcode at %"PFMT64d"\n", addr+cur); oaddr = UT64_MAX; break; } if (op->mnemonic[0] == '?') { eprintf ("Cannot analyze opcode at %"PFMT64d"\n", addr+cur); oaddr = UT64_MAX; break; } bbAddOpcode (addr+cur); switch (op->type) { case R_ANAL_OP_TYPE_NOP: // skip nops if (cur == 0) { cur -= op->size; addr += op->size; oaddr += op->size; } break; case R_ANAL_OP_TYPE_CALL: /* A call instruction implies that the destination * is a new function unless the address is inside * the same range than the current function */ addCall (op->jump); r_list_append (delayed_commands, r_str_newf ("axC %"PFMT64d" %"PFMT64d, op->jump, addr + cur)); break; case R_ANAL_OP_TYPE_UCALL: case R_ANAL_OP_TYPE_ICALL: case R_ANAL_OP_TYPE_RCALL: case R_ANAL_OP_TYPE_IRCALL: /* unknown calls depend on ESIL or DEBUG tracing * information to know the destination, we can mark * those 'calls' for later adding tracepoints in * there to record all possible destinations */ addUcall (addr+cur); if (op->ptr != UT64_MAX) { r_list_append (delayed_commands, r_str_newf ("axC %"PFMT64d" %"PFMT64d, op->ptr, addr + cur)); } break; case R_ANAL_OP_TYPE_UJMP: case R_ANAL_OP_TYPE_RJMP: case R_ANAL_OP_TYPE_IJMP: case R_ANAL_OP_TYPE_IRJMP: /* an unknown jump use to go into computed destinations * outside the current function, but it may result * on an antidisasm trick */ addUjmp (addr + cur); /* An unknown jump breaks the basic blocks */ block_end = true; // XXX more investigation here break; case R_ANAL_OP_TYPE_TRAP: if (cur == 0) { // skip leading int3 cur -= op->size; addr += op->size; oaddr += op->size; } else { block_end = true; } break; case R_ANAL_OP_TYPE_RET: addRet (addr + cur); bbAdd (db, addr, addr + cur + op->size, UT64_MAX, UT64_MAX); block_end = true; break; case R_ANAL_OP_TYPE_CJMP: addCjmp (addr+cur); bbAdd (db, addr, addr + cur + op->size, op->jump, addr + cur + op->size); addTarget (core, stack, db, op->jump); addTarget (core, stack, db, addr + cur + op->size); block_end = true; r_list_append (delayed_commands, r_str_newf ("axc %"PFMT64d" %"PFMT64d, op->jump, addr + cur)); break; case R_ANAL_OP_TYPE_JMP: addUjmp (addr+cur); bbAdd (db, addr, addr + cur + op->size, op->jump, UT64_MAX); addTarget (core, stack, db, op->jump); block_end = true; r_list_append (delayed_commands, r_str_newf ("axc %"PFMT64d" %"PFMT64d, op->jump, addr + cur)); break; case R_ANAL_OP_TYPE_UNK: case R_ANAL_OP_TYPE_ILL: eprintf ("a2f: Invalid instruction\n"); block_end = true; break; default: if (op->ptr != UT64_MAX) { r_list_append (delayed_commands, r_str_newf ("axd %"PFMT64d" %"PFMT64d, op->ptr, addr + cur)); } break; } cur += op->size; r_anal_op_free (op); op = NULL; } } r_stack_free (stack); return oaddr; }
R_API int r_str_word_set0_stack(char *str) { int i; char *p, *q; RStack *s; void *pop; if (!str || !*str) { return 0; } for (i = 0; str[i] && str[i+1]; i++) { if (i > 0 && str[i-1] == ' ' && str[i] == ' ') { int len = strlen (str+i) + 1; memmove (str+i, str+i+1, len); i--; } if (i == 0 && str[i] == ' ') { memmove (str+i, str+i+1, strlen (str+i) + 1); } } if (str[i] == ' ') { str[i] = 0; } s = r_stack_new (5); //Some random number for (i = 1, p = str; *p; p++) { q = p - 1; if (p > str && (*q == '\\')) { memmove (q, p, strlen (p) + 1); p--; continue; } switch (*p) { case '(': case '{': case '[': r_stack_push (s, (void *)p); continue; case '\'': case '"': pop = r_stack_pop (s); if (pop && *(char *)pop != *p) { r_stack_push (s, pop); r_stack_push (s, (void *)p); } else if (!pop) { r_stack_push (s, (void *)p); } continue; case ')': case '}': case ']': pop = r_stack_pop (s); if (pop) { if ((*(char *)pop == '(' && *p == ')') || (*(char *)pop == '{' && *p == '}') || (*(char *)pop == '[' && *p == ']')) { continue; } } break; case ' ': if (p > str && !*q) { memmove (p, p+1, strlen (p+1) + 1); if (*q == '\\') { *q = ' '; continue; } p--; } if (r_stack_is_empty (s)) { i++; *p = '\0'; } default: break; } } r_stack_free (s); return i; }