1 #ifndef MAGIC_DEBUG_FUNCTION_H_
2 #define MAGIC_DEBUG_FUNCTION_H_
6 #define NUM_DEBUG_ARGS 1
12 class MagicDebugFunction
{
14 MagicDebugFunction(Function
*function
);
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
="");
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
);
30 std::pair
<Function
*, Function
*> hooks
;
32 std::vector
<unsigned> argsMapping
;
33 std::vector
<Value
*> trailingArgs
;
35 Function
* getDebugClone(Function
* function
, const Twine wrapperName
, TYPECONST Type
* debugArgType
);
38 inline raw_ostream
&operator<<(raw_ostream
&OS
, const MagicDebugFunction
&aMagicDebugFunction
) {
39 aMagicDebugFunction
.print(OS
);
43 inline void MagicDebugFunction::print(raw_ostream
&OS
) const {
44 OS
<< getDescription();
47 inline void MagicDebugFunction::printDescription(raw_ostream
&OS
) const {
48 OS
<< "[ function = ";
49 OS
<< function
->getName() << "(" << TypeUtil::getDescription(function
->getFunctionType()) << ") ]";
52 inline const std::string
MagicDebugFunction::getDescription() const {
54 raw_string_ostream
ostream(string
);
55 printDescription(ostream
);
60 inline Function
* MagicDebugFunction::getDebugClone(Function
* function
, const Twine wrapperName
, TYPECONST Type
* debugArgType
) {
62 std::vector
<TYPECONST Type
*> ArgTypes
;
63 VALUE_TO_VALUE_MAP_TY VMap
;
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());
71 // Create a new function type...
72 FunctionType
*FTy
= FunctionType::get(function
->getFunctionType()->getReturnType(), ArgTypes
, function
->getFunctionType()->isVarArg());
75 wrapper
= Function::Create(FTy
, function
->getLinkage(), wrapperName
, function
->getParent());
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");
82 for (Function::const_arg_iterator I
= function
->arg_begin(), E
= function
->arg_end(); I
!= E
; ++I
) {
83 DestI
->setName(I
->getName());
87 SmallVector
<ReturnInst
*, 8> Returns
; // Ignore returns cloned...
88 CloneFunctionInto(wrapper
, function
, VMap
, false, Returns
, "", NULL
);
92 inline MagicDebugFunction::MagicDebugFunction(Function
*function
) {
93 this->function
= function
;
96 inline void MagicDebugFunction::addHooks(std::pair
<Function
*, Function
*> aHooks
, unsigned aFlags
, std::vector
<unsigned> aArgsMapping
,
97 std::vector
<Value
*> aTrailingArgs
) {
100 trailingArgs
= aTrailingArgs
;
101 argsMapping
= aArgsMapping
;
104 inline Function
* MagicDebugFunction::getFunction() const {
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
);
113 return debugFunction
;
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.");
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();
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")) {
142 raw_string_ostream
ostream(string
);
143 ostream
<< callParentName
<< MAGIC_ALLOC_NAME_SEP
<< Loc
.getFilename() << MAGIC_ALLOC_NAME_SEP
<< Loc
.getLineNumber();
145 callParentName
= string
;
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);
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
)) {
160 Users
.insert(Users
.end(), CE
->user_begin(), CE
->user_end());
161 EqPointers
.push_back(CE
);
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
;
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
;
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
);
190 debugArgsMapping
.insert(debugArgsMapping
.end(), argsMapping
.begin(), argsMapping
.end());
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
,
200 case MAGIC_PRE_HOOK_FORWARDING_CALL
:
201 MagicUtil::inlinePreHookForwardingCall(function
, hooks
.first
, (flags
& MAGIC_PRE_HOOK_DEBUG
) ? debugArgsMapping
: argsMapping
,
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
,
217 case MAGIC_POST_HOOK_FORWARDING_CALL
:
218 MagicUtil::inlinePostHookForwardingCall(function
, hooks
.second
, (flags
& MAGIC_POST_HOOK_DEBUG
) ? debugArgsMapping
: argsMapping
,
230 #endif /* MAGIC_DEBUG_FUNCTION_H_ */