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