Exemple #1
0
bool FuncAddrTaken::runOnModule(Module &M) {
  bool Changed = false;
  // add declaration of function __patch_at
  // declare void @__patch_at(void)
  FunctionType *FT = FunctionType::get(Type::getVoidTy(M.getContext()),
                                       false);
  Function* PatchAt = Function::Create(FT, Function::ExternalLinkage, "__patch_at", &M);
  if (PatchAt->getName() != "__patch_at") {
    PatchAt->eraseFromParent();
    return false;
  }
  Changed = true;

  // Simple optimization so that no function address will be taken twice
  // in the same basic block.
  std::map<BasicBlock*, std::set<std::string> > UniqPatchAt;

  // before each store instruction that manipulates a function, create a call
  // to __patch_at
  for (auto F = M.getFunctionList().begin(); F != M.getFunctionList().end(); F++) {
    for (auto BB = F->begin(); BB != F->end(); BB++) {
      for (auto MI = BB->begin(); MI != BB->end(); MI++) {
        if (isa<StoreInst>(MI)) {
          // check if the store inst moves a function to a variable
          Value *V = InnerMost(cast<StoreInst>(MI)->getValueOperand());
          addPatchAt(M, FT, V, MI, UniqPatchAt);
          if (isa<ConstantVector>(V)) {
            std::set<Value*> patched;
            for (unsigned i = 0; i < cast<ConstantVector>(V)->getNumOperands(); i++) {
              Value *VV = InnerMost(cast<ConstantVector>(V)->getOperand(i));
              if (patched.find(VV) == patched.end()) {
                addPatchAt(M, FT, VV, MI, UniqPatchAt);
                patched.insert(VV);
              }
            }
          } else if (isa<ConstantStruct>(V)) {
            std::set<Value*> patched;
            for (unsigned i = 0; i < cast<ConstantStruct>(V)->getNumOperands(); i++) {
              Value *VV = InnerMost(cast<ConstantStruct>(V)->getOperand(i));
              if (patched.find(VV) == patched.end()) {
                addPatchAt(M, FT, VV, MI, UniqPatchAt);
                patched.insert(VV);
              }
            }
          } else if (isa<ConstantArray>(V)) {
            std::set<Value*> patched;
            for (unsigned i = 0; i < cast<ConstantArray>(V)->getNumOperands(); i++) {
              Value *VV = InnerMost(cast<ConstantArray>(V)->getOperand(i));
              if (patched.find(VV) == patched.end()) {
                addPatchAt(M, FT, VV, MI, UniqPatchAt);
                patched.insert(VV);
              }
            }
          }
        } else if (isa<SelectInst>(MI)) {
          Value *V = InnerMost(cast<SelectInst>(MI)->getTrueValue());
          addPatchAt(M, FT, V, MI, UniqPatchAt);
          V = InnerMost(cast<SelectInst>(MI)->getFalseValue());
          addPatchAt(M, FT, V, MI, UniqPatchAt);
        } else if (isa<CallInst>(MI)) {
          CallInst* CI = cast<CallInst>(MI);
          for (unsigned i = 0; i < CI->getNumArgOperands(); i++) {
            Value *V = InnerMost(CI->getArgOperand(i));
            addPatchAt(M, FT, V, MI, UniqPatchAt);
          }
        } else if (isa<InvokeInst>(MI)) {
          InvokeInst* CI = cast<InvokeInst>(MI);
          for (unsigned i = 0; i < CI->getNumArgOperands(); i++) {
            Value *V = InnerMost(CI->getArgOperand(i));
            addPatchAt(M, FT, V, MI, UniqPatchAt);
          }
        } else if (isa<ReturnInst>(MI)) {
          Value *V = cast<ReturnInst>(MI)->getReturnValue();
          if (V) {
            V = InnerMost(V);
            addPatchAt(M, FT, V, MI, UniqPatchAt);
          }
        } else if (isa<PHINode>(MI)) {
          for (unsigned i = 0; i < cast<PHINode>(MI)->getNumIncomingValues(); i++) {
            Value *V = InnerMost(cast<PHINode>(MI)->getIncomingValue(i));
            BasicBlock* BB = cast<PHINode>(MI)->getIncomingBlock(i);
            // right before the last (maybe terminator) instruction.
            addPatchAt(M, FT, V, &(BB->back()), UniqPatchAt);
          }
        }
      }
    }
  }

  // TODO: separate the following virtual table traversal code into another pass
  for (auto G = M.getGlobalList().begin(); G != M.getGlobalList().end(); G++) {
    if (isa<GlobalVariable>(G) &&
        cast<GlobalVariable>(G)->hasInitializer()) {
      const GlobalVariable *GV = cast<GlobalVariable>(G);
      const Constant *C = GV->getInitializer();
      if (GV->hasName() && isa<ConstantArray>(C) && GV->getName().startswith("_ZTV")) {
        std::string VTName = CXXDemangledName(GV->getName().data());
        if (VTName.size() && VTName.find("vtable") == 0) {
          //llvm::errs() << VTName << "\n";
          VTName = VTName.substr(11); // get pass "vtable for "
          llvm::NamedMDNode* MD = M.getOrInsertNamedMetadata("MCFIVtable");
          std::string info = VTName;
          for (unsigned i = 0; i < cast<ConstantArray>(C)->getNumOperands(); i++) {
            Value *V = InnerMost(cast<ConstantArray>(C)->getOperand(i));
            if (isa<Function>(V) && cast<Function>(V)->hasName()) {
              //llvm::errs() << cast<Function>(V)->getName() << "\n";
              info += std::string("#") + cast<Function>(V)->getName().str();
            }
          }
          MD->addOperand(llvm::MDNode::get(M.getContext(),
                                           llvm::MDString::get(
                                             M.getContext(), info.c_str())));
        }
      }
    }
  }
  return Changed;
}
Exemple #2
0
void AAAnalyzer::handle_inst(Instruction *inst, FunctionWrapper * parent_func) {
    //outs()<<*inst<<"\n"; outs().flush();
    switch (inst->getOpcode()) {
            // common/bitwise binary operations
            // Terminator instructions
        case Instruction::Ret:
        {
            ReturnInst* retInst = ((ReturnInst*) inst);
            if (retInst->getNumOperands() > 0 && !retInst->getOperandUse(0)->getType()->isVoidTy()) {
                parent_func->addRet(retInst->getOperandUse(0));
            }
        }
            break;
        case Instruction::Resume:
        {
            Value* resume = ((ResumeInst*) inst)->getOperand(0);
            parent_func->addResume(resume);
        }
            break;
        case Instruction::Switch:
        case Instruction::Br:
        case Instruction::IndirectBr:
        case Instruction::Unreachable:
            break;

            // vector operations
        case Instruction::ExtractElement:
        {
        }
            break;
        case Instruction::InsertElement:
        {
        }
            break;
        case Instruction::ShuffleVector:
        {
        }
            break;

            // aggregate operations
        case Instruction::ExtractValue:
        {
            Value * agg = ((ExtractValueInst*) inst)->getAggregateOperand();
            DyckVertex* aggV = wrapValue(agg);

            Type* aggTy = agg->getType();

            ArrayRef<unsigned> indices = ((ExtractValueInst*) inst)->getIndices();
            DyckVertex* currentStruct = aggV;

            for (unsigned int i = 0; i < indices.size(); i++) {
                if (isa<CompositeType>(aggTy) && aggTy->isSized()) {
                    if (!aggTy->isStructTy()) {
                        aggTy = ((CompositeType*) aggTy)->getTypeAtIndex(indices[i]);
#ifndef ARRAY_SIMPLIFIED
                        current = addPtrOffset(current, (int) indices[i] * dl.getTypeAllocSize(aggTy), dgraph);
#endif
                        if (i == indices.size() - 1) {
                            this->makeAlias(currentStruct, wrapValue(inst));
                        }
                    } else {
                        aggTy = ((CompositeType*) aggTy)->getTypeAtIndex(indices[i]);

                        if (i != indices.size() - 1) {
                            currentStruct = this->addField(currentStruct, -2 - (int) indices[i], NULL);
                        } else {
                            currentStruct = this->addField(currentStruct, -2 - (int) indices[i], wrapValue(inst));
                        }
                    }
                } else {
                    break;
                }
            }
        }
            break;
        case Instruction::InsertValue:
        {
            DyckVertex* resultV = wrapValue(inst);
            Value * agg = ((InsertValueInst*) inst)->getAggregateOperand();
            if (!isa<UndefValue>(agg)) {
                makeAlias(resultV, wrapValue(agg));
            }

            Value * val = ((InsertValueInst*) inst)->getInsertedValueOperand();
            DyckVertex* insertedVal = wrapValue(val);

            Type *aggTy = inst->getType();

            ArrayRef<unsigned> indices = ((InsertValueInst*) inst)->getIndices();

            DyckVertex* currentStruct = resultV;

            for (unsigned int i = 0; i < indices.size(); i++) {
                if (isa<CompositeType>(aggTy) && aggTy->isSized()) {
                    if (!aggTy->isStructTy()) {
                        aggTy = ((CompositeType*) aggTy)->getTypeAtIndex(indices[i]);
#ifndef ARRAY_SIMPLIFIED
                        current = addPtrOffset(current, (int) indices[i] * dl.getTypeAllocSize(aggTy), dgraph);
#endif
                        if (i == indices.size() - 1) {
                            this->makeAlias(currentStruct, insertedVal);
                        }
                    } else {
                        aggTy = ((CompositeType*) aggTy)->getTypeAtIndex(indices[i]);

                        if (i != indices.size() - 1) {
                            currentStruct = this->addField(currentStruct, -2 - (int) indices[i], NULL);
                        } else {
                            currentStruct = this->addField(currentStruct, -2 - (int) indices[i], insertedVal);
                        }
                    }
                } else {
                    break;
                }
            }
        }
            break;

            // memory accessing and addressing operations
        case Instruction::Alloca:
        {
        }
            break;
        case Instruction::Fence:
        {
        }
            break;
        case Instruction::AtomicCmpXchg:
        {
            Value * retXchg = inst;
            Value * ptrXchg = inst->getOperand(0);
            Value * newXchg = inst->getOperand(2);
            addPtrTo(wrapValue(ptrXchg), wrapValue(retXchg));
            addPtrTo(wrapValue(ptrXchg), wrapValue(newXchg));
        }
            break;
        case Instruction::AtomicRMW:
        {
            Value * retRmw = inst;
            Value * ptrRmw = ((AtomicRMWInst*) inst)->getPointerOperand();
            addPtrTo(wrapValue(ptrRmw), wrapValue(retRmw));

            switch (((AtomicRMWInst*) inst)->getOperation()) {
                case AtomicRMWInst::Max:
                case AtomicRMWInst::Min:
                case AtomicRMWInst::UMax:
                case AtomicRMWInst::UMin:
                case AtomicRMWInst::Xchg:
                {
                    Value * newRmw = ((AtomicRMWInst*) inst)->getValOperand();
                    addPtrTo(wrapValue(ptrRmw), wrapValue(newRmw));
                }
                    break;
                default:
                    //others are binary ops like add/sub/...
                    ///@TODO
                    break;
            }
        }
            break;
        case Instruction::Load:
        {
            Value *lval = inst;
            Value *ladd = inst->getOperand(0);
            addPtrTo(wrapValue(ladd), wrapValue(lval));
        }
            break;
        case Instruction::Store:
        {
            Value * sval = inst->getOperand(0);
            Value * sadd = inst->getOperand(1);
            addPtrTo(wrapValue(sadd), wrapValue(sval));
        }
            break;
        case Instruction::GetElementPtr:
        {
            makeAlias(wrapValue(inst), handle_gep((GEPOperator*) inst));
        }
            break;

            // conversion operations
        case Instruction::Trunc:
        case Instruction::ZExt:
        case Instruction::SExt:
        case Instruction::FPTrunc:
        case Instruction::FPExt:
        case Instruction::FPToUI:
        case Instruction::FPToSI:
        case Instruction::UIToFP:
        case Instruction::SIToFP:
        case Instruction::BitCast:
        case Instruction::PtrToInt:
        case Instruction::IntToPtr:
        {
            Value * itpv = inst->getOperand(0);
            makeAlias(wrapValue(inst), wrapValue(itpv));
        }
            break;

            // other operations
        case Instruction::Invoke: // invoke is a terminal operation
        {
            InvokeInst * invoke = (InvokeInst*) inst;
            LandingPadInst* lpd = invoke->getLandingPadInst();
            parent_func->addLandingPad(invoke, lpd);

            Value * cv = invoke->getCalledValue();
            vector<Value*> args;
            for (unsigned i = 0; i < invoke->getNumArgOperands(); i++) {
                args.push_back(invoke->getArgOperand(i));
            }

            this->handle_invoke_call_inst(invoke, cv, &args, parent_func);
        }
            break;
        case Instruction::Call:
        {
            CallInst * callinst = (CallInst*) inst;

            if (callinst->isInlineAsm()) {
                break;
            }

            Value * cv = callinst->getCalledValue();
            vector<Value*> args;
            for (unsigned i = 0; i < callinst->getNumArgOperands(); i++) {
                args.push_back(callinst->getArgOperand(i));
            }

            this->handle_invoke_call_inst(callinst, cv, &args, parent_func);
        }
            break;
        case Instruction::PHI:
        {
            PHINode *phi = (PHINode *) inst;
            int nums = phi->getNumIncomingValues();
            for (int i = 0; i < nums; i++) {
                Value * p = phi->getIncomingValue(i);
                makeAlias(wrapValue(inst), wrapValue(p));
            }
        }
            break;
        case Instruction::Select:
        {
            Value *first = ((SelectInst*) inst)->getTrueValue();
            Value *second = ((SelectInst*) inst)->getFalseValue();
            makeAlias(wrapValue(inst), wrapValue(first));
            makeAlias(wrapValue(inst), wrapValue(second));
        }
            break;
        case Instruction::VAArg:
        {
            parent_func->addVAArg(inst);

            DyckVertex* vaarg = wrapValue(inst);
            Value * ptrVaarg = inst->getOperand(0);
            addPtrTo(wrapValue(ptrVaarg), vaarg);
        }
            break;
        case Instruction::LandingPad: // handled with invoke inst
        case Instruction::ICmp:
        case Instruction::FCmp:
        default:
            break;
    }
}