コード例 #1
0
ファイル: SafeDispatchFix.cpp プロジェクト: UCSD-PL/ivt
bool SDFix::fixDestructors2() {
  bool replaced = false;

  for (GlobalVariable& gv : module->getGlobalList()) {
    if (! sd_isVtableName_ref(gv.getName()))
      continue;
    else if (! gv.hasInitializer())
      continue;

    Constant* init = gv.getInitializer();
    assert(init);
    ConstantArray* vtable = dyn_cast<ConstantArray>(init);
    assert(vtable);

    for(unsigned i=0; i<vtable->getNumOperands(); i++) {
      Constant* destructor = sd_getDestructorFunction(vtable->getOperand(i));

      if (destructor == NULL)
        continue;

      // get the type from its name
      unsigned s = destructor->getName().size();
      char type = destructor->getName()[s-3];
      assert('0' <= type && type <= '2');
      unsigned typeInt = type - '0';

      DestructorInfo di(destructor, i);

      if(di.isDefined)
        continue;

      // this only handles the 1 -> 2 conversion
      assert(typeInt == 1);

      Function* f1 = di.getFunction();
      assert(f1);
      std::string gv2Name = f1->getName();
      unsigned l = gv2Name.length();
      gv2Name = gv2Name.replace(l-3, 1, "2");

      Function* f2 = module->getFunction(gv2Name);
      assert(f2 && ! f2->isDeclaration());

      sd_print("Replacing %s with %s inside %s\n",
               f1->getName().data(),
               gv2Name.c_str(),
               gv.getName().data());

      f1->replaceAllUsesWith(f2);
      replaced = true;

    }
  }

  return replaced;
}
コード例 #2
0
ファイル: SafeDispatchFix.cpp プロジェクト: UCSD-PL/ivt
static Constant*
sd_getDestructorFunction(Constant* vtblElement) {
  ConstantExpr* bcExpr = NULL;

  // if this a constant bitcast expression, this might be a vthunk
  if ((bcExpr = dyn_cast<ConstantExpr>(vtblElement)) && bcExpr->getOpcode() == BITCAST_OPCODE) {
    Constant* operand = bcExpr->getOperand(0);

    // this is a vthunk
    if (sd_isDestructorName(operand->getName())) {
      return operand;
    }
  }

  return NULL;
}
コード例 #3
0
ファイル: SafeDispatchFix.cpp プロジェクト: UCSD-PL/ivt
static Constant*
sd_isRTTI(Constant* vtblElement) {
  ConstantExpr* bcExpr = NULL;

  // if this a constant bitcast expression, this might be a vthunk
  if ((bcExpr = dyn_cast<ConstantExpr>(vtblElement)) &&
      bcExpr->getOpcode() == Instruction::BitCast) {
    Constant* operand = bcExpr->getOperand(0);

    // this is a vthunk
    if (operand->getName().startswith("_ZTI")) {
      return operand;
    }
  }

  return NULL;
}
コード例 #4
0
ファイル: SafeDispatchFix.cpp プロジェクト: UCSD-PL/ivt
bool SDFix::fixDestructors() {
  bool replaced = false;

  for (GlobalVariable& gv : module->getGlobalList()) {
    if (! sd_isVtableName_ref(gv.getName()))
      continue;
    else if (! gv.hasInitializer())
      continue;

    Constant* init = gv.getInitializer();
    assert(init);
    ConstantArray* vtable = dyn_cast<ConstantArray>(init);
    assert(vtable);

    // get an idea about the virtual function regions
    std::vector<vtbl_pair_t> vtblRegions = findSubVtables(vtable);

    // for each subvtable
    for(unsigned vtblInd = 0; vtblInd < vtblRegions.size(); vtblInd++) {
      // record the destructors used in the vtable
      std::vector<DestructorInfo> destructors(3);

      vtbl_pair_t p = vtblRegions[vtblInd];

      for(unsigned i=p.first; i<p.second; i++) {
        Constant* destructor = sd_getDestructorFunction(vtable->getOperand(i));

        if (destructor == NULL)
          continue;

        // get the type from its name
        unsigned s = destructor->getName().size();
        char type = destructor->getName()[s-3];
        assert('0' <= type && type <= '2');
        unsigned typeInt = type - '0';

        // store it temporarily
        destructors[typeInt] = DestructorInfo(destructor, i);
      }

      // deleting destructor should always be defined
      assert(! destructors[0].needsReplacement());

      DestructorInfo* d1 = &destructors[1];
      DestructorInfo* d2 = &destructors[2];

      // only one of the rest could be undefined
      assert(! d1->needsReplacement() || ! d2->needsReplacement());

      // if complete object destructor is missing...
      if (d1->needsReplacement()) {
        std::string gv2Name = d1->function->getName();
        unsigned l = gv2Name.length();
        gv2Name = gv2Name.replace(l-3, 1, "2");

        Function* f1 = d1->getFunction();
        assert(f1);
        Function* f2 = module->getFunction(gv2Name);
        assert(f2);

        sd_print("Replacing %s with %s inside %s\n",
                 d1->function->getName().data(),
                 gv2Name.c_str(),
                 gv.getName().data());

        f1->replaceAllUsesWith(f2);
        replaced = true;

      // if base object destructor is missing...
      } else if (d2->needsReplacement()) {
        std::string gv1Name = d2->function->getName();
        unsigned l = gv1Name.length();
        gv1Name = gv1Name.replace(l-3, 1, "1");

        Function* f2 = d2->getFunction();
        assert(f2);
        Function* f1 = module->getFunction(gv1Name);
        assert(f1);

        sd_print("Replacing %s with %s inside %s\n",
                 d2->function->getName().data(),
                 gv1Name.c_str(),
                 gv.getName().data());

        f2->replaceAllUsesWith(f1);
        replaced = true;
      }
    }
  }

  return replaced;
}