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); }
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); }
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); }