LLVM API Documentation
00001 //===- TraceValues.cpp - Value Tracing for debugging ----------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Support for inserting LLVM code to print values at basic block and function 00011 // exits. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "llvm/Transforms/Instrumentation.h" 00016 #include "llvm/Constants.h" 00017 #include "llvm/DerivedTypes.h" 00018 #include "llvm/Instructions.h" 00019 #include "llvm/Module.h" 00020 #include "llvm/Pass.h" 00021 #include "llvm/Assembly/Writer.h" 00022 #include "llvm/Support/CommandLine.h" 00023 #include "llvm/ADT/StringExtras.h" 00024 #include <algorithm> 00025 #include <sstream> 00026 using namespace llvm; 00027 00028 static cl::opt<bool> 00029 DisablePtrHashing("tracedisablehashdisable", cl::Hidden, 00030 cl::desc("Disable pointer hashing in the -trace or -tracem " 00031 "passes")); 00032 00033 static cl::list<std::string> 00034 TraceFuncNames("tracefunc", cl::desc("Only trace specific functions in the " 00035 "-trace or -tracem passes"), 00036 cl::value_desc("function"), cl::Hidden); 00037 00038 static void TraceValuesAtBBExit(BasicBlock *BB, 00039 Function *Printf, Function* HashPtrToSeqNum, 00040 std::vector<Instruction*> *valuesStoredInFunction); 00041 00042 // We trace a particular function if no functions to trace were specified 00043 // or if the function is in the specified list. 00044 // 00045 inline static bool 00046 TraceThisFunction(Function &F) 00047 { 00048 if (TraceFuncNames.empty()) return true; 00049 00050 return std::find(TraceFuncNames.begin(), TraceFuncNames.end(), F.getName()) 00051 != TraceFuncNames.end(); 00052 } 00053 00054 00055 namespace { 00056 struct ExternalFuncs { 00057 Function *PrintfFunc, *HashPtrFunc, *ReleasePtrFunc; 00058 Function *RecordPtrFunc, *PushOnEntryFunc, *ReleaseOnReturnFunc; 00059 void doInitialization(Module &M); // Add prototypes for external functions 00060 }; 00061 00062 class InsertTraceCode : public FunctionPass { 00063 protected: 00064 ExternalFuncs externalFuncs; 00065 public: 00066 00067 // Add a prototype for runtime functions not already in the program. 00068 // 00069 bool doInitialization(Module &M); 00070 00071 //-------------------------------------------------------------------------- 00072 // Function InsertCodeToTraceValues 00073 // 00074 // Inserts tracing code for all live values at basic block and/or function 00075 // exits as specified by `traceBasicBlockExits' and `traceFunctionExits'. 00076 // 00077 bool doit(Function *M); 00078 00079 virtual void handleBasicBlock(BasicBlock *BB, 00080 std::vector<Instruction*> &VI) = 0; 00081 00082 // runOnFunction - This method does the work. 00083 // 00084 bool runOnFunction(Function &F); 00085 00086 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00087 AU.setPreservesCFG(); 00088 } 00089 }; 00090 00091 struct FunctionTracer : public InsertTraceCode { 00092 // Ignore basic blocks here... 00093 virtual void handleBasicBlock(BasicBlock *BB, 00094 std::vector<Instruction*> &VI) {} 00095 }; 00096 00097 struct BasicBlockTracer : public InsertTraceCode { 00098 // Trace basic blocks here... 00099 virtual void handleBasicBlock(BasicBlock *BB, 00100 std::vector<Instruction*> &VI) { 00101 TraceValuesAtBBExit(BB, externalFuncs.PrintfFunc, 00102 externalFuncs.HashPtrFunc, &VI); 00103 } 00104 }; 00105 00106 // Register the passes... 00107 RegisterOpt<FunctionTracer> X("tracem","Insert Function trace code only"); 00108 RegisterOpt<BasicBlockTracer> Y("trace","Insert BB and Function trace code"); 00109 } // end anonymous namespace 00110 00111 /// Just trace functions 00112 FunctionPass *llvm::createTraceValuesPassForFunction() { 00113 return new FunctionTracer(); 00114 } 00115 00116 /// Trace BB's and functions 00117 FunctionPass *llvm::createTraceValuesPassForBasicBlocks() { 00118 return new BasicBlockTracer(); 00119 } 00120 00121 // Add a prototype for external functions used by the tracing code and require 00122 // the trace library for this module. 00123 // 00124 void ExternalFuncs::doInitialization(Module &M) { 00125 M.addLibrary("trace"); 00126 const Type *SBP = PointerType::get(Type::SByteTy); 00127 const FunctionType *MTy = 00128 FunctionType::get(Type::IntTy, std::vector<const Type*>(1, SBP), true); 00129 PrintfFunc = M.getOrInsertFunction("printf", MTy); 00130 00131 // uint (sbyte*) 00132 HashPtrFunc = M.getOrInsertFunction("HashPointerToSeqNum", Type::UIntTy, SBP, 00133 (Type *)0); 00134 00135 // void (sbyte*) 00136 ReleasePtrFunc = M.getOrInsertFunction("ReleasePointerSeqNum", 00137 Type::VoidTy, SBP, (Type *)0); 00138 RecordPtrFunc = M.getOrInsertFunction("RecordPointer", 00139 Type::VoidTy, SBP, (Type *)0); 00140 00141 PushOnEntryFunc = M.getOrInsertFunction("PushPointerSet", Type::VoidTy, 00142 (Type *)0); 00143 ReleaseOnReturnFunc = M.getOrInsertFunction("ReleasePointersPopSet", 00144 Type::VoidTy, (Type *)0); 00145 } 00146 00147 00148 // Add a prototype for external functions used by the tracing code. 00149 // 00150 bool InsertTraceCode::doInitialization(Module &M) { 00151 externalFuncs.doInitialization(M); 00152 return false; 00153 } 00154 00155 00156 static inline GlobalVariable *getStringRef(Module *M, const std::string &str) { 00157 // Create a constant internal string reference... 00158 Constant *Init = ConstantArray::get(str); 00159 00160 // Create the global variable and record it in the module 00161 // The GV will be renamed to a unique name if needed. 00162 GlobalVariable *GV = new GlobalVariable(Init->getType(), true, 00163 GlobalValue::InternalLinkage, Init, 00164 "trstr"); 00165 M->getGlobalList().push_back(GV); 00166 return GV; 00167 } 00168 00169 00170 // 00171 // Check if this instruction has any uses outside its basic block, 00172 // or if it used by either a Call or Return instruction (ditto). 00173 // (Values stored to memory within this BB are live at end of BB but are 00174 // traced at the store instruction, not where they are computed.) 00175 // 00176 static inline bool LiveAtBBExit(const Instruction* I) { 00177 const BasicBlock *BB = I->getParent(); 00178 for (Value::use_const_iterator U = I->use_begin(); U != I->use_end(); ++U) 00179 if (const Instruction *UI = dyn_cast<Instruction>(*U)) 00180 if (UI->getParent() != BB || isa<ReturnInst>(UI)) 00181 return true; 00182 00183 return false; 00184 } 00185 00186 00187 static inline bool TraceThisOpCode(unsigned opCode) { 00188 // Explicitly test for opCodes *not* to trace so that any new opcodes will 00189 // be traced by default (VoidTy's are already excluded) 00190 // 00191 return (opCode < Instruction::OtherOpsBegin && 00192 opCode != Instruction::Alloca && 00193 opCode != Instruction::PHI && 00194 opCode != Instruction::Cast); 00195 } 00196 00197 00198 // Trace a value computed by an instruction if it is non-void, it is computed 00199 // by a real computation, not just a copy (see TraceThisOpCode), and 00200 // -- it is a load instruction: we want to check values read from memory 00201 // -- or it is live at exit from the basic block (i.e., ignore local temps) 00202 // 00203 static bool ShouldTraceValue(const Instruction *I) { 00204 return 00205 I->getType() != Type::VoidTy && 00206 TraceThisOpCode(I->getOpcode()) && 00207 (isa<LoadInst>(I) || LiveAtBBExit(I)); 00208 } 00209 00210 static std::string getPrintfCodeFor(const Value *V) { 00211 if (V == 0) return ""; 00212 if (V->getType()->isFloatingPoint()) 00213 return "%g"; 00214 else if (V->getType() == Type::LabelTy) 00215 return "0x%p"; 00216 else if (isa<PointerType>(V->getType())) 00217 return DisablePtrHashing ? "0x%p" : "%d"; 00218 else if (V->getType()->isIntegral()) 00219 return "%d"; 00220 00221 assert(0 && "Illegal value to print out..."); 00222 return ""; 00223 } 00224 00225 00226 static void InsertPrintInst(Value *V, BasicBlock *BB, Instruction *InsertBefore, 00227 std::string Message, 00228 Function *Printf, Function* HashPtrToSeqNum) { 00229 // Escape Message by replacing all % characters with %% chars. 00230 std::string Tmp; 00231 std::swap(Tmp, Message); 00232 std::string::iterator I = std::find(Tmp.begin(), Tmp.end(), '%'); 00233 while (I != Tmp.end()) { 00234 Message.append(Tmp.begin(), I); 00235 Message += "%%"; 00236 ++I; // Make sure to erase the % as well... 00237 Tmp.erase(Tmp.begin(), I); 00238 I = std::find(Tmp.begin(), Tmp.end(), '%'); 00239 } 00240 Message += Tmp; 00241 Module *Mod = BB->getParent()->getParent(); 00242 00243 // Turn the marker string into a global variable... 00244 GlobalVariable *fmtVal = getStringRef(Mod, Message+getPrintfCodeFor(V)+"\n"); 00245 00246 // Turn the format string into an sbyte * 00247 Constant *GEP=ConstantExpr::getGetElementPtr(fmtVal, 00248 std::vector<Constant*>(2,Constant::getNullValue(Type::LongTy))); 00249 00250 // Insert a call to the hash function if this is a pointer value 00251 if (V && isa<PointerType>(V->getType()) && !DisablePtrHashing) { 00252 const Type *SBP = PointerType::get(Type::SByteTy); 00253 if (V->getType() != SBP) // Cast pointer to be sbyte* 00254 V = new CastInst(V, SBP, "Hash_cast", InsertBefore); 00255 00256 std::vector<Value*> HashArgs(1, V); 00257 V = new CallInst(HashPtrToSeqNum, HashArgs, "ptrSeqNum", InsertBefore); 00258 } 00259 00260 // Insert the first print instruction to print the string flag: 00261 std::vector<Value*> PrintArgs; 00262 PrintArgs.push_back(GEP); 00263 if (V) PrintArgs.push_back(V); 00264 new CallInst(Printf, PrintArgs, "trace", InsertBefore); 00265 } 00266 00267 00268 static void InsertVerbosePrintInst(Value *V, BasicBlock *BB, 00269 Instruction *InsertBefore, 00270 const std::string &Message, Function *Printf, 00271 Function* HashPtrToSeqNum) { 00272 std::ostringstream OutStr; 00273 if (V) WriteAsOperand(OutStr, V); 00274 InsertPrintInst(V, BB, InsertBefore, Message+OutStr.str()+" = ", 00275 Printf, HashPtrToSeqNum); 00276 } 00277 00278 static void 00279 InsertReleaseInst(Value *V, BasicBlock *BB, 00280 Instruction *InsertBefore, 00281 Function* ReleasePtrFunc) { 00282 00283 const Type *SBP = PointerType::get(Type::SByteTy); 00284 if (V->getType() != SBP) // Cast pointer to be sbyte* 00285 V = new CastInst(V, SBP, "RPSN_cast", InsertBefore); 00286 00287 std::vector<Value*> releaseArgs(1, V); 00288 new CallInst(ReleasePtrFunc, releaseArgs, "", InsertBefore); 00289 } 00290 00291 static void 00292 InsertRecordInst(Value *V, BasicBlock *BB, 00293 Instruction *InsertBefore, 00294 Function* RecordPtrFunc) { 00295 const Type *SBP = PointerType::get(Type::SByteTy); 00296 if (V->getType() != SBP) // Cast pointer to be sbyte* 00297 V = new CastInst(V, SBP, "RP_cast", InsertBefore); 00298 00299 std::vector<Value*> releaseArgs(1, V); 00300 new CallInst(RecordPtrFunc, releaseArgs, "", InsertBefore); 00301 } 00302 00303 // Look for alloca and free instructions. These are the ptrs to release. 00304 // Release the free'd pointers immediately. Record the alloca'd pointers 00305 // to be released on return from the current function. 00306 // 00307 static void 00308 ReleasePtrSeqNumbers(BasicBlock *BB, 00309 ExternalFuncs& externalFuncs) { 00310 00311 for (BasicBlock::iterator II=BB->begin(), IE = BB->end(); II != IE; ++II) 00312 if (FreeInst *FI = dyn_cast<FreeInst>(II)) 00313 InsertReleaseInst(FI->getOperand(0), BB, FI,externalFuncs.ReleasePtrFunc); 00314 else if (AllocaInst *AI = dyn_cast<AllocaInst>(II)) 00315 InsertRecordInst(AI, BB, AI->getNext(), externalFuncs.RecordPtrFunc); 00316 } 00317 00318 00319 // Insert print instructions at the end of basic block BB for each value 00320 // computed in BB that is live at the end of BB, 00321 // or that is stored to memory in BB. 00322 // If the value is stored to memory, we load it back before printing it 00323 // We also return all such loaded values in the vector valuesStoredInFunction 00324 // for printing at the exit from the function. (Note that in each invocation 00325 // of the function, this will only get the last value stored for each static 00326 // store instruction). 00327 // 00328 static void TraceValuesAtBBExit(BasicBlock *BB, 00329 Function *Printf, Function* HashPtrToSeqNum, 00330 std::vector<Instruction*> *valuesStoredInFunction) { 00331 // Get an iterator to point to the insertion location, which is 00332 // just before the terminator instruction. 00333 // 00334 TerminatorInst *InsertPos = BB->getTerminator(); 00335 00336 std::ostringstream OutStr; 00337 WriteAsOperand(OutStr, BB, false); 00338 InsertPrintInst(0, BB, InsertPos, "LEAVING BB:" + OutStr.str(), 00339 Printf, HashPtrToSeqNum); 00340 00341 // Insert a print instruction for each instruction preceding InsertPos. 00342 // The print instructions must go before InsertPos, so we use the 00343 // instruction *preceding* InsertPos to check when to terminate the loop. 00344 // 00345 for (BasicBlock::iterator II = BB->begin(); &*II != InsertPos; ++II) { 00346 if (StoreInst *SI = dyn_cast<StoreInst>(II)) { 00347 // Trace the stored value and address 00348 InsertVerbosePrintInst(SI->getOperand(0), BB, InsertPos, 00349 " (store value) ", Printf, HashPtrToSeqNum); 00350 InsertVerbosePrintInst(SI->getOperand(1), BB, InsertPos, 00351 " (store addr ) ", Printf, HashPtrToSeqNum); 00352 } 00353 else if (ShouldTraceValue(II)) 00354 InsertVerbosePrintInst(II, BB, InsertPos, " ", Printf, HashPtrToSeqNum); 00355 } 00356 } 00357 00358 static inline void InsertCodeToShowFunctionEntry(Function &F, Function *Printf, 00359 Function* HashPtrToSeqNum){ 00360 // Get an iterator to point to the insertion location 00361 BasicBlock &BB = F.getEntryBlock(); 00362 Instruction *InsertPos = BB.begin(); 00363 00364 std::ostringstream OutStr; 00365 WriteAsOperand(OutStr, &F); 00366 InsertPrintInst(0, &BB, InsertPos, "ENTERING FUNCTION: " + OutStr.str(), 00367 Printf, HashPtrToSeqNum); 00368 00369 // Now print all the incoming arguments 00370 unsigned ArgNo = 0; 00371 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I, ++ArgNo){ 00372 InsertVerbosePrintInst(I, &BB, InsertPos, 00373 " Arg #" + utostr(ArgNo) + ": ", Printf, 00374 HashPtrToSeqNum); 00375 } 00376 } 00377 00378 00379 static inline void InsertCodeToShowFunctionExit(BasicBlock *BB, 00380 Function *Printf, 00381 Function* HashPtrToSeqNum) { 00382 // Get an iterator to point to the insertion location 00383 ReturnInst *Ret = cast<ReturnInst>(BB->getTerminator()); 00384 00385 std::ostringstream OutStr; 00386 WriteAsOperand(OutStr, BB->getParent(), true); 00387 InsertPrintInst(0, BB, Ret, "LEAVING FUNCTION: " + OutStr.str(), 00388 Printf, HashPtrToSeqNum); 00389 00390 // print the return value, if any 00391 if (BB->getParent()->getReturnType() != Type::VoidTy) 00392 InsertPrintInst(Ret->getReturnValue(), BB, Ret, " Returning: ", 00393 Printf, HashPtrToSeqNum); 00394 } 00395 00396 00397 bool InsertTraceCode::runOnFunction(Function &F) { 00398 if (!TraceThisFunction(F)) 00399 return false; 00400 00401 std::vector<Instruction*> valuesStoredInFunction; 00402 std::vector<BasicBlock*> exitBlocks; 00403 00404 // Insert code to trace values at function entry 00405 InsertCodeToShowFunctionEntry(F, externalFuncs.PrintfFunc, 00406 externalFuncs.HashPtrFunc); 00407 00408 // Push a pointer set for recording alloca'd pointers at entry. 00409 if (!DisablePtrHashing) 00410 new CallInst(externalFuncs.PushOnEntryFunc, std::vector<Value*>(), "", 00411 F.getEntryBlock().begin()); 00412 00413 for (Function::iterator BB = F.begin(); BB != F.end(); ++BB) { 00414 if (isa<ReturnInst>(BB->getTerminator())) 00415 exitBlocks.push_back(BB); // record this as an exit block 00416 00417 // Insert trace code if this basic block is interesting... 00418 handleBasicBlock(BB, valuesStoredInFunction); 00419 00420 if (!DisablePtrHashing) // release seq. numbers on free/ret 00421 ReleasePtrSeqNumbers(BB, externalFuncs); 00422 } 00423 00424 for (unsigned i=0; i != exitBlocks.size(); ++i) 00425 { 00426 // Insert code to trace values at function exit 00427 InsertCodeToShowFunctionExit(exitBlocks[i], externalFuncs.PrintfFunc, 00428 externalFuncs.HashPtrFunc); 00429 00430 // Release all recorded pointers before RETURN. Do this LAST! 00431 if (!DisablePtrHashing) 00432 new CallInst(externalFuncs.ReleaseOnReturnFunc, std::vector<Value*>(), 00433 "", exitBlocks[i]->getTerminator()); 00434 } 00435 00436 return true; 00437 }