void BytecodeTranslatorVisitor::visitForNode(ForNode* node) { onVisitNode(node); const AstVar* i = node->var(); if (i->type() != VT_INT) ERROR("Non-iterable type in for loop"); const BinaryOpNode* expr = node->inExpr()->asBinaryOpNode(); if (expr == NULL || expr->kind() != tRANGE) ERROR("Invalid range in for loop"); CONTEXT(function(), locals(), node->body()->scope(), typeStack()); beforeProcessBlock(); bool needTempVar = !expr->right()->isIntLiteralNode(); AstVar* temp = NULL; if (needTempVar) { if (!scope()->declareVariable("<tempForEnd>", VT_INT)) ERROR("internal error: temp name is unavailable"); temp = scope()->lookupVariable("<tempForEnd>", false); } Label L_Begin(bytecode()); Label L_End(bytecode()); VISIT(expr->left()); EMIT_STORE(i); if (needTempVar) { VISIT(expr->right()); EMIT_STORE(temp); popType(VT_INT); } popType(VT_INT); EMIT_BIND(L_Begin); if (needTempVar) EMIT_LOAD(temp); else VISIT(expr->right()); EMIT_LOAD(i); EMIT_BRANCH(BC_IFICMPG, L_End); processBlockNode(node->body()); afterProcessBlock(); /* i += 1 */ EMIT_LOAD(i); EMIT(BC_ILOAD1); EMIT(BC_IADD); EMIT_STORE(i); EMIT_BRANCH(BC_JA, L_Begin); EMIT_BIND(L_End); pushType(VT_VOID); }
void BytecodeTranslatorVisitor::visitLoadNode(LoadNode* node) { onVisitNode(node); EMIT_LOAD(node->var()); pushType(node->var()->type()); }
void BytecodeTranslatorVisitor::visitStoreNode(StoreNode* node) { onVisitNode(node); visitTyped(node->value(), node->var()->type()); pushType(node->var()->type()); if (node->op() == tINCRSET || node->op() == tDECRSET) { ensureTopIsNumeric(); EMIT_LOAD(node->var()); if (node->op() == tINCRSET) EMIT(TYPED(ADD)); else EMIT(TYPED(SUB)); } else if (node->op() != tASSIGN) ERROR("Invalid store operation"); EMIT_STORE(node->var()); popType(); pushType(VT_VOID); /* a = b = c is forbidden */ }
static int bpf_anal(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) { RBpfSockFilter *f = (RBpfSockFilter *)data; memset (op, '\0', sizeof (RAnalOp)); op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; op->type = R_ANAL_OP_TYPE_UNK; op->size = 8; op->addr = addr; r_strbuf_init (&op->esil); switch (f->code) { case BPF_RET | BPF_A: op->type = R_ANAL_OP_TYPE_RET; esilprintf (op, "A,R0,=,0,$"); break; case BPF_RET | BPF_K: case BPF_RET | BPF_X: op->type = R_ANAL_OP_TYPE_RET; if (BPF_SRC (f->code) == BPF_K) { esilprintf (op, "%" PFMT64d ",R0,=,0,$", f->k); } else if (BPF_SRC (f->code) == BPF_X) { esilprintf (op, "X,R0,=,0,$"); } break; case BPF_MISC_TAX: op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "A", "X"); esilprintf (op, "A,X,="); break; case BPF_MISC_TXA: op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,="); break; case BPF_ST: if (INSIDE_M (f->k)) { op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "A", M[f->k]); esilprintf (op, "A,M[%" PFMT64d "],=", f->k); } else { op->type = R_ANAL_OP_TYPE_ILL; } break; case BPF_STX: if (INSIDE_M (f->k)) { op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "X", M[f->k]); esilprintf (op, "X,M[%" PFMT64d "],=", f->k); } else { op->type = R_ANAL_OP_TYPE_ILL; } break; case BPF_LD_W | BPF_LEN: op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "len", "A"); esilprintf (op, "len,A,=", f->k); break; case BPF_LDX | BPF_LEN: op->type = R_ANAL_OP_TYPE_MOV; SET_REG_SRC_DST (op, "len", "X"); esilprintf (op, "len,X,=", f->k); break; case BPF_LD_W | BPF_ABS: EMIT_LOAD (op, anal->gp + f->k, 4); SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",>,?{,0,R0,=,0,$,BREAK,},%" PFMT64d ",[4],A,=", f->k + 4, op->ptr); break; case BPF_LD_H | BPF_ABS: EMIT_LOAD (op, anal->gp + f->k, 2); SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",>,?{,0,R0,=,0,$,BREAK,}," "%" PFMT64d ",[2],A,=", f->k + 2, op->ptr); break; case BPF_LD_B | BPF_ABS: EMIT_LOAD (op, anal->gp + f->k, 1); SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",>,?{,0,R0,=,0,$,BREAK,}," "%" PFMT64d ",[1],A,=", f->k + 1, op->ptr); break; case BPF_LD_W | BPF_IND: op->type = R_ANAL_OP_TYPE_LOAD; op->ptrsize = 4; SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",X,+,0xffffffff,&,>,?{,0,R0,=,0,$,BREAK,}," "%" PFMT64d ",X,+,0xffffffff,&,[4],A,=", (st32)f->k + 4, anal->gp + (st32)f->k); break; case BPF_LD_H | BPF_IND: op->type = R_ANAL_OP_TYPE_LOAD; op->ptrsize = 2; SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",X,+,0xffffffff,&,>,?{,0,R0,=,0,$,BREAK,}," "%" PFMT64d ",X,+,0xffffffff,&,[2],A,=", (st32)f->k + 2, anal->gp + (st32)f->k); break; case BPF_LD_B | BPF_IND: op->type = R_ANAL_OP_TYPE_LOAD; op->ptrsize = 1; SET_A_DST (op); esilprintf (op, "len,%" PFMT64d ",X,+,0xffffffff,&,>,?{,0,R0,=,0,$,BREAK,}," "%" PFMT64d ",X,+,0xffffffff,&,[1],A,=", (st32)f->k + 1, anal->gp + (st32)f->k); break; case BPF_LD | BPF_IMM: op->type = R_ANAL_OP_TYPE_MOV; op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "0x%08" PFMT64x ",A,=", f->k); break; case BPF_LDX | BPF_IMM: op->type = R_ANAL_OP_TYPE_MOV; op->val = f->k; SET_REG_DST_IMM (op, "X", f->k); esilprintf (op, "0x%08" PFMT64x ",X,=", f->k); break; case BPF_LDX_B | BPF_MSH: op->type = R_ANAL_OP_TYPE_LOAD; op->ptrsize = 1; op->ptr = anal->gp + f->k; SET_A_DST (op); esilprintf (op, "%" PFMT64d ",[1],0xf,&,4,*,X,=", op->ptr); break; case BPF_LD | BPF_MEM: op->type = R_ANAL_OP_TYPE_MOV; if (INSIDE_M (f->k)) { SET_REG_SRC_DST (op, M[f->k], "A"); esilprintf (op, "M[%" PFMT64d "],A,=", f->k); } else { op->type = R_ANAL_OP_TYPE_ILL; } break; case BPF_LDX | BPF_MEM: op->type = R_ANAL_OP_TYPE_MOV; if (INSIDE_M (f->k)) { SET_REG_SRC_DST (op, M[f->k], "X"); esilprintf (op, "M[%" PFMT64d "],X,=", f->k); } else { op->type = R_ANAL_OP_TYPE_ILL; } break; case BPF_JMP_JA: op->type = R_ANAL_OP_TYPE_JMP; op->jump = addr + 8 + f->k * 8; esilprintf (op, "%" PFMT64d ",pc,=", op->jump); break; case BPF_JMP_JGT | BPF_X: case BPF_JMP_JGT | BPF_K: EMIT_CJMP (op, addr, f); op->cond = R_ANAL_COND_GT; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; esilprintf (op, "%" PFMT64d ",A,>,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->val, op->jump, op->fail); } else if (BPF_SRC (f->code) == BPF_X) { esilprintf (op, "X,A,>,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->jump, op->fail); } else { op->type = R_ANAL_OP_TYPE_ILL; } break; case BPF_JMP_JGE | BPF_X: case BPF_JMP_JGE | BPF_K: EMIT_CJMP (op, addr, f); op->cond = R_ANAL_COND_GE; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; esilprintf (op, "%" PFMT64d ",A,>=,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->val, op->jump, op->fail); } else { esilprintf (op, "X,A,>=,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->jump, op->fail); } break; case BPF_JMP_JEQ | BPF_X: case BPF_JMP_JEQ | BPF_K: EMIT_CJMP (op, addr, f); op->cond = R_ANAL_COND_EQ; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; esilprintf (op, "%" PFMT64d ",A,==,$z,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->val, op->jump, op->fail); } else { esilprintf (op, "X,A,==,$z,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->jump, op->fail); } break; case BPF_JMP_JSET | BPF_X: case BPF_JMP_JSET | BPF_K: EMIT_CJMP (op, addr, f); if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; esilprintf (op, "%" PFMT64d ",A,&,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->val, op->jump, op->fail); } else { esilprintf (op, "X,A,&,!,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=", op->val, op->jump, op->fail); } break; case BPF_ALU_NEG: op->type = R_ANAL_OP_TYPE_NOT; esilprintf (op, "A,0,-,A,="); SET_REG_SRC_DST (op, "A", "A"); break; case BPF_ALU_LSH | BPF_X: case BPF_ALU_LSH | BPF_K: op->type = R_ANAL_OP_TYPE_SHL; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,<<=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,<<="); } break; case BPF_ALU_RSH | BPF_X: case BPF_ALU_RSH | BPF_K: op->type = R_ANAL_OP_TYPE_SHR; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,>>=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,>>="); } break; case BPF_ALU_ADD | BPF_X: case BPF_ALU_ADD | BPF_K: op->type = R_ANAL_OP_TYPE_ADD; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", op->val); esilprintf (op, "%" PFMT64d ",A,+=", op->val); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,+="); } break; case BPF_ALU_SUB | BPF_X: case BPF_ALU_SUB | BPF_K: op->type = R_ANAL_OP_TYPE_SUB; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", op->val); esilprintf (op, "%" PFMT64d ",A,-=", op->val); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,-="); } break; case BPF_ALU_MUL | BPF_X: case BPF_ALU_MUL | BPF_K: op->type = R_ANAL_OP_TYPE_MUL; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,*=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,*="); } break; case BPF_ALU_DIV | BPF_X: case BPF_ALU_DIV | BPF_K: op->type = R_ANAL_OP_TYPE_DIV; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); if (f->k == 0) { esilprintf (op, "0,R0,=,0,$"); } else { esilprintf (op, "%" PFMT64d ",A,/=", f->k); } } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "0,X,==,$z,?{,0,R0,=,0,$,BREAK,},X,A,/="); } break; case BPF_ALU_MOD | BPF_X: case BPF_ALU_MOD | BPF_K: op->type = R_ANAL_OP_TYPE_MOD; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); if (f->k == 0) { esilprintf (op, "0,R0,=,0,$"); } else { esilprintf (op, "%" PFMT64d ",A,%%=", f->k); } } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "0,X,==,$z,?{,0,R0,=,0,$,BREAK,},X,A,%%="); } break; case BPF_ALU_AND | BPF_X: case BPF_ALU_AND | BPF_K: op->type = R_ANAL_OP_TYPE_AND; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,&=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,&="); } break; case BPF_ALU_OR | BPF_X: case BPF_ALU_OR | BPF_K: op->type = R_ANAL_OP_TYPE_OR; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,|=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,|,A,="); } break; case BPF_ALU_XOR | BPF_X: case BPF_ALU_XOR | BPF_K: op->type = R_ANAL_OP_TYPE_XOR; if (BPF_SRC (f->code) == BPF_K) { op->val = f->k; SET_REG_DST_IMM (op, "A", f->k); esilprintf (op, "%" PFMT64d ",A,^=", f->k); } else { SET_REG_SRC_DST (op, "X", "A"); esilprintf (op, "X,A,^="); } break; default: op->type = R_ANAL_OP_TYPE_ILL; break; } return op->size; }