// SPDX-FileCopyrightText: 2019 pancake // SPDX-License-Identifier: LGPL-3.0-only #define USE_BB_STACKPTR 0 #define USE_BB_LINEAR 1 static void ds_update_stackptr(RzDisasmState *ds, RzAnalysisOp *op) { if (!ds->show_stackptr) { return; } ds->ostackptr = ds->stackptr; switch (op->stackop) { case RZ_ANALYSIS_STACK_RESET: ds->stackptr = 0; break; case RZ_ANALYSIS_STACK_INC: ds->stackptr += op->stackptr; break; default: /* nothing to do here */ break; } /* XXX if we reset the stackptr 'ret 0x4' has not effect. * Use RzAnalysisFunction->RzAnalysisOp->stackptr? */ if (op->type == RZ_ANALYSIS_OP_TYPE_RET) { ds->stackptr = 0; } } static int _stackptr_range(RzDisasmState *ds, ut64 addr, ut64 addr_end, int stackptr, int *ostackptr) { ut64 at = addr; ut64 end = addr_end; while (at < end) { int sz = 1; RzAnalysisOp *op = rz_core_analysis_op(ds->core, at, 0); if (op) { *ostackptr = stackptr; switch (op->stackop) { case RZ_ANALYSIS_STACK_RESET: stackptr = 0; break; case RZ_ANALYSIS_STACK_INC: stackptr += op->stackptr; break; default: /* nothing to do here */ break; } if (op->size > 0) { sz = op->size; } rz_analysis_op_free(op); } at += sz; } return stackptr; } static int ds_ostackptr_atfcn(RzDisasmState *ds, int *ostackptr) { if (!ds->show_stackptr) { return 0; } #if USE_BB_LINEAR if (ds->at >= ds->fcn->addr) { return _stackptr_range(ds, ds->fcn->addr, ds->at, 0, ostackptr); } return ds->stackptr; #else int stackptr = 0; // SLOW, recursive emulation is more correct, but slow to find paths // return stackptr; ut64 addr = ds->at; RzList *paths = rz_core_analysis_graph_to(ds->core, addr, 2); if (paths) { RzAnalysisBlock *bb; RzList *path; RzListIter *pathi; RzListIter *bbi; rz_list_foreach (paths, pathi, path) { rz_list_foreach (path, bbi, bb) { ut64 end = bb->addr + bb->size; if (addr >= bb->addr && addr < bb->addr + bb->size) { end = addr; } stackptr = _stackptr_range(ds, bb->addr, end, stackptr, ostackptr); } } rz_list_free(paths); } return stackptr; #endif } static int ds_ostackptr_at(RzDisasmState *ds, int *ostackptr) { #if USE_BB_STACKPTR // XXX doesnt works because bb->stackptr returns the maximum increment of the bb instead of the initial stackptr value *ostackptr = ds->ostackptr; RzAnalysisFunction *fcn = rz_analysis_get_fcn_in(ds->core->analysis, ds->at, RZ_ANALYSIS_FCN_TYPE_NULL); if (fcn) { RzAnalysisBlock *bb = rz_analysis_fcn_bbget_in(ds->core->analysis, fcn, ds->at); if (bb) { return bb->stackptr; } else { rz_warn_if_reached(); } } return 0; #else if (ds->fcn) { return ds_ostackptr_atfcn(ds, ostackptr); } *ostackptr = ds->ostackptr; return ds->stackptr; #endif } static void ds_print_stackptr(RzDisasmState *ds) { int ostackptr = 0; int stackptr = ds_ostackptr_at(ds, &ostackptr); if (ds->show_stackptr) { rz_cons_printf("%5d%s", stackptr, ds->analysis_op.type == RZ_ANALYSIS_OP_TYPE_CALL ? ">" : ds->analysis_op.stackop == RZ_ANALYSIS_STACK_ALIGN ? "=" : stackptr > ostackptr ? "+" : stackptr < ostackptr ? "-" : " "); ds_update_stackptr(ds, &ds->analysis_op); } }