Commit 30bb737a authored by Matt Morehouse's avatar Matt Morehouse
Browse files

[DFSan] Add __dfsan_cmp_callback.

Summary:
When -dfsan-event-callbacks is specified, insert a call to
__dfsan_cmp_callback on every CMP instruction.

Reviewers: vitalybuka, pcc, kcc

Reviewed By: kcc

Subscribers: hiraditya, #sanitizers, eugenis, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D75389
parent 2e4f5e62
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -57,6 +57,13 @@ void __dfsan_mem_transfer_callback(dfsan_label *Start, size_t Len) {
  fprintf(stderr, "Label %u copied to memory\n", Start[0]);
}

void __dfsan_cmp_callback(dfsan_label CombinedLabel) {
  if (!CombinedLabel)
    return;

  fprintf(stderr, "Label %u used for branching\n", CombinedLabel);
}

#else
// Compile this code with DFSan and -dfsan-event-callbacks to insert the
// callbacks.
@@ -82,12 +89,14 @@ int main(int Argc, char *Argv[]) {
  volatile int Sink = I;

  // CHECK: Label 1 loaded from memory
  // CHECK: Label 1 used for branching
  assert(Sink == 1);

  // CHECK: Label 2 stored to memory
  Sink = J;

  // CHECK: Label 2 loaded from memory
  // CHECK: Label 2 used for branching
  assert(Sink == 2);

  // CHECK: Label 2 loaded from memory
@@ -95,8 +104,12 @@ int main(int Argc, char *Argv[]) {
  Sink += I;

  // CHECK: Label 3 loaded from memory
  // CHECK: Label 3 used for branching
  assert(Sink == 3);

  // CHECK: Label 3 used for branching
  assert(I != J);

  LenArgv = strlen(Argv[1]);
  LabelArgv = dfsan_create_label("Argv", 0);
  dfsan_set_label(LabelArgv, Argv[1], LenArgv);
+26 −11
Original line number Diff line number Diff line
@@ -163,14 +163,15 @@ static cl::opt<bool> ClDebugNonzeroLabels(
    cl::Hidden);

// Experimental feature that inserts callbacks for certain data events.
// Currently callbacks are only inserted for loads, stores, and memory transfers
// (i.e. memcpy and memmove).
// Currently callbacks are only inserted for loads, stores, memory transfers
// (i.e. memcpy and memmove), and comparisons.
//
// If this flag is set to true, the user must provide definitions for the
// following callback functions:
//   void __dfsan_load_callback(dfsan_label Label);
//   void __dfsan_store_callback(dfsan_label Label);
//   void __dfsan_mem_transfer_callback(dfsan_label *Start, size_t Len);
//   void __dfsan_cmp_callback(dfsan_label CombinedLabel);
static cl::opt<bool> ClEventCallbacks(
    "dfsan-event-callbacks",
    cl::desc("Insert calls to __dfsan_*_callback functions on data events."),
@@ -359,7 +360,7 @@ class DataFlowSanitizer : public ModulePass {
  FunctionType *DFSanSetLabelFnTy;
  FunctionType *DFSanNonzeroLabelFnTy;
  FunctionType *DFSanVarargWrapperFnTy;
  FunctionType *DFSanLoadStoreCallbackFnTy;
  FunctionType *DFSanLoadStoreCmpCallbackFnTy;
  FunctionType *DFSanMemTransferCallbackFnTy;
  FunctionCallee DFSanUnionFn;
  FunctionCallee DFSanCheckedUnionFn;
@@ -371,6 +372,7 @@ class DataFlowSanitizer : public ModulePass {
  FunctionCallee DFSanLoadCallbackFn;
  FunctionCallee DFSanStoreCallbackFn;
  FunctionCallee DFSanMemTransferCallbackFn;
  FunctionCallee DFSanCmpCallbackFn;
  MDNode *ColdCallWeights;
  DFSanABIList ABIList;
  DenseMap<Value *, Function *> UnwrappedFnMap;
@@ -457,7 +459,10 @@ public:
    return DFSF.F->getParent()->getDataLayout();
  }

  void visitOperandShadowInst(Instruction &I);
  // Combines shadow values for all of I's operands. Returns the combined shadow
  // value.
  Value *visitOperandShadowInst(Instruction &I);

  void visitUnaryOperator(UnaryOperator &UO);
  void visitBinaryOperator(BinaryOperator &BO);
  void visitCastInst(CastInst &CI);
@@ -602,7 +607,7 @@ bool DataFlowSanitizer::doInitialization(Module &M) {
      Type::getVoidTy(*Ctx), None, /*isVarArg=*/false);
  DFSanVarargWrapperFnTy = FunctionType::get(
      Type::getVoidTy(*Ctx), Type::getInt8PtrTy(*Ctx), /*isVarArg=*/false);
  DFSanLoadStoreCallbackFnTy =
  DFSanLoadStoreCmpCallbackFnTy =
      FunctionType::get(Type::getVoidTy(*Ctx), ShadowTy, /*isVarArg=*/false);
  Type *DFSanMemTransferCallbackArgs[2] = {ShadowPtrTy, IntptrTy};
  DFSanMemTransferCallbackFnTy =
@@ -809,11 +814,13 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
                                                  DFSanVarargWrapperFnTy);

  DFSanLoadCallbackFn = Mod->getOrInsertFunction("__dfsan_load_callback",
                                                 DFSanLoadStoreCallbackFnTy);
  DFSanStoreCallbackFn = Mod->getOrInsertFunction("__dfsan_store_callback",
                                                  DFSanLoadStoreCallbackFnTy);
                                                 DFSanLoadStoreCmpCallbackFnTy);
  DFSanStoreCallbackFn = Mod->getOrInsertFunction(
      "__dfsan_store_callback", DFSanLoadStoreCmpCallbackFnTy);
  DFSanMemTransferCallbackFn = Mod->getOrInsertFunction(
      "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
  DFSanCmpCallbackFn = Mod->getOrInsertFunction("__dfsan_cmp_callback",
                                                DFSanLoadStoreCmpCallbackFnTy);

  std::vector<Function *> FnsToInstrument;
  SmallPtrSet<Function *, 2> FnsWithNativeABI;
@@ -828,7 +835,8 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
        &i != DFSanVarargWrapperFn.getCallee()->stripPointerCasts() &&
        &i != DFSanLoadCallbackFn.getCallee()->stripPointerCasts() &&
        &i != DFSanStoreCallbackFn.getCallee()->stripPointerCasts() &&
        &i != DFSanMemTransferCallbackFn.getCallee()->stripPointerCasts())
        &i != DFSanMemTransferCallbackFn.getCallee()->stripPointerCasts() &&
        &i != DFSanCmpCallbackFn.getCallee()->stripPointerCasts())
      FnsToInstrument.push_back(&i);
  }

@@ -1212,9 +1220,10 @@ Value *DFSanFunction::combineOperandShadows(Instruction *Inst) {
  return Shadow;
}

void DFSanVisitor::visitOperandShadowInst(Instruction &I) {
Value *DFSanVisitor::visitOperandShadowInst(Instruction &I) {
  Value *CombinedShadow = DFSF.combineOperandShadows(&I);
  DFSF.setShadow(&I, CombinedShadow);
  return CombinedShadow;
}

// Generates IR to load shadow corresponding to bytes [Addr, Addr+Size), where
@@ -1451,7 +1460,13 @@ void DFSanVisitor::visitBinaryOperator(BinaryOperator &BO) {

void DFSanVisitor::visitCastInst(CastInst &CI) { visitOperandShadowInst(CI); }

void DFSanVisitor::visitCmpInst(CmpInst &CI) { visitOperandShadowInst(CI); }
void DFSanVisitor::visitCmpInst(CmpInst &CI) {
  Value *CombinedShadow = visitOperandShadowInst(CI);
  if (ClEventCallbacks) {
    IRBuilder<> IRB(&CI);
    IRB.CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
  }
}

void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
  visitOperandShadowInst(GEPI);