1 #ifndef MAGIC_DEBUG_FUNCTION_H_
2 #define MAGIC_DEBUG_FUNCTION_H_
3 
4 #include <pass.h>
5 
6 #define NUM_DEBUG_ARGS 1
7 
8 using namespace llvm;
9 
10 namespace llvm {
11 
12 class MagicDebugFunction {
13 public:
14 	MagicDebugFunction(Function *function);
15 
16 	Function* getFunction() const;
17 	void addHooks(std::pair<Function*, Function*> hooks, unsigned flags, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs);
18 	void fixCalls(Module &M, const std::string &baseDir="");
19 
20 	void print(raw_ostream &OS) const;
21 	void printDescription(raw_ostream &OS) const;
22 	const std::string getDescription() const;
23 	static bool inlineHookCalls(Function* function, std::pair<Function*, Function*> hooks, unsigned flags, std::vector<unsigned> argsMapping,
24 			std::vector<Value*> trailingArgs);
25 	Function* getDebugFunction(Module &M);
26 
27 private:
28 	Function *function;
29 
30 	std::pair<Function*, Function*> hooks;
31 	unsigned flags;
32 	std::vector<unsigned> argsMapping;
33 	std::vector<Value*> trailingArgs;
34 
35 	Function* getDebugClone(Function* function, const Twine wrapperName, TYPECONST Type* debugArgType);
36 };
37 
38 inline raw_ostream &operator<<(raw_ostream &OS, const MagicDebugFunction &aMagicDebugFunction) {
39 	aMagicDebugFunction.print(OS);
40 	return OS;
41 }
42 
43 inline void MagicDebugFunction::print(raw_ostream &OS) const {
44 	OS << getDescription();
45 }
46 
47 inline void MagicDebugFunction::printDescription(raw_ostream &OS) const {
48 	OS << "[ function = ";
49 	OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ") ]";
50 }
51 
52 inline const std::string MagicDebugFunction::getDescription() const {
53 	std::string string;
54 	raw_string_ostream ostream(string);
55 	printDescription(ostream);
56 	ostream.flush();
57 	return string;
58 }
59 
60 inline Function* MagicDebugFunction::getDebugClone(Function* function, const Twine wrapperName, TYPECONST Type* debugArgType) {
61 	Function* wrapper;
62 	std::vector<TYPECONST Type*> ArgTypes;
63 	VALUE_TO_VALUE_MAP_TY VMap;
64 
65 	// Build arg types for wrapper
66 	ArgTypes.push_back(debugArgType);
67 	Function::const_arg_iterator E = function->arg_end();
68 	for (Function::const_arg_iterator I = function->arg_begin(); I != E; ++I)
69 		ArgTypes.push_back(I->getType());
70 
71 	// Create a new function type...
72 	FunctionType *FTy = FunctionType::get(function->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
73 
74 	// Create the wrapper
75 	wrapper = Function::Create(FTy, function->getLinkage(), wrapperName, function->getParent());
76 
77 	// Loop over the arguments, copying the names of the mapped arguments over...
78 	Function::arg_iterator DestI = wrapper->arg_begin();
79 	Value *magicTypeValue = DestI;
80 	magicTypeValue->setName("cs_info");
81 	DestI++;
82 	for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
83 		DestI->setName(I->getName());
84 		VMap[I] = DestI++;
85 	}
86 
87 	SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
88 	CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL);
89 	return wrapper;
90 }
91 
92 inline MagicDebugFunction::MagicDebugFunction(Function *function) {
93 	this->function = function;
94 }
95 
96 inline void MagicDebugFunction::addHooks(std::pair<Function*, Function*> aHooks, unsigned aFlags, std::vector<unsigned> aArgsMapping,
97 		std::vector<Value*> aTrailingArgs) {
98 	hooks = aHooks;
99 	flags = aFlags;
100 	trailingArgs = aTrailingArgs;
101 	argsMapping = aArgsMapping;
102 }
103 
104 inline Function* MagicDebugFunction::getFunction() const {
105 	return function;
106 }
107 
108 inline Function* MagicDebugFunction::getDebugFunction(Module &M) {
109 	PointerType* PointerTy = PointerType::get(IntegerType::get((&M)->getContext(), 8), 0);
110 	Function* debugFunction = MagicDebugFunction::getDebugClone(function, "debug_magic_" + function->getName(), PointerTy);
111 	bool ret = MagicDebugFunction::inlineHookCalls(debugFunction, hooks, flags, argsMapping, trailingArgs);
112 	if (ret) {
113 		return debugFunction;
114 	} else {
115 		return NULL;
116 	}
117 }
118 
119 inline void MagicDebugFunction::fixCalls(Module &M, const std::string &baseDir) {
120 	PointerType* PointerTy = PointerType::get(IntegerType::get((&M)->getContext(), 8), 0);
121 	Function* debugFunction = MagicDebugFunction::getDebugClone(function, "debug_magic_" + function->getName(), PointerTy);
122 	bool ret = MagicDebugFunction::inlineHookCalls(debugFunction, hooks, flags, argsMapping, trailingArgs);
123 	assert(ret && "Unable to inline the calls to the hook functions.");
124 
125 	std::vector<User*> Users(function->user_begin(), function->user_end());
126 	std::vector<Value*> EqPointers;
127 	while (!Users.empty()) {
128 		User *U = Users.back();
129 		Users.pop_back();
130 
131 		if (Instruction * I = dyn_cast<Instruction>(U)) {
132 			CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
133 			if (CS.getInstruction()
134 					&& (MagicUtil::getCalledFunctionFromCS(CS) == function
135 							|| std::find(EqPointers.begin(), EqPointers.end(), CS.getCalledValue()) != EqPointers.end())) {
136 				Function *parentFunction = CS.getInstruction()->getParent()->getParent();
137 				StringRef callParentName = MagicUtil::getFunctionSourceName(M, parentFunction, NULL, baseDir);
138 				//extend function name with debug information
139 				if (MDNode *N = I->getMetadata("dbg")) {
140 					DILocation Loc(N);
141 					std::string string;
142 					raw_string_ostream ostream(string);
143 					ostream << callParentName << MAGIC_ALLOC_NAME_SEP << Loc.getFilename() << MAGIC_ALLOC_NAME_SEP << Loc.getLineNumber();
144 					ostream.flush();
145 					callParentName = string;
146 				}
147 				Value* callParentNameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, callParentName));
148 				std::vector<Value*> debugArgs;
149 				debugArgs.push_back(callParentNameValue);
150 				debugArgs.insert(debugArgs.end(), CS.arg_begin(), CS.arg_end());
151 				CallInst* newInst = MagicUtil::createCallInstruction(debugFunction, debugArgs, "", I);
152 				newInst->takeName(I);
153 				MagicUtil::replaceCallInst(I, newInst, 1);
154 			}
155 		} else if (GlobalValue * GV = dyn_cast<GlobalValue>(U)) {
156 			Users.insert(Users.end(), GV->user_begin(), GV->user_end());
157 			EqPointers.push_back(GV);
158 		} else if (ConstantExpr * CE = dyn_cast<ConstantExpr>(U)) {
159 			if (CE->isCast()) {
160 				Users.insert(Users.end(), CE->user_begin(), CE->user_end());
161 				EqPointers.push_back(CE);
162 			}
163 		}
164 	}
165 }
166 
167 }
168 
169 // inlines calls to the pre and post hooks and returns true if the inlining succeeded, false otherwise
170 inline bool MagicDebugFunction::inlineHookCalls(Function* function, std::pair<Function*, Function*> hooks, unsigned flags,
171 		std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs) {
172 	std::vector<Value*> emptyArgs;
173 	std::vector<unsigned> emptyMapping;
174 	std::vector<unsigned> debugEmptyMapping;
175 	std::vector<unsigned> debugArgsMapping;
176 
177 	// debug version of the function, argument mapping has to be adjusted
178 	if (flags & MAGIC_HOOK_DEBUG_MASK) {
179 		// re-adjusted the index of the arguments (do not re-adjust return value)
180 		for (unsigned i = 0; i < argsMapping.size(); i++) {
181 			if (argsMapping[i] > 0) {
182 				argsMapping[i] += NUM_DEBUG_ARGS;
183 			}
184 		}
185 		// first come the debug argument
186 		for (unsigned i = 1; i <= NUM_DEBUG_ARGS; i++) {
187 			debugEmptyMapping.push_back(i);
188 			debugArgsMapping.push_back(i);
189 		}
190 		debugArgsMapping.insert(debugArgsMapping.end(), argsMapping.begin(), argsMapping.end());
191 	}
192 
193 	if (hooks.first != NULL) {
194 		// inline first hook call at the beginning of the function, according to the flag
195 		switch (flags & MAGIC_PRE_HOOK_FLAGS_MASK) {
196 		case MAGIC_PRE_HOOK_SIMPLE_CALL:
197 			MagicUtil::inlinePreHookForwardingCall(function, hooks.first, (flags & MAGIC_PRE_HOOK_DEBUG) ? debugEmptyMapping : emptyMapping,
198 					emptyArgs);
199 			break;
200 		case MAGIC_PRE_HOOK_FORWARDING_CALL:
201 			MagicUtil::inlinePreHookForwardingCall(function, hooks.first, (flags & MAGIC_PRE_HOOK_DEBUG) ? debugArgsMapping : argsMapping,
202 					trailingArgs);
203 			break;
204 		default:
205 			// unknown flag
206 			return false;
207 		}
208 	}
209 
210 	if (hooks.second != NULL) {
211 		// inline the second wrapper call at the end of the function, according to the flag
212 		switch (flags & MAGIC_POST_HOOK_FLAGS_MASK) {
213 		case MAGIC_POST_HOOK_SIMPLE_CALL:
214 			MagicUtil::inlinePostHookForwardingCall(function, hooks.second, (flags & MAGIC_POST_HOOK_DEBUG) ? debugEmptyMapping : emptyMapping,
215 					emptyArgs);
216 			break;
217 		case MAGIC_POST_HOOK_FORWARDING_CALL:
218 			MagicUtil::inlinePostHookForwardingCall(function, hooks.second, (flags & MAGIC_POST_HOOK_DEBUG) ? debugArgsMapping : argsMapping,
219 					trailingArgs);
220 			break;
221 		default:
222 			// unknown flag
223 			return false;
224 		}
225 	}
226 
227 	return true;
228 }
229 
230 #endif /* MAGIC_DEBUG_FUNCTION_H_ */
231