Hi all,<br><br>I am a newbie in LLVM and I am trying to replace the function like:<br><br>old function || new function<br>=======================================<br><div id=":s">int haha(int a) { int haha(int a, char* ID) {<br>
<br> ===> <br>
<br><br>} } <br><div><br>Of course in the newly replaced function "int haha(int, char*ID)", I want to insert some instrumentation code.<br><br>
Here is my code that I am working on till now and it generates segmentation fault in the place I comment with "//////////////////////"<br>
Can you help me? Any advice will be helpful because I am a beginner in llvm.<br>dulpicateFunction.cpp, test.c, and Make file are attached.<br><br>Thank you in advance.<br>Shawn.<br><br>//===- duplicateFunction.cpp - Writing an LLVM Pass -----------------------===//<br>
//<br>// The LLVM Compiler Infrastructure<br>//<br>//===----------------------------------------------------------------------===//<br>//<br>// This file implements the LLVM duplicating function pass.<br>
// It starts by computing a new prototype for the function,<br>// which is the same as the old function, but has an extra argument.<br>//<br>//===----------------------------------------------------------------------===//<br>
#include "llvm/Transforms/Utils/Cloning.h"<br>#include "llvm/Pass.h"<br>#include "llvm/Function.h"<br>#include "llvm/Module.h"<br>#include "llvm/CallingConv.h"<br>#include "llvm/DerivedTypes.h"<br>
#include "llvm/InstrTypes.h"<br>#include "llvm/Constants.h"<br>#include "llvm/Instructions.h"<br>#include "llvm/Support/raw_ostream.h"<br>#include "llvm/Transforms/Utils/BasicBlockUtils.h"<br>
#include "llvm/BasicBlock.h"<br>#include "llvm/Support/Debug.h"<br>#include "llvm/Support/CallSite.h"<br>using namespace llvm;<br><br>namespace {<br> Constant *f;<br> Function *Fn;<br>
FunctionType *FTy;<br>
Type *RetTy;<br> std::vector<Type*> Params;<br> class DP : public FunctionPass {<br><br> public:<br> static char ID;<br><br> DP() : FunctionPass(ID) {}<br><br> virtual bool doInitialization(Module &M);<br>
virtual bool runOnFunction(Function &F);<br> virtual bool doFinalization(Module &mdl) {<br> mdl.dump();<br> return true;<br> }<br> <br>#if 0<br> // optimization passes should implement the following function to be efficient. <br>
virtual void getAnalysisUsage(AnalysisUsage &AU) const {<br> FunctionPass::getAnalysisUsage(AU);<br> AU.setPreservesAll();<br> AU.addRequired<AliasAnalysis>();<br> }<br>
#endif<br> }; /* class */<br>}<br><br>char DP::ID = 0;<br>static RegisterPass<DP> IC("duplicateFunction", "Duplicate Function Pass");<br><br><br>bool DP::doInitialization(Module &M) {<br>
<br>
// find the function that we want to change.<br> // f = M.getFunction("haha");<br> // <br> Fn = M.getFunction("haha");<br> <br> // Start by computing a new prototype for the function, which is the same as<br>
// the old function, but has an extra argument.<br> FTy = Fn->getFunctionType();<br><br> // Find out the return value.<br> RetTy = FTy->getReturnType();<br>#if 0 <br> if (Fn->getName() == "haha") {<br>
f = M.getOrInsertFunction("ShawnFunction",<br> /* return type */ Type::getVoidTy(M.getContext()),<br> /* actual 1 type */ IntegerType::get(M.getContext(), 32),<br> NULL);<br>
} <br> if ( !f ) {<br> errs() << "### Error: No matched function\n";<br> }<br>#endif<br>#if 0<br> // f = M.getOrInsertFunction(StringRef Name, FunctionType *T, AttrListPtr AttributeList);<br>
#endif<br><br> // set the calling convention to C.<br> // so, we interoperate with C Code properly.<br> // Function *tmp = cast<Function>(f);<br> // tmp->setCallingConv(CallingConv::C);<br> Function *tmp = cast<Function>(Fn);<br>
tmp->setCallingConv(CallingConv::C);<br><br> return true;<br>}<br><br>bool DP::runOnFunction(Function &F) {<br>#if 1<br> Value *param;<br> <br> // Find the instruction before which you want to insert the function call<br>
Instruction *nextInstr = F.back().getTerminator();<br> <br> // Create the actual parameter for the function call<br> param = ConstantInt::get(Type::getInt32Ty(F.getContext()), 333);<br> <br> // create and insert the function call<br>
//CallInst::Create(f, param, "", nextInstr);<br> CallInst::Create(Fn, param, "", nextInstr);<br><br> // indicates that we changed the code<br> //return true;<br>#endif<br> Type *NRetTy;<br>
<br> std::vector<Type*> Params(FTy->param_begin(), FTy->param_end());<br> FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false);<br><br> // Create the new function body and insert it into the module...<br>
Function *NF = Function::Create(NFTy, Fn->getLinkage());<br> NF->copyAttributesFrom(Fn);<br> Fn->getParent()->getFunctionList().insert(Fn, NF);<br> NF->takeName(Fn);<br><br> for (Function::arg_iterator AI=F.arg_begin(), AE=F.arg_end(), NAI=NF->arg_begin();<br>
AI != AE; ++AI, ++NAI) {<br> NAI->takeName(AI);<br> }<br><br> // Since we have now create the new function, splice the body of the old<br> // function right into the new function, leaving the old rotting hulk of the<br>
// function empty.<br> NF->getBasicBlockList().splice(NF->begin(), F.getBasicBlockList());<br><br> llvm::Value *Globals = --NF->arg_end();<br> Globals->setName("IOCallIDs");<br><br> // Now, exploit all return instructions.<br>
for (Function::iterator BI = NF->begin(), BE = NF->end(); BI != BE; ++BI) {<br> if (ReturnInst *RI = llvm::dyn_cast<llvm::ReturnInst>(BI->getTerminator())) {<br> // Don't support functions that have multiple return values.<br>
assert(RI->getNumOperands() < 2);<br><br> // Insert a new load instruction to return.<br> ///////////////////////////////////////////////////////////////////////////////////// HERE, GENERATE ERROR<br>
/////////////////////////////////////////////////////////////////////////////////////<br>
Value *Load = new llvm::LoadInst(Globals, "globalsret", RI);<br> /////////////////////////////////////////////////////////////////////////////////////<br><div> </div> // Return type is void<br>
if ( RetTy->isVoidTy() ) {<br>// ReturnInst::Create(Load, 0, RI); // Return void<br>
ReturnInst::Create(F.getContext(), 0, RI); // Return void<br> RI->getParent()->getInstList().erase(RI);<br> } else {<br> // Start with an empty struct.<br> Value *Return = ConstantAggregateZero::get(NRetTy);<br>
DEBUG(errs() << "Return: " << *Return->getType() << '\n');<br><br> // Insert the original return value in field 0<br> Return = InsertValueInst::Create(Return, RI->getOperand(0), 0, "ret", RI);<br>
DEBUG(errs() << "Return: " << *Return->getType() << '\n');<br><br> // Insert the globals return value in field 1 <br> Return = InsertValueInst::Create(Return, Load, 1, "ret", RI); // <- maybe useless<br>
DEBUG(errs() << "Return: " << *Return->getType() << '\n');<br><br> // Update the return instruction<br> RI->setOperand(0, Return);<br>
}<br> } // if <br> } // for<br><br> // Replace all uses of the old arguments with the new arguments.<br> for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(), NI = NF->arg_begin();<br>
I != E; ++I, ++NI) {<br> I->replaceAllUsesWith(NI);<br> }<br><br>#if 1<br> // Replace all callers<br> while ( !F.use_empty() ) {<br> CallSite CS(F.use_back());<br> Instruction *Call = CS.getInstruction();<br>
// Function *CallingF = Call->getParent()->getParent();<br><br> // Get the global struct in our caller.<br> //Value* CallerGlobals = ModifyFunctionRecursive(CallingF).first;<br> Value* CallerGlobals = NULL; // <- This should be modified later.<br>
<br> // Copy the existing arguments<br> std::vector<Value*> Args;<br> Args.reserve(CS.arg_size());<br> CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();<br><br> // First, copy regular arguments<br>
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++AI) {<br> Args.push_back(*AI);<br> }<br> // Then, insert the new argument<br> Args.push_back(CallerGlobals);<br> // Lastly, copy any remaining varargs<br>
for (; AI != AE; ++AI) {<br> Args.push_back(*AI);<br> }<br><br> Instruction *New;<br> Instruction *Before = Call;<br> if ( InvokeInst *II = dyn_cast<InvokeInst>(Call) ) {<br>
New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args, "", Before);<br> cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());<br>// cast<InvokeInst>(New)->setParamAttrs(CS.getParamAttrs());<br>
cast<InvokeInst>(New)->setAttributes(CS.getAttributes());<br> } else {<br> New = CallInst::Create(NF, Args, "", Before);<br> cast<CallInst>(New)->setCallingConv(CS.getCallingConv());<br>
// cast<CallInst>(New)->setParamAttrs(CS.getParamAttrs());<br> cast<CallInst>(New)->setAttributes(CS.getAttributes());<br> if ( cast<CallInst>(Call)->isTailCall() ) {<br>
cast<CallInst>(New)->setTailCall();<br> }<br> }<br><br> if (Call->hasName()) {<br> New->takeName(Call);<br> } else { <br> New->setName(NF->getName() + ".ret");<br>
}<br><br> Value *GlobalsRet;<br> if ( Call->getType()->isVoidTy() ) {<br> // The original function returned nothing, so the new function returns<br> // only the globals<br>
GlobalsRet = New;<br> } else {<br> // Split the values<br> Value *OrigRet = ExtractValueInst::Create(New, 0, "origret", Before);<br> GlobalsRet = ExtractValueInst::Create(New, 1, "globalsret", Before);<br>
// Replace all the uses of the original result<br> Call->replaceAllUsesWith(OrigRet);<br> }<br> <br> // Now, store the globals back<br> new StoreInst(GlobalsRet, CallerGlobals, Before);<br>
<br> DEBUG(errs() << "Call " << *Call << "
replaced, function is now " <<
*Call->getParent()->getParent() << "\n");<br><br> // Finally, remove the old call from the program, reducing the use-count of F.<br>
Call->eraseFromParent();<br><br> } // while<br>#endif<br> return true;<br>}</div></div>