Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

/users/u3/mtikir/PMaCInstrumentor_v1601/tools/BasicBlockTracer.C

Go to the documentation of this file.
00001 #include <SectHeader.h>
00002 #include <Iterator.h>
00003 #include <Function.h>
00004 #include <LineInfoFinder.h>
00005 #include <XCoffFile.h>
00006 #include <BasicBlockTracer.h>
00007 
00008 bool BasicBlockTracer::filterBlockForInst(BasicBlock* bb){
00009     if (!bb)
00010         return true;
00011     if (bb->isTrace() || bb->isJumpTable())
00012         return true;
00013     return false;
00014 }
00015 
00016 
00017 /* initialize any extra data being put into the data section */
00018 void BasicBlockTracer::initializeReservedData(DataSection* dataSect,BaseGen* gen){
00019     uint32_t lineno = 0;
00020     char* functionNameOfBlock = NULL;
00021     LineInfoFinder* LIF = ((TextSection*)xcoffFile->getRawSection(xcoffFile->getTextSectionIndex()))->getLineInfoFinder();
00022     uint64_t baseAddress;
00023 
00024     for (uint32_t i = 0; i < numberOfInstPoints; i++){
00025             /* get the address, line number and function name of this block */
00026         baseAddress = blocksToInstrument[i]->getBaseAddress();
00027         if (LIF){
00028             lineno = LIF->getLineNumberInFunction(baseAddress);
00029             functionNameOfBlock = LIF->getFunctionName(baseAddress);
00030         } 
00031 
00032             /* write the info collected for this block to the data section */
00033         gen->writeWord(allBlockInfo[i]-dataSect->getSectHeader()->GET(s_vaddr),i);
00034         gen->writeWord(allBlockInfo[i]-dataSect->getSectHeader()->GET(s_vaddr)+sizeof(uint32_t),lineno);
00035         gen->writeString(allBlockInfo[i]-dataSect->getSectHeader()->GET(s_vaddr)+(2*sizeof(uint32_t)),functionNameOfBlock,strlen(functionNameOfBlock));
00036         gen->writeString(allBlockInfo[i]-dataSect->getSectHeader()->GET(s_vaddr)+(2*sizeof(uint32_t))+strlen(functionNameOfBlock),"\0",sizeof(char));
00037 
00038         PRINT_DEBUG("Writing [%d,%d,%s] (length %d) to data section at location %#lx", i, lineno, functionNameOfBlock, 
00039             (2*sizeof(uint32_t))+strlen(functionNameOfBlock)+sizeof(char), allBlockInfo[i]);
00040     }
00041 }
00042 
00043 uint32_t BasicBlockTracer::generateSharedLibFuncWrapper(
00044         uint32_t libFuncIdx,uint64_t funcCallAddr,uint32_t genBufferOffset,BaseGen* gen)
00045 {
00046     uint32_t insnCount = 0;
00047     Instruction* insnBuffer = new Instruction[byteCountForSharedLibFuncWrappers() / sizeof(uint32_t)];
00048 
00049     PRINT_DEBUG("Generating library stub for library function at %#llx", funcCallAddr);
00050 
00051     uint32_t scratchReg = 6;
00052     uint32_t fpScratchReg = 3;
00053     uint32_t savedReg = 31;
00054     uint32_t tocHoldReg = 30;
00055     uint32_t firstArgReg = 3;
00056 
00057     ASSERT(scratchReg == 6);
00058     ASSERT(fpScratchReg == 3);
00059     ASSERT(savedReg == 31);
00060     ASSERT(tocHoldReg == 30);
00061     ASSERT(firstArgReg == 3);
00062 
00063     int32_t saveOffset = 0x0;
00064 
00065     updateTOCRegister(insnBuffer,&insnCount);
00066 
00067     for (uint32_t i = 0; i <= LAST_VOLATILE_REG; i++){
00068         saveOffset = getGPRSaveOffset(i);
00069         insnBuffer[insnCount++] = Instruction::generateStoreDouble(i,REG_TOC,saveOffset);
00070     }
00071     for (uint32_t i = 0; i <= LAST_VOLATILE_REG; i++){
00072         saveOffset = getFPRSaveOffset(i);
00073         insnBuffer[insnCount++] = Instruction::generateStoreDoubleFloat(i,REG_TOC,saveOffset);
00074     }
00075 
00076     saveCTRRegister(insnBuffer,&insnCount,scratchReg);
00077     saveEXRRegister(insnBuffer,&insnCount,scratchReg);
00078     saveFPSCRRegister(insnBuffer,&insnCount,fpScratchReg);
00079 
00080         /* load the saved block info pointer offset (saved in function stub) into the scratch register */
00081     insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,getBlockPointerOffsetSaveOffset());
00082         /* copy the TOC location to a function argument register */
00083     insnBuffer[insnCount++] = Instruction::generateMoveReg(REG_TOC,firstArgReg);
00084         /* add the block info pointer offset to the TOC location to get the location of the block info */
00085     insnBuffer[insnCount++] = Instruction::generateAdd(firstArgReg,firstArgReg,scratchReg);
00086 
00087     insnBuffer[insnCount++] = Instruction::generateMoveFromSPR(savedReg,REG_LNK);
00088     insnBuffer[insnCount++] = Instruction::generateMoveReg(REG_TOC,tocHoldReg);
00089 
00090 
00091     int32_t callOffset = funcCallAddr - execTOCAddress - tocDistUpdateVal;
00092     if (xcoffFile->is64Bit()){
00093         insnBuffer[insnCount++] = Instruction::generateSPIncrementDouble(-SAFE_FRAME_LOC*sizeof(uint64_t));
00094         insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,callOffset);
00095         insnBuffer[insnCount++] = Instruction::generateLoadDouble(REG_TOC,scratchReg,sizeof(uint64_t));
00096         insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,scratchReg,0);
00097     } else {
00098         insnBuffer[insnCount++] = Instruction::generateSPIncrementWord(-SAFE_FRAME_LOC*sizeof(uint64_t));
00099         insnBuffer[insnCount++] = Instruction::generateLoadWord(scratchReg,REG_TOC,callOffset);
00100         insnBuffer[insnCount++] = Instruction::generateLoadWord(REG_TOC,scratchReg,sizeof(uint32_t));
00101         insnBuffer[insnCount++] = Instruction::generateLoadWord(scratchReg,scratchReg,0);
00102     }
00103     insnBuffer[insnCount++] = Instruction::generateMoveToSPR(scratchReg,REG_CTR);
00104     insnBuffer[insnCount++] = Instruction::generateCallToCTR();
00105 
00106     insnBuffer[insnCount++] = Instruction::generateMoveReg(tocHoldReg,REG_TOC);
00107     insnBuffer[insnCount++] = Instruction::generateMoveToSPR(savedReg,REG_LNK);
00108 
00109     restFPSCRRegister(insnBuffer,&insnCount,fpScratchReg);
00110     restEXRRegister(insnBuffer,&insnCount,scratchReg);
00111     restCTRRegister(insnBuffer,&insnCount,scratchReg);
00112 
00113     for (uint32_t i = 0; i <= LAST_VOLATILE_REG; i++){
00114         saveOffset = getFPRSaveOffset(i);
00115         insnBuffer[insnCount++] = Instruction::generateLoadDoubleFloat(i,REG_TOC,saveOffset);
00116     }
00117     for (uint32_t i = 0; i <= LAST_VOLATILE_REG; i++){
00118         saveOffset = getGPRSaveOffset(i);
00119         insnBuffer[insnCount++] = Instruction::generateLoadDouble(i,REG_TOC,saveOffset);
00120     }
00121     updateTOCRegister(insnBuffer,&insnCount);
00122 
00123     insnBuffer[insnCount++] = Instruction::generateReturnToLnk();
00124 
00125     gen->writeInstructions(genBufferOffset,insnCount,insnBuffer);
00126 
00127     delete[] insnBuffer;
00128 
00129     return (insnCount*sizeof(uint32_t));
00130 }
00131 
00132 void BasicBlockTracer::reserveDataForInstrumentation(){
00133 
00134     extendedDataSize = 0;
00135     extendedBeginAddr = 0;
00136     dataBufferEntryCount = 0;
00137 
00138     uint64_t dataSectionBeginAddr = xcoffFile->getDataSectionVAddr();
00139     uint32_t dataSectionSize = xcoffFile->getDataSectionSize();
00140 
00141     execTOCAddress = xcoffFile->getTOCAddress();
00142 
00143     uint64_t currentFreeAddress = dataSectionBeginAddr + dataSectionSize;
00144 
00145     uint32_t incrementSize = 0;
00146     if (xcoffFile->is64Bit()){
00147         currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00148         incrementSize = sizeof(uint64_t);
00149     } else {
00150         currentFreeAddress = nextAlignAddressWord(currentFreeAddress);
00151         incrementSize = sizeof(uint32_t);
00152     }
00153 
00154     extendedBeginAddr = currentFreeAddress;
00155 
00156     for (uint32_t i = 0; i < getNumOfSharedLibFuncs(); i++){
00157         libraryFunctionStubAddrLocs[i] = currentFreeAddress;
00158         currentFreeAddress += incrementSize;
00159     }
00160 
00161     currentFreeAddress = nextAlignAddressWord(currentFreeAddress);
00162 
00163     saveAddressCondReg = currentFreeAddress;
00164     currentFreeAddress += sizeof(uint32_t);
00165     saveAddressFPCondReg = currentFreeAddress;
00166     currentFreeAddress += sizeof(uint32_t);
00167 
00168     currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00169 
00170     saveAddressLinkReg = currentFreeAddress;
00171     currentFreeAddress += sizeof(uint64_t);
00172     saveAddressCtrReg = currentFreeAddress;
00173     currentFreeAddress += sizeof(uint64_t);
00174     saveAddressExpReg = currentFreeAddress;
00175     currentFreeAddress += sizeof(uint64_t);
00176 
00177     saveAddressGprRegs = currentFreeAddress;
00178     currentFreeAddress += (sizeof(uint64_t) * NUM_OF_GPR_REGS);
00179     saveAddressFprRegs = currentFreeAddress;
00180     currentFreeAddress += (sizeof(uint64_t) * NUM_OF_FPR_REGS);
00181         
00182     currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00183 
00184 
00185         /* the offset of the block info pointer that will be saved for each library call */
00186     blockPointerOffset = currentFreeAddress;
00187     currentFreeAddress += sizeof(uint64_t);
00188 
00189         /* reserve the locations for the information for each block */
00190     allBlockInfo = new uint32_t[numberOfInstPoints];
00191     uint32_t totalNameSizes = 0;
00192     char* functionNameOfBlock = NULL;
00193     uint32_t lineno = 0;
00194     LineInfoFinder* LIF = ((TextSection*)xcoffFile->getRawSection(xcoffFile->getTextSectionIndex()))->getLineInfoFinder();
00195 
00196     for (uint32_t i = 0; i < numberOfInstPoints; i++){
00197         uint64_t baseAddress = blocksToInstrument[i]->getBaseAddress();
00198         if (LIF){
00199             lineno = LIF->getLineNumberInFunction(baseAddress);
00200             functionNameOfBlock = LIF->getFunctionName(baseAddress);
00201         }
00202         totalNameSizes += (strlen(functionNameOfBlock) + 1);
00203         currentFreeAddress = nextAlignAddressWord(currentFreeAddress);
00204         allBlockInfo[i] = currentFreeAddress;
00205         currentFreeAddress += ((2 * sizeof(uint32_t)) + strlen(functionNameOfBlock) + 1);
00206     }
00207 
00208     currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00209     extendedDataSize = currentFreeAddress - (dataSectionBeginAddr + dataSectionSize);
00210 
00211     tocXorUpdateVal = 0;
00212     if (!Instruction::isInLoadOffsetInsnRange((int32_t)(dataBufferAddress-execTOCAddress))){
00213         tocXorUpdateVal = (uint32_t)(extendedBeginAddr ^ execTOCAddress);
00214         tocDistUpdateVal = (uint32_t)(extendedBeginAddr - execTOCAddress);
00215     }
00216 }
00217 
00218 BasicBlockTracer::BasicBlockTracer(XCoffFile* xcoff,char* extension,uint32_t phaseNo)
00219     : CommonMethods(xcoff,extension,phaseNo,1,NULL)
00220 {
00221 }
00222 
00223 void BasicBlockTracer::selectInstrumentationPoints(char* inpFile){
00224     
00225     terminationBlock = findTerminationBlock();
00226     ASSERT(terminationBlock && "FATAL : There is no exit block");
00227 
00228     uint32_t allBlocksCount = xcoffFile->getNumberOfBlocks();
00229 
00230     bool insertAppExitBlock = true;
00231 
00232     if (allBlocksCount){
00233         blocksToInstrument = new BasicBlock*[allBlocksCount];
00234         xcoffFile->getAllBlocks(blocksToInstrument);
00235 
00236         for (uint32_t i = 0; i < allBlocksCount; i++){
00237             BasicBlock* bb = blocksToInstrument[i];
00238             if (filterBlockForInst(bb)){
00239                 PRINT_DEBUG("Filtering basic block %#12llx",bb->getHashCode().getValue());
00240                 numOfBlocksFiltered++;
00241                 continue;
00242             }
00243             if (insertAppExitBlock && (bb == terminationBlock)){
00244                 PRINT_INFOR("The exit block sequence id will be %#x",numberOfInstPoints);
00245                 insertAppExitBlock = false;
00246             }
00247             blocksToInstrument[numberOfInstPoints++] = bb;
00248         }
00249     } else {
00250         PRINT_ERROR("There is no basic block identified in the executable yet, is executable parsed");
00251     }
00252 
00253     if (!numberOfInstPoints){
00254         PRINT_ERROR("There is no basic block passed the filter");
00255     }
00256 
00257     if (insertAppExitBlock){
00258         blocksToInstrument[numberOfInstPoints++] = terminationBlock;
00259     }
00260     PRINT_INFOR("**** Number of basic blocks considered in instrumentation %d ******",numberOfInstPoints);
00261 }
00262 
00263 uint32_t BasicBlockTracer::byteCountForInst(uint32_t instPointIdx,uint64_t instStubAddress,TextSection* textSect){
00264 
00265     BasicBlock* block = blocksToInstrument[instPointIdx];
00266     ASSERT(block);
00267     ASSERT(extendedDataSize);
00268 
00269     uint64_t instPointAddress = 0;
00270 
00271     if (!block->findFirstInstPoint(&instPointAddress)){
00272         PRINT_INFOR("Basic Block %#18llx does not have suitable location for inst",
00273                     block->getHashCode().getValue());
00274         return 0;
00275     }
00276     ASSERT(textSect->inRange(instPointAddress));
00277 
00278     if (!Instruction::isInJumpInsnRange(instPointAddress,instStubAddress)){
00279         PRINT_INFOR("Basic Block %#18llx can not be instrumented due to branch offset limit",
00280                     block->getHashCode().getValue());
00281         return 0;
00282     }
00283     uint32_t numberOfInstructions = 0;
00284 
00285     uint32_t origInstructionSize = 0;
00286     uint32_t updateTOCSize = 0;
00287     uint32_t saveRestSize = 0;
00288     uint32_t blockPointSize = 0;
00289     uint32_t funcCallSize = 0;
00290 
00291     origInstructionSize++;
00292 
00293     uint16_t tocUpdateValLow = FIRST_HALFWORD(tocXorUpdateVal);
00294     uint16_t tocUpdateValHigh = SECOND_HALFWORD(tocXorUpdateVal);
00295     if(tocXorUpdateVal){
00296         if(tocUpdateValHigh){
00297             updateTOCSize += 4;
00298         }
00299         updateTOCSize += 4;
00300     }
00301 
00302     saveRestSize += 2;
00303     blockPointSize += 3;
00304     funcCallSize += 9;        
00305     saveRestSize += 2;
00306     funcCallSize += 2;
00307 
00308     numberOfInstructions = origInstructionSize + updateTOCSize + saveRestSize + blockPointSize + funcCallSize;    
00309     PRINT_DEBUG("Found %d instructions in the stub for inst point %d", numberOfInstructions, instPointIdx); 
00310 
00311     return numberOfInstructions * sizeof(uint32_t);
00312 }
00313 
00314 uint32_t BasicBlockTracer::generateCodeForInst(uint32_t instPointIdx,
00315                                                     uint64_t instStubAddress,TextSection* textSect,
00316                                                     BaseGen* gen,uint32_t genBufferOffset)
00317 {
00318     ASSERT(gen->getParsedBase() == (Base*)textSect);
00319     BasicBlock* block = blocksToInstrument[instPointIdx];
00320     ASSERT(block);
00321     ASSERT(extendedDataSize);
00322 
00323     uint64_t instPointAddress = 0;
00324 
00325     if (!block->findFirstInstPoint(&instPointAddress)){
00326         PRINT_INFOR("Basic Block %#18llx does not have suitable location for inst",
00327                     block->getHashCode().getValue());
00328         return 0;
00329     }
00330     ASSERT(textSect->inRange(instPointAddress));
00331 
00332     if (!Instruction::isInJumpInsnRange(instPointAddress,instStubAddress)){
00333         PRINT_INFOR("Basic Block %#18llx can not be instrumented due to branch offset limit",
00334                     block->getHashCode().getValue());
00335         return 0;
00336     }
00337 
00338     AddressIterator ait = block->getInstructionIterator();
00339     ait.skipTo(instPointAddress);
00340     Instruction origInsn = textSect->readInstruction(&ait);
00341 
00342     bool isApplicationExit = (block == terminationBlock);
00343 
00344     uint32_t savedReg = 31;
00345     uint32_t scratchReg = 30;
00346     ASSERT(savedReg > LAST_VOLATILE_REG);
00347     ASSERT(scratchReg > LAST_VOLATILE_REG);
00348 
00349     int32_t savedRegSaveOffset = getGPRSaveOffset(savedReg);
00350     int32_t scratchRegSaveOffset = getGPRSaveOffset(scratchReg);
00351     int32_t blockPointerOffsetSaveOffset = getBlockPointerOffsetSaveOffset();
00352     int32_t blockPointerOffset = getBlockPointerOffset(instPointIdx);
00353 
00354     uint32_t maxInsnCount = (maxByteCountPerInst() / sizeof(uint32_t));
00355 
00356     uint32_t insnCount = 0;
00357     Instruction* insnBuffer = new Instruction[maxInsnCount];
00358 
00359     insnBuffer[insnCount++] = origInsn;
00360 
00361     updateTOCRegister(insnBuffer,&insnCount);
00362 
00363     insnBuffer[insnCount++] = Instruction::generateStoreDouble(savedReg,REG_TOC,savedRegSaveOffset);
00364     insnBuffer[insnCount++] = Instruction::generateStoreDouble(scratchReg,REG_TOC,scratchRegSaveOffset);
00365 
00366     insnBuffer[insnCount++] = Instruction::generateLoad32BitHigh(scratchReg,blockPointerOffset);
00367     insnBuffer[insnCount++] = Instruction::generateLoad32BitLow(scratchReg,blockPointerOffset);
00368     insnBuffer[insnCount++] = Instruction::generateStoreDouble(scratchReg,REG_TOC,blockPointerOffsetSaveOffset);
00369 
00370     generateFuncCallFull(insnBuffer,&insnCount,savedReg,instStubAddress,libraryFuncStubAddrs[0]);
00371 
00372     insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,scratchRegSaveOffset);
00373     insnBuffer[insnCount++] = Instruction::generateLoadDouble(savedReg,REG_TOC,savedRegSaveOffset);
00374 
00375     updateTOCRegister(insnBuffer,&insnCount);
00376 
00377     uint64_t fromAddr = instStubAddress + (insnCount * sizeof(uint32_t));
00378     uint64_t toAddr   = instPointAddress + sizeof(uint32_t);
00379     insnBuffer[insnCount++] = Instruction::generateJumpInsn(fromAddr,toAddr);
00380     insnBuffer[insnCount++] = Instruction(instPointIdx);
00381 
00382     ASSERT(insnCount <= maxInsnCount);
00383 
00384     gen->writeInstructions(genBufferOffset,insnCount,insnBuffer);
00385 
00386     delete[] insnBuffer;
00387 
00388     fromAddr = instPointAddress;
00389     toAddr   = instStubAddress;
00390     Instruction origJumpToStub = Instruction::generateJumpInsn(fromAddr,toAddr);
00391     gen->writeWord(instPointAddress-textSect->getSectHeader()->GET(s_vaddr),origJumpToStub.bits());
00392 
00393     PRINT_DEBUG("Generating function stub with %d instructions", insnCount);
00394     return (insnCount*sizeof(uint32_t));
00395 }
00396 
00397 void BasicBlockTracer::getSharedLibraryPathAndObj(char** path,char** name,char** obj){
00398     *path = getPathToInstLib();
00399     *obj  = "";
00400     if(xcoffFile->is64Bit()){
00401         *name = "libtracFunc_64.a";
00402     } else {
00403         *name = "libtracFunc.a";
00404     }
00405     ASSERT(path && name && obj);
00406 }
00407 
00408 

Generated on Mon Jan 28 11:08:33 2008 for PMaCInstrumentor by doxygen 1.3.5