Branch prediction optimizations (3/3) ##performance

This commit is contained in:
pancake 2023-04-18 17:48:13 +02:00 committed by GitHub
parent 433917e551
commit 872e02dff9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 146 additions and 117 deletions

View File

@ -35,11 +35,14 @@ static void __max_end(RBNode *node) {
static int __bb_addr_cmp(const void *incoming, const RBNode *in_tree, void *user) {
ut64 incoming_addr = *(ut64 *)incoming;
const RAnalBlock *in_tree_block = container_of (in_tree, const RAnalBlock, _rb);
if (incoming_addr < in_tree_block->addr) {
return -1;
}
if (incoming_addr > in_tree_block->addr) {
return 1;
if (in_tree_block) {
ut64 itaddr = in_tree_block->addr;
if (incoming_addr < itaddr) {
return -1;
}
if (incoming_addr > itaddr) {
return 1;
}
}
return 0;
}

View File

@ -383,17 +383,17 @@ R_API void r_anal_hint_free(RAnalHint *h) {
R_API R_NULLABLE R_BORROW const char *r_anal_hint_arch_at(RAnal *anal, ut64 addr, R_NULLABLE ut64 *hint_addr) {
RBNode *node = r_rbtree_upper_bound (anal->arch_hints, &addr, ranged_hint_record_cmp, NULL);
if (!node) {
if (R_LIKELY (node)) {
RAnalArchHintRecord *record = (RAnalArchHintRecord *)container_of (node, RAnalRangedHintRecordBase, rb);
if (hint_addr) {
*hint_addr = UT64_MAX;
*hint_addr = record->base.addr;
}
return NULL;
return record->arch;
}
RAnalArchHintRecord *record = (RAnalArchHintRecord *)container_of (node, RAnalRangedHintRecordBase, rb);
if (hint_addr) {
*hint_addr = record->base.addr;
*hint_addr = UT64_MAX;
}
return record->arch;
return NULL;
}
R_API int r_anal_hint_bits_at(RAnal *anal, ut64 addr, R_NULLABLE ut64 *hint_addr) {

View File

@ -2756,6 +2756,56 @@ static void set_opdir(RAnalOp *op, cs_insn *insn) {
}
}
static void inscmp(RAnalOp *op, ut64 addr, cs_insn *insn, int regsz) {
switch (INSOP(0).type) {
case X86_OP_MEM:
op->disp = INSOP(0).mem.disp;
op->refptr = INSOP(0).size;
if (INSOP(0).mem.base == X86_REG_RIP) {
op->ptr = addr + insn->size + op->disp;
} else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) {
op->stackop = R_ANAL_STACK_SET;
op->stackptr = regsz;
op->type |= R_ANAL_OP_TYPE_REG;
} else if (INSOP(0).mem.segment == X86_REG_INVALID && INSOP(0).mem.base == X86_REG_INVALID
&& INSOP(0).mem.index == X86_REG_INVALID && INSOP(0).mem.scale == 1) { // [<addr>]
op->ptr = op->disp;
}
if (INSOP(1).type == X86_OP_IMM) {
op->val = INSOP(1).imm;
}
break;
default:
switch (INSOP(1).type) {
case X86_OP_MEM:
op->disp = INSOP(1).mem.disp;
op->refptr = INSOP(1).size;
if (INSOP(1).mem.base == X86_REG_RIP) {
op->ptr = addr + insn->size + op->disp;
} else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) {
op->type |= R_ANAL_OP_TYPE_REG;
op->stackop = R_ANAL_STACK_SET;
op->stackptr = regsz;
} else if (INSOP(1).mem.segment == X86_REG_INVALID
&& INSOP(1).mem.base == X86_REG_INVALID
&& INSOP(1).mem.index == X86_REG_INVALID
&& INSOP(1).mem.scale == 1) { // [<addr>]
op->ptr = op->disp;
}
if (INSOP(0).type == X86_OP_IMM) {
op->val = INSOP(0).imm;
}
break;
case X86_OP_IMM:
op->val = op->ptr = INSOP(1).imm;
break;
default:
break;
}
break;
}
}
static void anop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) {
int bits = a->config->bits;
struct Getarg gop = {
@ -3140,59 +3190,12 @@ static void anop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh
case X86_INS_CMPSQ:
case X86_INS_CMPSB:
case X86_INS_CMPSS:
op->type = R_ANAL_OP_TYPE_CMP;
inscmp (op, addr, insn, regsz);
break;
case X86_INS_TEST:
if (insn->id == X86_INS_TEST) {
op->type = R_ANAL_OP_TYPE_ACMP; //compare via and
} else {
op->type = R_ANAL_OP_TYPE_CMP;
}
switch (INSOP(0).type) {
case X86_OP_MEM:
op->disp = INSOP(0).mem.disp;
op->refptr = INSOP(0).size;
if (INSOP(0).mem.base == X86_REG_RIP) {
op->ptr = addr + insn->size + op->disp;
} else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) {
op->stackop = R_ANAL_STACK_SET;
op->stackptr = regsz;
op->type |= R_ANAL_OP_TYPE_REG;
} else if (INSOP(0).mem.segment == X86_REG_INVALID && INSOP(0).mem.base == X86_REG_INVALID
&& INSOP(0).mem.index == X86_REG_INVALID && INSOP(0).mem.scale == 1) { // [<addr>]
op->ptr = op->disp;
}
if (INSOP(1).type == X86_OP_IMM) {
op->val = INSOP(1).imm;
}
break;
default:
switch (INSOP(1).type) {
case X86_OP_MEM:
op->disp = INSOP(1).mem.disp;
op->refptr = INSOP(1).size;
if (INSOP(1).mem.base == X86_REG_RIP) {
op->ptr = addr + insn->size + op->disp;
} else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) {
op->type |= R_ANAL_OP_TYPE_REG;
op->stackop = R_ANAL_STACK_SET;
op->stackptr = regsz;
} else if (INSOP(1).mem.segment == X86_REG_INVALID
&& INSOP(1).mem.base == X86_REG_INVALID
&& INSOP(1).mem.index == X86_REG_INVALID
&& INSOP(1).mem.scale == 1) { // [<addr>]
op->ptr = op->disp;
}
if (INSOP(0).type == X86_OP_IMM) {
op->val = INSOP(0).imm;
}
break;
case X86_OP_IMM:
op->val = op->ptr = INSOP(1).imm;
break;
default:
break;
}
break;
}
op->type = R_ANAL_OP_TYPE_ACMP; // compare via and
inscmp (op, addr, insn, regsz);
break;
case X86_INS_LEA:
op->type = R_ANAL_OP_TYPE_LEA;

View File

@ -7,6 +7,8 @@
#include <r_list.h>
#define ACCESS_CMP(x, y) ((st64)((ut64)(x) - ((RAnalVarAccess *)y)->offset))
// XXX this helper function is crap and shouldnt be used
#define STR_EQUAL(s1, s2) (s1 && s2 && !strcmp (s1, s2))
R_API bool r_anal_var_display(RAnal *anal, RAnalVar *var) {
r_return_val_if_fail (anal && var, false);
@ -30,16 +32,17 @@ R_API bool r_anal_var_display(RAnal *anal, RAnalVar *var) {
R_LOG_ERROR ("register not found");
}
break;
case R_ANAL_VAR_KIND_BPV: {
const st32 real_delta = var->delta + var->fcn->bp_off;
const ut32 udelta = R_ABS (real_delta);
const char sign = real_delta >= 0 ? '+' : '-';
if (usePxr) {
anal->cb_printf ("pxr $w @%s%c0x%x\n", anal->reg->name[R_REG_NAME_BP], sign, udelta);
} else {
anal->cb_printf ("pf %s @%s%c0x%x\n", fmt, anal->reg->name[R_REG_NAME_BP], sign, udelta);
case R_ANAL_VAR_KIND_BPV:
{
const st32 real_delta = var->delta + var->fcn->bp_off;
const ut32 udelta = R_ABS (real_delta);
const char sign = real_delta >= 0 ? '+' : '-';
if (usePxr) {
anal->cb_printf ("pxr $w @%s%c0x%x\n", anal->reg->name[R_REG_NAME_BP], sign, udelta);
} else {
anal->cb_printf ("pf %s @%s%c0x%x\n", fmt, anal->reg->name[R_REG_NAME_BP], sign, udelta);
}
}
}
break;
case R_ANAL_VAR_KIND_SPV: {
ut32 udelta = R_ABS (var->delta + var->fcn->maxstack);
@ -856,6 +859,7 @@ static bool var_add_structure_fields_to_list(RAnal *a, RAnalVar *av, RList *list
}
static const char *get_regname(RAnal *anal, RAnalValue *value) {
// R2_590 - this is underperforming hard
const char *name = NULL;
if (value && value->reg && value->reg->name) {
name = value->reg->name;
@ -1082,7 +1086,33 @@ beach:
;
}
static bool is_reg_in_src(const char *regname, RAnal *anal, RAnalOp *op);
#if 0
static bool is_reg_in_src(const char *regname, RAnal *anal, RAnalOp *op) {
RAnalValue *src0 = r_vector_at (&op->srcs, 0);
RAnalValue *src1 = r_vector_at (&op->srcs, 1);
RAnalValue *src2 = r_vector_at (&op->srcs, 2);
const char* opsreg0 = src0 ? get_regname (anal, src0) : NULL;
const char* opsreg1 = src1 ? get_regname (anal, src1) : NULL;
const char* opsreg2 = src2 ? get_regname (anal, src2) : NULL;
return (STR_EQUAL (regname, opsreg0)) || (STR_EQUAL (regname, opsreg1)) || (STR_EQUAL (regname, opsreg2));
}
#else
static bool is_reg_in_src(const char *regname, RAnal *anal, RAnalOp *op) {
r_return_val_if_fail (regname && anal && op, false);
int i;
for (i = 0; i < 3; i++) {
RAnalValue *src = r_vector_at (&op->srcs, i);
if (!src) {
return false;
}
const char *srcreg = get_regname (anal, src);
if (srcreg && !strcmp (regname, srcreg)) {
return true;
}
}
return false;
}
#endif
static inline bool op_affect_dst(RAnalOp* op) {
switch (op->type) {
@ -1108,10 +1138,9 @@ static inline bool op_affect_dst(RAnalOp* op) {
}
}
#define STR_EQUAL(s1, s2) (s1 && s2 && !strcmp (s1, s2))
static inline bool arch_destroys_dst(const char *arch) {
return (STR_EQUAL (arch, "arm") || STR_EQUAL (arch, "riscv") || STR_EQUAL (arch, "ppc"));
r_return_val_if_fail (arch, false);
return (!strcmp (arch, "arm") || !strcmp (arch, "riscv") || !strcmp (arch, "ppc"));
}
static bool is_used_like_arg(const char *regname, const char *opsreg, const char *opdreg, RAnalOp *op, RAnal *anal) {
@ -1155,16 +1184,6 @@ static bool is_used_like_arg(const char *regname, const char *opsreg, const char
}
}
static bool is_reg_in_src(const char *regname, RAnal *anal, RAnalOp *op) {
RAnalValue *src0 = r_vector_at (&op->srcs, 0);
RAnalValue *src1 = r_vector_at (&op->srcs, 1);
RAnalValue *src2 = r_vector_at (&op->srcs, 2);
const char* opsreg0 = src0 ? get_regname (anal, src0) : NULL;
const char* opsreg1 = src1 ? get_regname (anal, src1) : NULL;
const char* opsreg2 = src2 ? get_regname (anal, src2) : NULL;
return (STR_EQUAL (regname, opsreg0)) || (STR_EQUAL (regname, opsreg1)) || (STR_EQUAL (regname, opsreg2));
}
R_API void r_anal_extract_rarg(RAnal *anal, RAnalOp *op, RAnalFunction *fcn, int *reg_set, int *count) {
int i, argc = 0;
r_return_if_fail (anal && op && fcn);
@ -1273,21 +1292,23 @@ R_API void r_anal_extract_rarg(RAnal *anal, RAnalOp *op, RAnalFunction *fcn, int
for (i = 0; i < max_count; i++) {
const char *regname = r_anal_cc_arg (anal, fcn->cc, i);
if (regname) {
if (!regname) {
// WIP break;
} else {
int delta = 0;
RRegItem *ri = NULL;
RAnalVar *var = NULL;
bool is_used_like_an_arg = is_used_like_arg (regname, opsreg, opdreg, op, anal);
if (reg_set[i] != 2 && is_used_like_an_arg) {
const bool is_arg = is_used_like_arg (regname, opsreg, opdreg, op, anal);
if (is_arg && reg_set[i] != 2) {
ri = r_reg_get (anal->reg, regname, -1);
if (ri) {
delta = ri->index;
r_unref (ri);
}
}
if (reg_set[i] == 1 && is_used_like_an_arg) {
if (is_arg && reg_set[i] == 1) {
var = r_anal_function_get_var (fcn, R_ANAL_VAR_KIND_REG, delta);
} else if (reg_set[i] != 2 && is_used_like_an_arg) {
} else if (is_arg && reg_set[i] != 2) {
const char *vname = NULL;
char *type = NULL;
char *name = NULL;
@ -1321,8 +1342,8 @@ R_API void r_anal_extract_rarg(RAnal *anal, RAnalOp *op, RAnalFunction *fcn, int
const char *selfreg = r_anal_cc_self (anal, fcn->cc);
if (selfreg) {
bool is_used_like_an_arg = is_used_like_arg (selfreg, opsreg, opdreg, op, anal);
if (reg_set[i] != 2 && is_used_like_an_arg) {
bool is_arg = is_used_like_arg (selfreg, opsreg, opdreg, op, anal);
if (is_arg && reg_set[i] != 2) {
int delta = 0;
char *vname = strdup ("self");
RRegItem *ri = r_reg_get (anal->reg, selfreg, -1);
@ -1383,9 +1404,7 @@ R_API void r_anal_extract_vars(RAnal *anal, RAnalFunction *fcn, RAnalOp *op) {
}
static RList *var_generate_list(RAnal *a, RAnalFunction *fcn, int kind) {
if (!a || !fcn) {
return NULL;
}
r_return_val_if_fail (a && fcn, NULL);
RList *list = r_list_new ();
if (kind < 1) {
kind = R_ANAL_VAR_KIND_BPV; // by default show vars
@ -1534,6 +1553,7 @@ static int var_comparator(const RAnalVar *a, const RAnalVar *b) {
}
R_API void r_anal_var_list_show(RAnal *anal, RAnalFunction *fcn, int kind, int mode, PJ *pj) {
r_return_if_fail (anal && fcn);
bool newstack = anal->opt.var_newstack;
RList *list = r_anal_var_list (anal, fcn, kind);
RAnalVar *var;

View File

@ -20,16 +20,12 @@ static RBinSymbol *__getMethod(RBinFile *bf, const char *klass, const char *meth
}
static RBinString *__stringAt(RBinFile *bf, RList *ret, ut64 addr) {
if (addr != 0 && addr != UT64_MAX) {
if (R_LIKELY (addr != 0 && addr != UT64_MAX)) {
return ht_up_find (bf->o->strings_db, addr, NULL);
}
return NULL;
}
static ut64 binobj_a2b(RBinObject *bo, ut64 addr) {
return addr + (bo ? bo->baddr_shift : 0);
}
static void print_string(RBinFile *bf, RBinString *string, int raw, PJ *pj) {
r_return_if_fail (bf && string);
@ -1130,7 +1126,7 @@ R_API RBinField *r_bin_file_add_field(RBinFile *binfile, const char *classname,
R_API ut64 r_bin_file_get_vaddr(RBinFile *bf, ut64 paddr, ut64 vaddr) {
r_return_val_if_fail (bf && bf->o, paddr);
if (bf->o->info && bf->o->info->has_va) {
return binobj_a2b (bf->o, vaddr);
return bf->o->baddr_shift + vaddr;
}
return paddr;
}

View File

@ -49,10 +49,6 @@ static const char *__getname(RBin *bin, int type, int idx, bool sd) {
return NULL;
}
static ut64 binobj_a2b(RBinObject *o, ut64 addr) {
return o ? addr + o->baddr_shift : addr;
}
// TODO: move these two function do a different file
R_API RBinXtrData *r_bin_xtrdata_new(RBuffer *buf, ut64 offset, ut64 size, ut32 file_count, RBinXtrMetadata *metadata) {
RBinXtrData *data = R_NEW0 (RBinXtrData);
@ -713,18 +709,16 @@ R_API RList *r_bin_get_sections(RBin *bin) {
}
R_API RBinSection *r_bin_get_section_at(RBinObject *o, ut64 off, int va) {
r_return_val_if_fail (o, NULL);
RBinSection *section;
RListIter *iter;
ut64 from, to;
r_return_val_if_fail (o, NULL);
// TODO: must be O(1) .. use sdb here
r_list_foreach (o->sections, iter, section) {
if (section->is_segment) {
continue;
}
from = va ? binobj_a2b (o, section->vaddr) : section->paddr;
to = from + (va ? section->vsize: section->size);
ut64 from = va ? o->baddr_shift + section->vaddr : section->paddr;
ut64 to = from + (va ? section->vsize: section->size);
if (off >= from && off < to) {
return section;
}
@ -1281,10 +1275,14 @@ R_API ut64 r_bin_get_vaddr(RBin *bin, ut64 paddr, ut64 vaddr) {
return r_bin_file_get_vaddr (bin->cur, paddr, vaddr);
}
// XXX remove this public api
R_API ut64 r_bin_a2b(RBin *bin, ut64 addr) {
r_return_val_if_fail (bin, UT64_MAX);
RBinObject *o = r_bin_cur_object (bin);
return binobj_a2b (o, addr);
if (o) {
return o->baddr_shift + addr;
}
return addr;
}
R_API ut64 r_bin_get_size(RBin *bin) {

View File

@ -1680,6 +1680,12 @@ static int var_cmd(RCore *core, const char *str) {
int delta, type = *str, res = true;
RAnalVar *v1;
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, -1);
if (!fcn) {
if (str[0] == 'j') { // "afvj"
r_cons_println ("{}");
}
return false;
}
if (!str[0]) {
if (fcn) {
// "afv"
@ -1911,8 +1917,12 @@ static int var_cmd(RCore *core, const char *str) {
if (!pj) {
return false;
}
r_anal_var_list_show (core->anal, fcn, type, str[1], pj);
r_cons_println (pj_string (pj));
if (fcn) {
r_anal_var_list_show (core->anal, fcn, type, str[1], pj);
r_cons_println (pj_string (pj));
} else {
R_LOG_ERROR ("No function");
}
pj_free (pj);
break;
case '.': // "afv[bsr]."

View File

@ -278,10 +278,9 @@ R_API bool r_rbtree_aug_update_sum(RBNode *root, void *data, RBNode *node, RBCom
if (cur == node) {
break;
}
int direction = cmp (data, cur, cmp_user);
const int direction = cmp (data, cur, cmp_user);
cur = cur->child[(direction < 0)? 0: 1];
}
for (; depth > 0; depth--) {
sum (path[depth - 1]);
}
@ -294,7 +293,7 @@ R_API bool r_rbtree_delete(RBNode **root, void *data, RBComparator cmp, void *cm
R_API RBNode *r_rbtree_find(RBNode *x, void *data, RBComparator cmp, void *user) {
while (x) {
int direction = cmp (data, x, user);
const int direction = cmp (data, x, user);
if (direction < 0) {
x = x->child[0];
} else if (direction > 0) {