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