Ejemplo n.º 1
0
void taint_parallel_compute(
        FastShad *shad,
        uint64_t dest, uint64_t ignored,
        uint64_t src1, uint64_t src2, uint64_t src_size,
        llvm::Instruction *I) {
    uint64_t shad_size = shad->get_size();
    if (unlikely(dest >= shad_size || src1 >= shad_size || src2 >= shad_size)) {
        taint_log("  Ignoring IO RW\n");
        return;
    }

    taint_log("pcompute: %s[%lx+%lx] <- %lx + %lx\n",
            shad->name(), dest, src_size, src1, src2);
    uint64_t i;
    for (i = 0; i < src_size; ++i) {
        TaintData td = TaintData::make_union(
                shad->query_full(src1 + i),
                shad->query_full(src2 + i), true);
        shad->set_full(dest + i, td);
    }

    // Unlike mixed computes, parallel computes guaranteed to be bitwise.
    // This means we can honestly compute CB masks; in fact we have to because
    // of the way e.g. the deposit TCG op is lifted to LLVM.
    CBMasks cb_mask_1 = compile_cb_masks(shad, src1, src_size);
    CBMasks cb_mask_2 = compile_cb_masks(shad, src2, src_size);
    CBMasks cb_mask_out = {0};
    if (I && I->getOpcode() == llvm::Instruction::Or) {
        cb_mask_out.one_mask = cb_mask_1.one_mask | cb_mask_2.one_mask;
        cb_mask_out.zero_mask = cb_mask_1.zero_mask & cb_mask_2.zero_mask;
        // Anything that's a literal zero in one operand will not affect
        // the other operand, so those bits are still controllable.
        cb_mask_out.cb_mask =
            (cb_mask_1.zero_mask & cb_mask_2.cb_mask) |
            (cb_mask_2.zero_mask & cb_mask_1.cb_mask);
    } else if (I && I->getOpcode() == llvm::Instruction::And) {
        cb_mask_out.one_mask = cb_mask_1.one_mask & cb_mask_2.one_mask;
        cb_mask_out.zero_mask = cb_mask_1.zero_mask | cb_mask_2.zero_mask;
        // Anything that's a literal one in one operand will not affect
        // the other operand, so those bits are still controllable.
        cb_mask_out.cb_mask =
            (cb_mask_1.one_mask & cb_mask_2.cb_mask) |
            (cb_mask_2.one_mask & cb_mask_1.cb_mask);
    }
    taint_log("pcompute_cb: %#lx + %#lx = %lx ",
            cb_mask_1.cb_mask, cb_mask_2.cb_mask, cb_mask_out.cb_mask);
    taint_log_labels(shad, dest, src_size);
    write_cb_masks(shad, dest, src_size, cb_mask_out);
}
Ejemplo n.º 2
0
static void update_cb(
        FastShad *shad_dest, uint64_t dest,
        FastShad *shad_src, uint64_t src, uint64_t size,
        llvm::Instruction *I) {
    if (!I) return;

    CBMasks cb_masks = compile_cb_masks(shad_src, src, size);
    uint64_t &cb_mask = cb_masks.cb_mask;
    uint64_t &one_mask = cb_masks.one_mask;
    uint64_t &zero_mask = cb_masks.zero_mask;

    uint64_t orig_one_mask = one_mask, orig_zero_mask = zero_mask;
    __attribute__((unused)) uint64_t orig_cb_mask = cb_mask;
    std::vector<uint64_t> literals;
    uint64_t last_literal = ~0UL; // last valid literal.
    literals.reserve(I->getNumOperands());

    for (auto it = I->value_op_begin(); it != I->value_op_end(); it++) {
        const llvm::Value *arg = *it;
        const llvm::ConstantInt *CI = llvm::dyn_cast<llvm::ConstantInt>(arg);
        uint64_t literal = CI ? CI->getZExtValue() : ~0UL;
        literals.push_back(literal);
        if (literal != ~0UL) last_literal = literal;
    }
    int log2 = 0;

    switch (I->getOpcode()) {
        // Totally reversible cases.
        case llvm::Instruction::Sub:
            if (literals[1] == ~0UL) {
                tassert(last_literal != ~0UL);
                // first operand is a variable. so negate.
                // throw out ones/zeroes info.
                // FIXME: handle better.
                one_mask = zero_mask = 0;
                break;
            } // otherwise fall through.
        case llvm::Instruction::Add:
            tassert(last_literal != ~0UL);
            log2 = 64 - __builtin_clz(last_literal);
            // FIXME: this isn't quite right. for example, if all bits ones,
            // adding one makes all bits zero.
            one_mask &= ~((1 << log2) - 1);
            zero_mask &= ~((1 << log2) - 1);
            break;

        case llvm::Instruction::Xor:
            one_mask &= ~last_literal;
            one_mask |= last_literal & orig_zero_mask;
            zero_mask &= ~last_literal;
            zero_mask |= last_literal & orig_one_mask;
            break;

        case llvm::Instruction::ZExt:
        case llvm::Instruction::IntToPtr:
        case llvm::Instruction::PtrToInt:
        case llvm::Instruction::BitCast:
        // This one copies the existing bits and adds non-controllable bits.
        // One and zero masks too complicated to compute. Bah.
        case llvm::Instruction::SExt:
        // Copies. These we ignore (the copy will copy the CB data for us)
        case llvm::Instruction::Store:
        case llvm::Instruction::Load:
        case llvm::Instruction::ExtractValue:
        case llvm::Instruction::InsertValue:
            break;

        case llvm::Instruction::Trunc:
            cb_mask &= (1 << (size * 8)) - 1;
            one_mask &= (1 << (size * 8)) - 1;
            zero_mask &= (1 << (size * 8)) - 1;
            break;

        case llvm::Instruction::Mul:
        {
            tassert(last_literal != ~0UL);
            // Powers of two in last_literal destroy reversibility.
            uint64_t trailing_zeroes = __builtin_ctz(last_literal);
            cb_mask <<= trailing_zeroes;
            zero_mask = (1 << trailing_zeroes) - 1;
            one_mask = 0;
            break;
        }

        case llvm::Instruction::URem:
        case llvm::Instruction::SRem:
            tassert(last_literal != ~0UL);
            log2 = 64 - __builtin_clz(last_literal);
            cb_mask &= (1 << log2) - 1;
            one_mask = 0;
            zero_mask = 0;
            break;

        case llvm::Instruction::UDiv:
        case llvm::Instruction::SDiv:
            tassert(last_literal != ~0UL);
            log2 = 64 - __builtin_clz(last_literal);
            cb_mask >>= log2;
            one_mask = 0;
            zero_mask = 0;
            break;

        case llvm::Instruction::And:
            tassert(last_literal != ~0UL);
            // Bits not in the bit mask are no longer controllable
            cb_mask &= last_literal;
            zero_mask |= ~last_literal;
            one_mask &= last_literal;
            break;

        case llvm::Instruction::Or:
            tassert(last_literal != ~0UL);
            // Bits in the bit mask are no longer controllable
            cb_mask &= ~last_literal;
            one_mask |= last_literal;
            zero_mask &= ~last_literal;
            break;

        case llvm::Instruction::Shl:
            tassert(last_literal != ~0UL);
            cb_mask <<= last_literal;
            one_mask <<= last_literal;
            zero_mask <<= last_literal;
            zero_mask |= (1 << last_literal) - 1;
            break;

        case llvm::Instruction::LShr:
            tassert(last_literal != ~0UL);
            cb_mask >>= last_literal;
            one_mask >>= last_literal;
            zero_mask >>= last_literal;
            zero_mask |= ~((1 << (64 - last_literal)) - 1);
            break;

        case llvm::Instruction::AShr: // High bits not really controllable.
            tassert(last_literal != ~0UL);
            cb_mask >>= last_literal;
            one_mask >>= last_literal;
            zero_mask >>= last_literal;

            // See if high bit is a last_literal
            if (orig_one_mask & (1 << (size * 8 - 1))) {
                one_mask |= ~((1 << (64 - last_literal)) - 1);
            } else if (orig_zero_mask & (1 << (size * 8 - 1))) {
                zero_mask |= ~((1 << (64 - last_literal)) - 1);
            }
            break;

        // Totally irreversible cases. Erase and bail.
        case llvm::Instruction::FAdd:
        case llvm::Instruction::FSub:
        case llvm::Instruction::FMul:
        case llvm::Instruction::FDiv:
        case llvm::Instruction::FRem:
        case llvm::Instruction::Call:
        case llvm::Instruction::ICmp:
        case llvm::Instruction::FCmp:
            cb_mask = 0;
            one_mask = 0;
            zero_mask = 0;
            break;

        case llvm::Instruction::GetElementPtr:
        {
            llvm::GetElementPtrInst *GEPI =
                llvm::dyn_cast<llvm::GetElementPtrInst>(I);
            tassert(GEPI);
            one_mask = 0;
            zero_mask = 0;
            // Constant indices => fully reversible
            if (GEPI->hasAllConstantIndices()) break;
            // Otherwise we know nothing.
            cb_mask = 0;
            break;
        }

        default:
            printf("Unknown instruction in update_cb: ");
            I->dump();
            fflush(stdout);
            return;
    }

    taint_log("update_cb: %s[%lx+%lx] CB %#lx -> 0x%#lx, 0 %#lx -> %#lx, 1 %#lx -> %#lx\n",
            shad_dest->name(), dest, size, orig_cb_mask, cb_mask,
            orig_zero_mask, zero_mask, orig_one_mask, one_mask);

    write_cb_masks(shad_dest, dest, size, cb_masks);
}
Ejemplo n.º 3
0
static void update_cb(
        FastShad *shad_dest, uint64_t dest,
        FastShad *shad_src, uint64_t src, uint64_t size,
        llvm::Instruction *I) {
    if (!I) return;

    CBMasks cb_masks = compile_cb_masks(shad_src, src, size);
    uint64_t &cb_mask = cb_masks.cb_mask;
    uint64_t &one_mask = cb_masks.one_mask;
    uint64_t &zero_mask = cb_masks.zero_mask;

    uint64_t orig_one_mask = one_mask, orig_zero_mask = zero_mask;
    llvm::Value *rhs = I->getNumOperands() >= 2 ? I->getOperand(1) : nullptr;
    llvm::ConstantInt *CI = rhs ? llvm::dyn_cast<llvm::ConstantInt>(rhs) : nullptr;
    uint64_t literal = CI ? CI->getZExtValue() : ~0UL;
    int log2 = 0;

    switch (I->getOpcode()) {
        // Totally reversible cases.
        case llvm::Instruction::Add:
        case llvm::Instruction::Sub:
            tassert(literal != ~0UL);
            log2 = 64 - __builtin_clz(literal);
            one_mask &= ~((1 << log2) - 1);
            zero_mask &= ~((1 << log2) - 1);
            break;

        case llvm::Instruction::Xor:
            one_mask &= ~literal;
            one_mask |= literal & orig_zero_mask;
            zero_mask &= ~literal;
            zero_mask |= literal & orig_one_mask;
            break;

        case llvm::Instruction::ZExt:
        case llvm::Instruction::IntToPtr:
        case llvm::Instruction::PtrToInt:
        case llvm::Instruction::BitCast:
        // This one copies the existing bits and adds non-controllable bits.
        // One and zero masks too complicated to compute. Bah.
        case llvm::Instruction::SExt:
        // Copies. These we ignore (the copy will copy the CB data for us)
        case llvm::Instruction::Store:
        case llvm::Instruction::Load:
        case llvm::Instruction::ExtractValue:
        case llvm::Instruction::InsertValue:
            break;

        case llvm::Instruction::Trunc:
            cb_mask &= (1 << (size * 8)) - 1;
            one_mask &= (1 << (size * 8)) - 1;
            zero_mask &= (1 << (size * 8)) - 1;
            break;

        case llvm::Instruction::Mul:
        {
            tassert(literal != ~0UL);
            // Powers of two in literal destroy reversibility.
            uint64_t trailing_zeroes = __builtin_ctz(literal);
            cb_mask <<= trailing_zeroes;
            zero_mask = (1 << trailing_zeroes) - 1;
            one_mask = 0;
            break;
        }

        case llvm::Instruction::URem:
        case llvm::Instruction::SRem:
            tassert(literal != ~0UL);
            log2 = 64 - __builtin_clz(literal);
            cb_mask &= (1 << log2) - 1;
            one_mask = 0;
            zero_mask = 0;
            break;

        case llvm::Instruction::UDiv:
        case llvm::Instruction::SDiv:
            tassert(literal != ~0UL);
            log2 = 64 - __builtin_clz(literal);
            cb_mask >>= log2;
            one_mask = 0;
            zero_mask = 0;
            break;

        case llvm::Instruction::And:
            tassert(literal != ~0UL);
            // Bits not in the bit mask are no longer controllable
            cb_mask &= literal;
            zero_mask |= ~literal;
            one_mask &= literal;
            break;

        case llvm::Instruction::Or:
            tassert(literal != ~0UL);
            // Bits in the bit mask are no longer controllable
            cb_mask &= ~literal;
            one_mask |= literal;
            zero_mask &= ~literal;
            break;

        case llvm::Instruction::Shl:
            tassert(literal != ~0UL);
            cb_mask <<= literal;
            one_mask <<= literal;
            zero_mask <<= literal;
            zero_mask |= (1 << literal) - 1;
            break;

        case llvm::Instruction::LShr:
            tassert(literal != ~0UL);
            cb_mask >>= literal;
            one_mask >>= literal;
            zero_mask >>= literal;
            zero_mask |= ~((1 << (64 - literal)) - 1);
            break;

        case llvm::Instruction::AShr: // High bits not really controllable.
            tassert(literal != ~0UL);
            cb_mask >>= literal;
            one_mask >>= literal;
            zero_mask >>= literal;

            // See if high bit is a literal
            if (orig_one_mask & (1 << (size * 8 - 1))) {
                one_mask |= ~((1 << (64 - literal)) - 1);
            } else if (orig_zero_mask & (1 << (size * 8 - 1))) {
                zero_mask |= ~((1 << (64 - literal)) - 1);
            }
            break;

        // Totally irreversible cases. Erase and bail.
        case llvm::Instruction::FAdd:
        case llvm::Instruction::FSub:
        case llvm::Instruction::FMul:
        case llvm::Instruction::FDiv:
        case llvm::Instruction::FRem:
        case llvm::Instruction::Call:
        case llvm::Instruction::ICmp:
            cb_mask = 0;
            one_mask = 0;
            zero_mask = 0;
            break;

        case llvm::Instruction::GetElementPtr:
        {
            llvm::GetElementPtrInst *GEPI =
                llvm::dyn_cast<llvm::GetElementPtrInst>(I);
            tassert(GEPI);
            one_mask = 0;
            zero_mask = 0;
            // Constant indices => fully reversible
            if (GEPI->hasAllConstantIndices()) break;
            // Otherwise we know nothing.
            cb_mask = 0;
            break;
        }

        default:
            printf("Unknown instruction in update_cb: ");
            I->dump();
            fflush(stdout);
            return;
    }

    taint_log("update_cb: %s[%lx+%lx] CB %#lx -> 0x%#lx, 0 %#lx -> %#lx, 1 %#lx -> %#lx\n",
            shad_dest->name(), dest, size, orig_cb_mask, cb_mask,
            orig_zero_mask, zero_mask, orig_one_mask, one_mask);

    write_cb_masks(shad_dest, dest, size, cb_masks);
}