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>