Hi all,<br><br>Sorry for the inconvenient about the previous post. The files were not attached. So I put them here again.<br><br>I am a newbie in LLVM and I am trying to replace the function like:<br><br>old function || new function<br>
==============================<div id=":r">=========<br><div>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><br><br>Thank you in advance.<br>Shawn.<br><br><br>duplicateFunction.cpp<br>=============================================================================<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> }; /* 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> 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><br> // set the calling convention to C.<br>
// so, we interoperate with C Code properly.<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 0<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>}<br><br><br>test.c<br>====================================================================================<br>#include <stdio.h><br>
#include <stdlib.h><br><br>int v[200];<br>int haha(int);<br><br>int main()<br>{<br> int i;<br> int n=100;<br><br> if ( !haha(n) )<br> exit(-1);<br><br> return 1;<br>}<br><br>int haha(int n)<br>//int haha(int n, char* IOCallIDs)<br>
{<br> int i;<br> for (i=1; i<n; i++)<br> v[i] = v[i-1] + v[i];<br><br> printf ("hahaha\n");<br> return 1;<br>}<br><br>Makefile<br>
====================================================================================<br>LLVM_CONFIG?=llvm-config<br><br># location of the source<br># useful if you want separate source and object directories.<br>SRC_DIR?=$(PWD)<br>
<br>#ifndef VERBOSE<br># QUIET:=@<br>#endif<br><br>COMMON_FLAGS=-Wall -Wextra #-fvisibility=hidden<br>CFLAGS+=$(COMMON_FLAGS) $(shell $(LLVM_CONFIG) --cflags)<br>CXXFLAGS+=$(COMMON_FLAGS) $(shell $(LLVM_CONFIG) --cxxflags)<br>
<br>#ifeq ($(shell uname),Darwin)<br>#LOADABLE_MODULE_OPTIONS=-bundle -undefined dynamic_lookup<br>#else<br>LOADABLE_MODULE_OPTIONS=-shared -Wl,-O1<br>#endif<br><br>TEST_C=test.c<br>TEST_FILE=$(subst .c,.s, $(TEST_C))<br>
PLUGIN=duplicateFunction.so<br>PLUGIN_OBJECTS=duplicateFunction.o <br><br>ALL_OBJECTS=$(PLUGIN_OBJECTS)<br>ALL_TARGETS=$(PLUGIN) $(TEST_FILE)<br><br>CPP_OPTIONS+=$(CPPFLAGS) $(shell $(LLVM_CONFIG) --cppflags) -MD -MP -I$(SRC_DIR)<br>
<br>LD_OPTIONS+=$(LDFLAGS) $(shell $(LLVM_CONFIG) --ldflags)<br><br>all: $(ALL_TARGETS)<br><br>%.o : $(SRC_DIR)/%.cpp<br> @echo Compiling $*.cpp<br> $(QUIET)$(CXX) -c $(CPP_OPTIONS) $(CXXFLAGS) $<<br><br>$(PLUGIN): $(PLUGIN_OBJECTS)<br>
@echo Linking $@<br> $(QUIET)$(CXX) -o $@ $(LOADABLE_MODULE_OPTIONS) $(CXXFLAGS) $(LD_OPTIONS) $(PLUGIN_OBJECTS)<br><br>RUN_FLAGS=-duplicateFunction<br><br>$(TEST_FILE): $(TEST_C)<br> clang -g -O3 -S -emit-llvm $^<br>
# clang -g -O0 -S -emit-llvm $^<br># clang -O0 -S -emit-llvm $^<br>run: <br> opt -load ./$(PLUGIN) $(RUN_FLAGS) < $(TEST_FILE) > /dev/null 2> after.s<br># opt -load ./$(PLUGIN) $(RUN_FLAGS) < $(TEST_FILE) > /dev/null<br>
<br>clean:<br> $(QUIET)rm -f $(ALL_OBJECTS) *.d $(PLUGIN) $(TEST_FILE)<br><br><br>-include $(ALL_OBJECTS:.o=.d)<br><br><br><br><br>
<br></div></div></div>