00001 #include <SectHeader.h> 00002 #include <Iterator.h> 00003 #include <Function.h> 00004 #include <LineInfoFinder.h> 00005 #include <XCoffFile.h> 00006 #include <BasicBlockCounter.h> 00007 00008 BasicBlockCounter::BasicBlockCounter(XCoffFile* xcoff,char* extension,uint32_t phaseNo) 00009 : CommonMethods(xcoff,extension,phaseNo,1,NULL) 00010 { 00011 } 00012 00013 void BasicBlockCounter::selectInstrumentationPoints(char* inpFile){ 00014 00015 terminationBlock = findTerminationBlock(); 00016 ASSERT(terminationBlock && "FATAL : There is no exit block"); 00017 00018 uint32_t allBlocksCount = xcoffFile->getNumberOfBlocks(); 00019 00020 bool insertAppExitBlock = true; 00021 00022 if (allBlocksCount){ 00023 blocksToInstrument = new BasicBlock*[allBlocksCount]; 00024 xcoffFile->getAllBlocks(blocksToInstrument); 00025 00026 for (uint32_t i = 0; i < allBlocksCount; i++){ 00027 BasicBlock* bb = blocksToInstrument[i]; 00028 if (filterBlockForInst(bb)){ 00029 PRINT_DEBUG("Filtering basic block %#12llx",bb->getHashCode().getValue()); 00030 numOfBlocksFiltered++; 00031 continue; 00032 } 00033 if (insertAppExitBlock && (bb == terminationBlock)){ 00034 PRINT_INFOR("The exit block sequence id will be %#x",numberOfInstPoints); 00035 insertAppExitBlock = false; 00036 } 00037 blocksToInstrument[numberOfInstPoints++] = bb; 00038 } 00039 } else { 00040 PRINT_ERROR("There is no basic block identified in the executable yet, is executable parsed"); 00041 } 00042 00043 if (!numberOfInstPoints){ 00044 PRINT_ERROR("There is no basic block passed the filter"); 00045 } 00046 00047 if (insertAppExitBlock){ 00048 blocksToInstrument[numberOfInstPoints++] = terminationBlock; 00049 } 00050 00051 PRINT_INFOR("**** Number of basic blocks considered in instrumentation %d ******",numberOfInstPoints); 00052 } 00053 00054 uint32_t BasicBlockCounter::byteCountForInst(uint32_t instPointIdx,uint64_t instStubAddress,TextSection* textSect){ 00055 BasicBlock* block = blocksToInstrument[instPointIdx]; 00056 00057 uint64_t instPointAddress = 0; 00058 00059 if(!block->findFirstInstPoint(&instPointAddress)) 00060 return 0; 00061 00062 ASSERT(textSect->inRange(instPointAddress)); 00063 00064 if(!Instruction::isInJumpInsnRange(instPointAddress,instStubAddress)) 00065 return 0; 00066 00067 int32_t blockCounterOffset = getDataOffsetForInst(instPointIdx); 00068 bool isApplicationExit = (block == terminationBlock); 00069 00070 uint32_t minInsnCount = 8; 00071 uint32_t tocUpdateInsnCount = 0; 00072 uint32_t indexAccessInsnCount = 0; 00073 uint32_t exitInsnCount = 0; 00074 00075 if(tocXorUpdateVal){ 00076 tocUpdateInsnCount += 2; 00077 if(SECOND_HALFWORD(tocXorUpdateVal)){ 00078 tocUpdateInsnCount += 2; 00079 } 00080 } 00081 if(!Instruction::isInLoadOffsetInsnRange(blockCounterOffset)){ 00082 indexAccessInsnCount += 4; 00083 } 00084 if(isApplicationExit){ 00085 tocUpdateInsnCount *= 2; 00086 exitInsnCount = 11; 00087 } 00088 uint32_t insnCount = minInsnCount + tocUpdateInsnCount + 00089 indexAccessInsnCount + exitInsnCount; 00090 00091 return (insnCount*sizeof(uint32_t)); 00092 } 00093 00094 uint32_t BasicBlockCounter::generateCodeForInst(uint32_t instPointIdx, 00095 uint64_t instStubAddress,TextSection* textSect, 00096 BaseGen* gen,uint32_t genBufferOffset) 00097 { 00098 ASSERT(gen->getParsedBase() == (Base*)textSect); 00099 BasicBlock* block = blocksToInstrument[instPointIdx]; 00100 ASSERT(block); 00101 ASSERT(extendedDataSize && dataBufferEntryCount); 00102 00103 uint64_t instPointAddress = 0; 00104 00105 if(!block->findFirstInstPoint(&instPointAddress)){ 00106 PRINT_INFOR("Basic Block %#18llx does not have suitable location for inst", 00107 block->getHashCode().getValue()); 00108 return 0; 00109 } 00110 ASSERT(textSect->inRange(instPointAddress)); 00111 00112 if(!Instruction::isInJumpInsnRange(instPointAddress,instStubAddress)){ 00113 PRINT_INFOR("Basic Block %#18llx can not be instrumented due to branch offset limit", 00114 block->getHashCode().getValue()); 00115 return 0; 00116 } 00117 00118 AddressIterator ait = block->getInstructionIterator(); 00119 ait.skipTo(instPointAddress); 00120 Instruction origInsn = textSect->readInstruction(&ait); 00121 00122 bool isApplicationExit = (block == terminationBlock); 00123 00124 uint32_t savedReg = 31; 00125 uint32_t scratchReg = 30; 00126 ASSERT(savedReg > LAST_VOLATILE_REG); 00127 ASSERT(scratchReg > LAST_VOLATILE_REG); 00128 00129 int32_t savedRegSaveOffset = getGPRSaveOffset(savedReg); 00130 int32_t scratchRegSaveOffset = getGPRSaveOffset(scratchReg); 00131 int32_t blockCounterOffset = getDataOffsetForInst(instPointIdx); 00132 00133 uint32_t maxInsnCount = (maxByteCountPerInst() / sizeof(uint32_t)); 00134 00135 uint32_t insnCount = 0; 00136 Instruction* insnBuffer = new Instruction[maxInsnCount]; 00137 00138 insnBuffer[insnCount++] = origInsn; 00139 00140 updateTOCRegister(insnBuffer,&insnCount); 00141 00142 insnBuffer[insnCount++] = Instruction::generateStoreDouble(savedReg,REG_TOC,savedRegSaveOffset); 00143 00144 bool oneWordCounter = (sizeof(uint32_t) == bytesPerBufferEntry()); 00145 00146 if(!Instruction::isInLoadOffsetInsnRange(blockCounterOffset)){ 00147 insnBuffer[insnCount++] = Instruction::generateStoreDouble(scratchReg,REG_TOC,scratchRegSaveOffset); 00148 insnBuffer[insnCount++] = Instruction::generateLoad32BitHigh(scratchReg,blockCounterOffset); 00149 insnBuffer[insnCount++] = Instruction::generateLoad32BitLow(scratchReg,blockCounterOffset); 00150 if(oneWordCounter){ 00151 insnBuffer[insnCount++] = Instruction::generateLoadWordIndx(savedReg,REG_TOC,scratchReg); 00152 } else { 00153 insnBuffer[insnCount++] = Instruction::generateLoadDoubleIndx(savedReg,REG_TOC,scratchReg); 00154 } 00155 00156 insnBuffer[insnCount++] = Instruction::generateIncrement(savedReg,1); 00157 if(oneWordCounter){ 00158 insnBuffer[insnCount++] = Instruction::generateStoreWordIndx(savedReg,REG_TOC,scratchReg); 00159 } else { 00160 insnBuffer[insnCount++] = Instruction::generateStoreDoubleIndx(savedReg,REG_TOC,scratchReg); 00161 } 00162 insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,scratchRegSaveOffset); 00163 } else { 00164 if(oneWordCounter){ 00165 insnBuffer[insnCount++] = Instruction::generateLoadWord(savedReg,REG_TOC,blockCounterOffset); 00166 } else { 00167 insnBuffer[insnCount++] = Instruction::generateLoadDouble(savedReg,REG_TOC,blockCounterOffset); 00168 } 00169 insnBuffer[insnCount++] = Instruction::generateIncrement(savedReg,1); 00170 if(oneWordCounter){ 00171 insnBuffer[insnCount++] = Instruction::generateStoreWord(savedReg,REG_TOC,blockCounterOffset); 00172 } else { 00173 insnBuffer[insnCount++] = Instruction::generateStoreDouble(savedReg,REG_TOC,blockCounterOffset); 00174 } 00175 } 00176 00177 if(isApplicationExit){ 00178 insnBuffer[insnCount++] = Instruction::generateStoreDouble(scratchReg,REG_TOC,scratchRegSaveOffset); 00179 00180 generateFuncCallFull(insnBuffer,&insnCount,savedReg,instStubAddress,libraryFuncStubAddrs[0]); 00181 00182 insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,scratchRegSaveOffset); 00183 } 00184 00185 insnBuffer[insnCount++] = Instruction::generateLoadDouble(savedReg,REG_TOC,savedRegSaveOffset); 00186 00187 updateTOCRegister(insnBuffer,&insnCount); 00188 00189 uint64_t fromAddr = instStubAddress + (insnCount * sizeof(uint32_t)); 00190 uint64_t toAddr = instPointAddress + sizeof(uint32_t); 00191 insnBuffer[insnCount++] = Instruction::generateJumpInsn(fromAddr,toAddr); 00192 insnBuffer[insnCount++] = Instruction(instPointIdx); 00193 00194 ASSERT(insnCount <= maxInsnCount); 00195 00196 gen->writeInstructions(genBufferOffset,insnCount,insnBuffer); 00197 00198 delete[] insnBuffer; 00199 00200 fromAddr = instPointAddress; 00201 toAddr = instStubAddress; 00202 Instruction origJumpToStub = Instruction::generateJumpInsn(fromAddr,toAddr); 00203 gen->writeWord(instPointAddress-textSect->getSectHeader()->GET(s_vaddr),origJumpToStub.bits()); 00204 00205 return (insnCount*sizeof(uint32_t)); 00206 } 00207 00208 bool BasicBlockCounter::filterBlockForInst(BasicBlock* bb){ 00209 if(!bb) 00210 return true; 00211 if(bb->isTrace() || bb->isJumpTable()) 00212 return true; 00213 if((bb->getNumOfMemoryOps() == 0) && 00214 (bb->getNumOfFloatPOps() == 0)) 00215 return true; 00216 return false; 00217 } 00218 00219 void BasicBlockCounter::getSharedLibraryPathAndObj(char** path,char** name,char** obj){ 00220 *path = getPathToInstLib(); 00221 *obj = ""; 00222 if(xcoffFile->is64Bit()){ 00223 *name = "libcntrFunc_64.a"; 00224 } else { 00225 *name = "libcntrFunc.a"; 00226 } 00227 ASSERT(path && name && obj); 00228 } 00229 00230 void BasicBlockCounter::initializeReservedData(DataSection* dataSect,BaseGen* gen){ 00231 gen->writeString(commentAddress-dataSect->getSectHeader()->GET(s_vaddr), 00232 sharedLibraryInfoStr,strlen(sharedLibraryInfoStr) + 1); 00233 }