00001 #include <SectHeader.h>
00002 #include <Instruction.h>
00003 #include <RawSection.h>
00004 #include <SymbolTable.h>
00005 #include <DemangleWrapper.h>
00006 #include <Instruction.h>
00007 #include <Function.h>
00008 #include <Iterator.h>
00009 #include <XCoffFile.h>
00010 #include <BitSet.h>
00011 #include <BinaryFile.h>
00012 #include <Loop.h>
00013 #include <Stack.h>
00014 #include <LinkedList.h>
00015 #include <LengauerTarjan.h>
00016
00017 TIMER(
00018 double cfg_s1=0.0;
00019 double cfg_s2=0.0;
00020 double cfg_s3=0.0;
00021 double cfg_s4=0.0;
00022 double cfg_s5=0.0;
00023 );
00024
00025 void FlowGraph::printInnerLoops(){
00026 for (uint32_t i = 0; i < numberOfLoops; i++){
00027 for (uint32_t j = 0; j < numberOfLoops; j++){
00028 if (loops[i]->isInnerLoop(loops[j])){
00029 PRINT_INFOR("Loop %d is inside loop %d", j, i);
00030 }
00031 if (i == j){
00032 ASSERT(loops[i]->isIdenticalLoop(loops[j]));
00033 } else {
00034 ASSERT(!loops[i]->isIdenticalLoop(loops[j]));
00035 }
00036 }
00037 }
00038 }
00039
00040 int compareLoopHeaderVaddr(const void* arg1,const void* arg2){
00041 Loop* lp1 = *((Loop**)arg1);
00042 Loop* lp2 = *((Loop**)arg2);
00043 uint64_t vl1 = lp1->getHead()->getBaseAddress();
00044 uint64_t vl2 = lp2->getHead()->getBaseAddress();
00045
00046 if(vl1 < vl2)
00047 return -1;
00048 if(vl1 > vl2)
00049 return 1;
00050 return 0;
00051 }
00052
00053 void FlowGraph::buildLoops(){
00054 if(loops){
00055 return;
00056 }
00057
00058 PRINT_DEBUG("Considering flowgraph for function %d -- has %d blocks", function->getIndex(), numOfBasicBlocks);
00059
00060 numberOfLoops = 0;
00061 loops = NULL;
00062
00063 BasicBlock** allBlocks = getAllBlocks();
00064
00065 LinkedList<BasicBlock*> backEdges;
00066 BitSet <BasicBlock*>* visitedBitSet = newBitSet();
00067 BitSet <BasicBlock*>* completedBitSet = newBitSet();
00068
00069 depthFirstSearch(allBlocks[0],visitedBitSet,true,completedBitSet,&backEdges);
00070
00071 delete visitedBitSet;
00072 delete completedBitSet;
00073
00074 if(backEdges.empty()){
00075 PRINT_DEBUG("\t%d Contains %d loops (back edges) from %d", getIndex(),numberOfLoops,numOfBasicBlocks);
00076 return;
00077 }
00078
00079 ASSERT(!(backEdges.size() % 2) && "Fatal: Back edge list should be multiple of 2, (from->to)");
00080 BitSet<BasicBlock*>* inLoop = newBitSet();
00081 Stack<BasicBlock*> loopStack(numOfBasicBlocks);
00082 LinkedList<Loop*> loopList;
00083
00084 while(!backEdges.empty()){
00085
00086 BasicBlock* from = backEdges.shift();
00087 BasicBlock* to = backEdges.shift();
00088 ASSERT(from && to && "Fatal: Backedge end points are invalid");
00089
00090 if(from->isDominatedBy(to)){
00091
00092
00093
00094 numberOfLoops++;
00095
00096 loopStack.clear();
00097 inLoop->clear();
00098
00099 inLoop->insert(to->getIndex());
00100 if (!inLoop->contains(from->getIndex())){
00101 inLoop->insert(from->getIndex());
00102 loopStack.push(from);
00103 }
00104 while(!loopStack.empty()){
00105 BasicBlock* top = loopStack.pop();
00106 uint32_t numOfSources = top->getNumOfSources();
00107 for (uint32_t m = 0; m < numOfSources; m++){
00108 BasicBlock* pred = top->getSourceBlock(m);
00109 if (!inLoop->contains(pred->getIndex())){
00110 inLoop->insert(pred->getIndex());
00111 loopStack.push(pred);
00112 }
00113 }
00114 }
00115
00116 Loop* newLoop = new Loop(to, from, this, inLoop);
00117 loopList.insert(newLoop);
00118
00119 DEBUG_MORE(
00120 newLoop->print()
00121 );
00122 }
00123 }
00124
00125 ASSERT((loopList.size() == numberOfLoops) &&
00126 "Fatal: Number of loops should match backedges defining them");
00127
00128 delete inLoop;
00129
00130 PRINT_DEBUG("\t%d Contains %d loops (back edges) from %d", getIndex(),numberOfLoops,numOfBasicBlocks);
00131
00132 if(numberOfLoops){
00133 loops = new Loop*[numberOfLoops];
00134 uint32_t i = 0;
00135 while(!loopList.empty()){
00136 loops[i++] = loopList.shift();
00137 }
00138 ASSERT(numberOfLoops == i);
00139
00140 qsort(loops,numberOfLoops,sizeof(Loop*),compareLoopHeaderVaddr);
00141 for(i=0;i<numberOfLoops;i++){
00142 loops[i]->setIndex(i);
00143 }
00144 }
00145 ASSERT(!loopList.size());
00146
00147 DEBUG_MORE(printInnerLoops());
00148 }
00149
00150 BasicBlock* FlowGraph::getEntryBlock(){
00151 for (uint32_t i = 0; i < numOfBasicBlocks; i++){
00152 if (basicBlocks[i]->isEntry()){
00153 return basicBlocks[i];
00154 }
00155 }
00156 ASSERT(0 && "No entry block found");
00157 return NULL;
00158 }
00159
00160 MemoryOperation::MemoryOperation(Instruction insn,uint64_t addr,BasicBlock* bb,uint32_t idx)
00161 : instruction(insn),basicBlock(bb),index(idx)
00162 {
00163 ASSERT(insn.isMemoryOperation() &&
00164 "FATAL : Only the memory instructions can form memory operation");
00165 offset = (uint32_t)(addr-basicBlock->getBaseAddress());
00166 hashCode = HashCode(basicBlock->getFlowGraph()->getRawSection()->getIndex(),
00167 basicBlock->getFlowGraph()->getFunction()->getIndex(),
00168 basicBlock->getIndex(),
00169 index);
00170 }
00171
00172 Operand MemoryOperation::getAddressOperand1(){
00173 uint32_t src1 = 0;
00174 if(isDForm() || isDsForm())
00175 src1 = instruction.getDFormSrc1();
00176 else if(isXForm())
00177 src1 = instruction.getXFormSrc1();
00178
00179 if(src1)
00180 return Operand::GPRegisterOperands[src1];
00181
00182 return Operand::IntegerOperand0;
00183 }
00184
00185 Operand MemoryOperation::getAddressOperand2(){
00186 if(isDForm() || isDsForm()) {
00187 int32_t offset = instruction.getDFormImmediate();
00188 if(isDsForm())
00189 offset = instruction.getDsFormImmediate();
00190 return IntegerOperand(offset);
00191 } else if(isXForm()){
00192 uint32_t src2 = instruction.getXFormSrc2();
00193 if(instruction.isMemoryXFormButNoSrc2())
00194 return Operand::IntegerOperand0;
00195 else
00196 return Operand::GPRegisterOperands[src2];
00197 }
00198 return Operand::IntegerOperand0;
00199 }
00200 bool MemoryOperation::isDForm(){
00201 return instruction.isMemoryDForm();
00202 }
00203 bool MemoryOperation::isDsForm(){
00204 return instruction.isMemoryDsForm();
00205 }
00206 bool MemoryOperation::isXForm(){
00207 return instruction.isMemoryXForm();
00208 }
00209 void MemoryOperation::print(){
00210 PRINT_INFOR("\t(mem %#12llx) (idx %4d) (unq %#12llx)",
00211 offset+basicBlock->getBaseAddress(),index,getHashCode().getValue());
00212 getAddressOperand1().print();
00213 getAddressOperand2().print();
00214 }
00215
00216 uint64_t MemoryOperation::getInsnAddr(){
00217 return (offset + basicBlock->getBaseAddress());
00218 }
00219
00220 void BasicBlock::addEdge(BasicBlock* to)
00221 {
00222 ASSERT(to && "FATAL : Invalid block is being added as an edge");
00223 if(isJumpTable() || to->isJumpTable() || isTrace() || to->isTrace()){
00224 PRINT_DEBUG("Inserting edge between JumpTable/TraceBack");
00225 return;
00226 }
00227 }
00228
00229 AddressIterator BasicBlock::getInstructionIterator(){
00230 return AddressIterator::newAddressIteratorWord(baseAddress,sizeInBytes);
00231 }
00232
00233 RawSection* BasicBlock::getRawSection(){
00234 return flowGraph->getRawSection();
00235 }
00236
00237 void BasicBlock::findMemoryFloatOps(){
00238 if(isTrace() || isJumpTable())
00239 return;
00240
00241 uint32_t insnCount = 0;
00242 numOfMemoryOps = 0;
00243
00244 MemoryOperation** insnArr = new MemoryOperation*[getInstructionCount()];
00245
00246 AddressIterator ait = getInstructionIterator();
00247 while(ait.hasMore()){
00248 insnCount++;
00249 Instruction insn = getRawSection()->readInstruction(&ait);
00250 if(insn.isMemoryOperation() && !insn.isUnhandledMemoryOp()){
00251 insnArr[numOfMemoryOps] = new MemoryOperation(insn,*ait,this,numOfMemoryOps);
00252 numOfMemoryOps++;
00253 } else if(insn.isFloatPOperation()){
00254 numOfFloatPOps++;
00255 } else if(insn.isUnhandledMemoryOp()){
00256 PRINT_INFOR("Unhandled memop bits of block %#llx, %dth instruction,\taddr %#llx\tvalue %x",
00257 getBaseAddress(), insnCount, *ait, insn.bits());
00258
00259 }
00260 ait++;
00261 }
00262
00263 if(numOfMemoryOps){
00264 memoryOps = new MemoryOperation*[numOfMemoryOps];
00265 for(uint32_t i=0;i<numOfMemoryOps;i++){
00266 memoryOps[i] = insnArr[i];
00267 }
00268 }
00269
00270 delete[] insnArr;
00271 }
00272
00273 void BasicBlock::print(){
00274 PRINT_INFOR("[B(idx %5d) (adr %#12llx,%#12llx) (sz %4d) (unq %#12llx) (dom %d) (flgs %#8x)",
00275 index,baseAddress,(baseAddress+sizeInBytes),sizeInBytes,
00276 getHashCode().getValue(),immDominatedBy ? immDominatedBy->getIndex() : -1,
00277 flags);
00278
00279 for(uint32_t i=0;i<numOfTargets;i++){
00280 BasicBlock* bb = targets[i];
00281 PRINT_INFOR("\t(tgt %5d)",bb->getIndex());
00282 }
00283
00284 for(uint32_t i=0;i<numOfSources;i++){
00285 BasicBlock* bb = sources[i];
00286 PRINT_INFOR("\t(src %5d)",bb->getIndex());
00287 }
00288
00289
00290 PRINT_INFOR("\t(inst %5d) (mops %3d) (fops %3d)",getInstructionCount(),numOfMemoryOps,numOfFloatPOps);
00291 for(uint32_t i=0;i<numOfMemoryOps;i++){
00292 memoryOps[i]->print();
00293 }
00294
00295 AddressIterator ait = getInstructionIterator();
00296 while(ait.hasMore()){
00297 Instruction insn = getRawSection()->readInstruction(&ait);
00298 insn.print(*ait,getXCoffFile()->is64Bit());
00299 ait++;
00300 }
00301 PRINT_INFOR("]");
00302 }
00303
00304 void BasicBlock::setIndex(uint32_t idx){
00305 index = idx;
00306 hashCode = HashCode(flowGraph->getRawSection()->getIndex(),
00307 flowGraph->getFunction()->getIndex(),
00308 index);
00309
00310 ASSERT(hashCode.isBlock() && "FATAL : the has code for the block is not right");
00311 }
00312
00313 RawSection* FlowGraph::getRawSection(){
00314 return function->getRawSection();
00315 }
00316
00317 uint32_t FlowGraph::getIndex() {
00318 return function->getIndex();
00319 }
00320
00321 uint32_t FlowGraph::getAllBlocks(BasicBlock** arr){
00322 for(uint32_t i=0;i<numOfBasicBlocks;i++)
00323 arr[i] = basicBlocks[i];
00324 return numOfBasicBlocks;
00325 }
00326
00327 uint32_t FlowGraph::initializeAllBlocks(BasicBlock** blockArray,BasicBlock* traceBlock,uint32_t arrCount){
00328
00329 ASSERT("blockArray has to be sorted interms of block base addresses");
00330
00331 uint32_t totalCount = (traceBlock ? 1 : 0);
00332
00333 for(uint32_t i=0;i<arrCount;i++){
00334 if(blockArray[i]){
00335 totalCount++;
00336 }
00337 }
00338
00339 if(totalCount){
00340
00341 numOfBasicBlocks = totalCount;
00342 basicBlocks = new BasicBlock*[totalCount];
00343
00344 if(traceBlock){
00345 totalCount--;
00346 traceBlock->setIndex(totalCount);
00347 basicBlocks[totalCount] = traceBlock;
00348 }
00349
00350 uint32_t idx = 0;
00351 for(uint32_t i = 0;idx<totalCount;i++){
00352 BasicBlock* bb = blockArray[i];
00353 if(!bb)
00354 continue;
00355 bb->setIndex(idx);
00356 basicBlocks[idx++] = bb;
00357 }
00358 }
00359
00360 return numOfBasicBlocks;
00361 }
00362
00363 void FlowGraph::findMemoryFloatOps(){
00364 if(!numOfBasicBlocks)
00365 return;
00366
00367 for(uint32_t i=0;i<numOfBasicBlocks;i++){
00368 basicBlocks[i]->findMemoryFloatOps();
00369 }
00370 }
00371
00372
00373 void FlowGraph::print(){
00374 PRINT_INFOR("[G(idx %5d) (#bb %6d) (unq %#12llx)",
00375 getIndex(),numOfBasicBlocks,function->getHashCode().getValue());
00376
00377 if(!numOfBasicBlocks){
00378 PRINT_INFOR("]");
00379 return;
00380 }
00381
00382 for(uint32_t i=0;i<numOfBasicBlocks;i++){
00383 basicBlocks[i]->print();
00384 }
00385
00386 PRINT_INFOR("]");
00387
00388 for (uint32_t i = 0; i < numberOfLoops; i++){
00389 loops[i]->print();
00390 }
00391 }
00392
00393 BitSet<BasicBlock*>* FlowGraph::newBitSet() {
00394 if(numOfBasicBlocks)
00395 return new BitSet<BasicBlock*>(numOfBasicBlocks,basicBlocks);
00396 return NULL;
00397 }
00398
00399 Function::Function(uint32_t idx,uint32_t symCount,Symbol** symbols,RawSection* sect)
00400 : rawSection(sect),index(idx),numOfAllSymbols(symCount),insnSizeInBytes(0),
00401 flowGraph(NULL) {
00402
00403 ASSERT(numOfAllSymbols && "FATAL : there should be at least one symbol for the function");
00404
00405 allSymbols = new Symbol*[numOfAllSymbols];
00406
00407 for(uint32_t i=0;i<numOfAllSymbols;i++){
00408 allSymbols[i] = symbols[i];
00409 }
00410 for(uint32_t i=0;i<numOfAllSymbols;i++){
00411 ASSERT(allSymbols[0]->GET(n_value) == allSymbols[i]->GET(n_value));
00412 }
00413
00414 SymbolTable* symbolTable = rawSection->getSymbolTable();
00415 ASSERT(symbolTable && "FATAL : Every raw section should have the same symbol table not NULL");
00416
00417 baseAddress = allSymbols[0]->GET(n_value);
00418 sizeInBytes = (uint32_t)(symbolTable->getSymbolLength(allSymbols[0]));
00419
00420 hashCode = HashCode(rawSection->getIndex(),index);
00421 ASSERT(hashCode.isFunction() && "FATAL : the has code for the function is not right");
00422
00423 }
00424
00425 uint32_t Function::getAllSymbolNames(char* buffer,uint32_t len,bool onlyFirst){
00426 uint32_t ret = 0;
00427 uint32_t howMany = numOfAllSymbols;
00428 if(onlyFirst){
00429 howMany = 1;
00430 }
00431 SymbolTable* symbolTable = rawSection->getSymbolTable();
00432 if(buffer && len){
00433 char* ptr = buffer;
00434 for(uint32_t i=0;i<howMany;i++){
00435 char* name = symbolTable->getSymbolName(allSymbols[i]);
00436 uint32_t namelen = strlen(name);
00437
00438 namelen = (len < namelen ? len : namelen);
00439 strncpy(ptr,name,namelen);
00440 ptr += namelen;
00441 len -= namelen;
00442 free(name);
00443
00444 if(!len){
00445 ptr--;
00446 break;
00447 }
00448 if(i != (howMany-1)){
00449 *ptr = ' ';
00450 ptr++;
00451 len--;
00452 }
00453 }
00454 *ptr = '\0';
00455 ret = (uint32_t)(ptr-buffer);
00456 }
00457 return ret;
00458 }
00459
00460 void Function::print(){
00461 SymbolTable* symbolTable = rawSection->getSymbolTable();
00462
00463 PRINT_INFOR("");
00464 PRINT_INFOR("[F(idx %5d) (bsz %#12llx,%5d) (trb %5d,%5d) (unq %#12llx)",
00465 index,baseAddress,sizeInBytes,insnSizeInBytes,sizeInBytes-insnSizeInBytes,
00466 getHashCode().getValue());
00467
00468 for(uint32_t i=0;i<numOfAllSymbols;i++){
00469 char* name = symbolTable->getSymbolName(allSymbols[i]);
00470 uint64_t symSize = symbolTable->getSymbolLength(allSymbols[i]);
00471
00472 DemangleWrapper wrapper;
00473 char* demangled = wrapper.demangle_combined(name);
00474
00475 PRINT_INFOR("\t(sym %3lld,%3d,%s)",symSize,symbolTable->getStorageMapping(allSymbols[i]),demangled);
00476
00477 free(name);
00478 }
00479
00480 if(flowGraph)
00481 flowGraph->print();
00482
00483 PRINT_INFOR("]");
00484 PRINT_INFOR("");
00485 }
00486
00487 void Function::updateInstructionSize(){
00488
00489 insnSizeInBytes = sizeInBytes;
00490
00491 AddressIterator ait = getAddressIterator();
00492
00493 while(ait.hasMore()){
00494 Instruction insn = rawSection->readInstruction(&ait);
00495 if(insn.isZero()){
00496 break;
00497 }
00498 ++ait;
00499 }
00500
00501 if(ait.hasMore()){
00502 insnSizeInBytes = (uint32_t)(ait.getOffset());
00503 }
00504 }
00505
00506 bool Function::getJumpTableInformation(uint64_t* jumpTableAddr,
00507 uint32_t* jumpTableEntryCount,
00508 AddressIterator ait)
00509 {
00510 *jumpTableAddr = 0;
00511 *jumpTableEntryCount = 0;
00512
00513 ASSERT(ait.hasMore());
00514
00515 if(!ait.hasPrev()){
00516 return false;
00517 }
00518
00519 Instruction jumpInst = rawSection->readInstruction(&ait);
00520
00521 ait--; ait--;
00522
00523 int32_t additionalOffset = 0;
00524 bool jumpRequiresOneMoreIndir = false;
00525 uint32_t tocBaseRegister = INVALID_REGISTER;
00526
00527 if(ait.hasMore()){
00528 Instruction prevInst = rawSection->readInstruction(&ait);
00529 if(jumpInst.isIndirectJumpCtr()){
00530 if(!prevInst.isAddBeforeJump()){
00531 return false;
00532 }
00533 } else if(jumpInst.isIndirectJumpLnk()){
00534 if(!prevInst.isLoadBeforeJump()){
00535 return false;
00536 } else {
00537 tocBaseRegister = prevInst.getLoadBeforeJumpSrc1();
00538 ait--;
00539 if(ait.hasMore()){
00540 prevInst = rawSection->readInstruction(&ait);
00541 if(prevInst.definesJTBaseAddrIndir()){
00542 additionalOffset = prevInst.getJTBaseAddrIndirOffset();
00543 tocBaseRegister = prevInst.getJTBaseAddrIndirSrc();
00544 jumpRequiresOneMoreIndir = true;
00545 }
00546 }
00547 }
00548
00549 }
00550 }
00551
00552 bool isCountSet = false;
00553 bool isAddrSet = false;
00554
00555 while(ait.hasMore()){
00556 Instruction insn = rawSection->readInstruction(&ait);
00557
00558 if(!*jumpTableEntryCount && insn.definesJTEntryCount()){
00559 *jumpTableEntryCount = insn.getJTEntryCount() + 1;
00560 isCountSet = true;
00561 }
00562
00563 if(!*jumpTableAddr && insn.definesJTBaseAddress()){
00564 if((tocBaseRegister == INVALID_REGISTER) ||
00565 (insn.getJTBaseAddrTarget() == tocBaseRegister))
00566 {
00567 int32_t TOCoffset = insn.getJTBaseOffsetTOC();
00568 *jumpTableAddr = getXCoffFile()->readTOC(TOCoffset);
00569 isAddrSet = true;
00570 if(jumpRequiresOneMoreIndir){
00571 PRINT_DEBUG("JMPINDIR one more indirection common to xlC");
00572 *jumpTableAddr += additionalOffset;
00573 }
00574 }
00575 }
00576
00577 if(isAddrSet && isCountSet){
00578 return true;
00579 }
00580
00581 ait--;
00582 }
00583
00584 return false;
00585 }
00586
00587 void Function::parseJumpTable(AddressIterator dait,
00588 BasicBlock** allBlocks,
00589 BasicBlock* currBlock,
00590 LinkedList<uint32_t>* outgoingEdgeBags,
00591 LinkedList<uint32_t>* incomingEdgeBags)
00592 {
00593 dait--;
00594
00595 Instruction insn = rawSection->readInstruction(&dait);
00596
00597 uint64_t jumpTableAddr = 0;
00598 uint32_t jumpTableEntryCount = 0;
00599
00600 if(getJumpTableInformation(&jumpTableAddr,&jumpTableEntryCount,dait)){
00601
00602 PRINT_DEBUG("JUMP TABLE : %#112llx %#12llx %d",*dait,jumpTableAddr,jumpTableEntryCount);
00603
00604 RawSection* jumpTableSect = getXCoffFile()->findRawSection(jumpTableAddr);
00605
00606 if(jumpTableSect &&
00607 (jumpTableSect->IS_SECT_TYPE(TEXT) || jumpTableSect->IS_SECT_TYPE(DATA))){
00608 AddressIterator jumpTableIt = jumpTableSect->getAddressIterator();
00609 jumpTableIt.skipTo(jumpTableAddr);
00610 for(uint32_t i=0;i<jumpTableEntryCount;i++){
00611 uint64_t leaderAddr = jumpTableSect->readBytes(&jumpTableIt);
00612 if(insn.isIndirectJumpCtr()){
00613 leaderAddr += jumpTableAddr;
00614 }
00615 if(instructionInRange(leaderAddr)){
00616 uint32_t insnIndex = getInstructionIndex(leaderAddr);
00617 if(!allBlocks[insnIndex]){
00618 allBlocks[insnIndex] = new BasicBlock(flowGraph,leaderAddr);
00619 }
00620 if(currBlock){
00621 BasicBlock* toBlock = allBlocks[insnIndex];
00622 outgoingEdgeBags[currBlock->getIndex()].insert(toBlock->getIndex());
00623 incomingEdgeBags[toBlock->getIndex()].insert(currBlock->getIndex());
00624 }
00625
00626 PRINT_DEBUG("\tLeader : %#12llx JMP",leaderAddr);
00627 jumpTableIt++;
00628 }
00629 }
00630 }
00631
00632 if(currBlock)
00633 return;
00634
00635 if(instructionInRange(jumpTableAddr)){
00636 uint32_t insnIndex = getInstructionIndex(jumpTableAddr);
00637 BasicBlock* jumpTableBlock = allBlocks[insnIndex];
00638 if(!jumpTableBlock){
00639 jumpTableBlock = new BasicBlock(flowGraph,jumpTableAddr);
00640 allBlocks[insnIndex] = jumpTableBlock;
00641 }
00642 jumpTableBlock->setJumpTable();
00643 jumpTableBlock->setNoPath();
00644 jumpTableBlock->setSizeInBytes(jumpTableEntryCount*dait.unit());
00645 }
00646 }
00647 }
00648
00649 FlowGraph* Function::getFlowGraph(){
00650 return flowGraph;
00651 }
00652
00653 void Function::generateCFG(){
00654
00655 TIMER(double t1 = timer());
00656
00657 DEBUG_MORE(
00658 PRINT_INFOR("********************************\n");
00659 print();
00660 );
00661
00662 flowGraph = new FlowGraph(this);
00663
00664 uint32_t instructionCount = getInstructionCount();
00665 BasicBlock** allBlocks = new BasicBlock*[instructionCount];
00666 for(uint32_t i=0;i<instructionCount;i++){
00667 allBlocks[i] = NULL;
00668 }
00669
00670 AddressIterator ait = getInstructionIterator();
00671
00672 if (!ait.hasMore()){
00673 PRINT_INFOR("Function %d has no instructions", index);
00674 return;
00675 }
00676 ASSERT(ait.hasMore() && "FATAL : There is a Function with no instructions");
00677
00678 allBlocks[0] = new BasicBlock(flowGraph,getBaseAddress());
00679 PRINT_DEBUG("\tLeader : %#12llx",getBaseAddress());
00680
00681 while(ait.hasMore()){
00682
00683 uint64_t insnAddr = *ait;
00684 Instruction insn = rawSection->readInstruction(&ait);
00685 uint32_t insnIndex = getInstructionIndex(insnAddr);
00686 BasicBlock* fromBlock = allBlocks[insnIndex];
00687
00688 ASSERT(!insn.isZero() && "FATAL : Instructions should not have 0 word in them");
00689
00690 if(fromBlock && fromBlock->isJumpTable()){
00691 ait.skip(fromBlock->getSizeInBytes());
00692 continue;
00693 }
00694
00695 ait++;
00696
00697 if(insn.definesLeaders()){
00698 uint64_t leaderAddr = *ait;
00699 if(instructionInRange(leaderAddr)){
00700 insnIndex = getInstructionIndex(leaderAddr);
00701 if(!allBlocks[insnIndex]){
00702 allBlocks[insnIndex] = new BasicBlock(flowGraph,leaderAddr);
00703 }
00704 PRINT_DEBUG("\tLeader : %#12llx",leaderAddr);
00705 }
00706 }
00707
00708 if(insn.hasTargetAddress()){
00709 uint64_t leaderAddr = insn.getTargetAddress(insnAddr);
00710 if(instructionInRange(leaderAddr)){
00711 insnIndex = getInstructionIndex(leaderAddr);
00712 if(!allBlocks[insnIndex]){
00713 allBlocks[insnIndex] = new BasicBlock(flowGraph,leaderAddr);
00714 }
00715 PRINT_DEBUG("\tLeader : %#12llx",leaderAddr);
00716 }
00717 } else if(insn.isIndirectJump()){
00718 uint64_t leaderAddr = *ait;
00719 if(instructionInRange(leaderAddr)){
00720 parseJumpTable(ait,allBlocks);
00721 }
00722 } else if(insn.isOtherBranch()){
00723 PRINT_ERROR("\tConditional Return/Call");
00724 PRINT_ERROR("\tConditional Indirect Call");
00725 PRINT_ERROR("\tConditional Indirect Branch");
00726 ASSERT(0 && "FATAL : There is a type of branch does is not handled");
00727 }
00728 }
00729
00730 BasicBlock* traceBackBlock = NULL;
00731 if(getSize() != getInstructionSize()){
00732 traceBackBlock = new BasicBlock(flowGraph,getBaseAddress()+getInstructionSize());
00733 traceBackBlock->setSizeInBytes(getSize()-getInstructionSize());
00734 traceBackBlock->setTrace();
00735 traceBackBlock->setNoPath();
00736 }
00737
00738 TIMER(double t2 = timer();cfg_s1+=(t2-t1);t1=t2);
00739
00740 uint32_t blockCount = flowGraph->initializeAllBlocks(allBlocks,traceBackBlock,instructionCount);
00741 if(!blockCount){
00742 delete[] allBlocks;
00743 return;
00744 }
00745
00746 LinkedList<uint32_t>* outgoingEdgeBags = new LinkedList<uint32_t>[blockCount];
00747 LinkedList<uint32_t>* incomingEdgeBags = new LinkedList<uint32_t>[blockCount];
00748
00749 BasicBlock* currBlock = NULL;
00750 bool prevInsnDefinesLeader = false;
00751
00752 allBlocks[0]->setEntry();
00753 ait.reset();
00754 while(ait.hasMore()){
00755
00756 uint64_t insnAddr = *ait;
00757 Instruction insn = rawSection->readInstruction(&ait);
00758 uint32_t insnIndex = getInstructionIndex(insnAddr);
00759 BasicBlock* nextBlock = allBlocks[insnIndex];
00760
00761 if(nextBlock){
00762 if(currBlock && !currBlock->isJumpTable()){
00763 currBlock->setSizeInBytes((uint32_t)(insnAddr-currBlock->getBaseAddress()));
00764 if(!prevInsnDefinesLeader){
00765 ASSERT(!nextBlock->isJumpTable() && "FATAL : Fallbacks to jump table???");
00766 BasicBlock* toBlock = nextBlock;
00767 outgoingEdgeBags[currBlock->getIndex()].insert(toBlock->getIndex());
00768 incomingEdgeBags[toBlock->getIndex()].insert(currBlock->getIndex());
00769 }
00770 }
00771
00772 currBlock = nextBlock;
00773
00774 if(currBlock->isJumpTable()){
00775 ait.skip(currBlock->getSizeInBytes());
00776 prevInsnDefinesLeader = false;
00777 continue;
00778 }
00779 }
00780
00781 ait++;
00782
00783 prevInsnDefinesLeader = false;
00784 if(insn.definesLeaders()){
00785 prevInsnDefinesLeader = true;
00786 }
00787
00788 if(insn.isCondBranch() || insn.isCondReturn() || insn.isCall()){
00789 uint64_t leaderAddr = *ait;
00790 if(instructionInRange(leaderAddr)){
00791 insnIndex = getInstructionIndex(leaderAddr);
00792 BasicBlock* toBlock = allBlocks[insnIndex];
00793 outgoingEdgeBags[currBlock->getIndex()].insert(toBlock->getIndex());
00794 incomingEdgeBags[toBlock->getIndex()].insert(currBlock->getIndex());
00795 } else {
00796 currBlock->setExit();
00797 }
00798 }
00799
00800 if(insn.hasTargetAddress()){
00801 uint64_t leaderAddr = insn.getTargetAddress(insnAddr);
00802 if(instructionInRange(leaderAddr)){
00803 insnIndex = getInstructionIndex(leaderAddr);
00804 BasicBlock* toBlock = allBlocks[insnIndex];
00805 outgoingEdgeBags[currBlock->getIndex()].insert(toBlock->getIndex());
00806 incomingEdgeBags[toBlock->getIndex()].insert(currBlock->getIndex());
00807 } else {
00808 currBlock->setExit();
00809 }
00810 } else if(insn.isIndirectJump()){
00811 uint64_t leaderAddr = *ait;
00812 if(instructionInRange(leaderAddr)){
00813 parseJumpTable(ait,allBlocks,currBlock,outgoingEdgeBags,incomingEdgeBags);
00814 } else {
00815 currBlock->setExit();
00816 }
00817 }
00818
00819 if(insn.isReturn()){
00820 currBlock->setExit();
00821 }
00822 }
00823
00824 TIMER(t2 = timer();cfg_s2+=(t2-t1);t1=t2);
00825
00826
00827 if(currBlock){
00828 currBlock->setSizeInBytes((uint32_t)((*ait)-currBlock->getBaseAddress()));
00829 }
00830
00831 PRINT_DEBUG("*** Found %d blocks for function %d\n",blockCount,getIndex());
00832
00833 BitSet<BasicBlock*>* edgeSet = flowGraph->newBitSet();
00834
00835 for(uint32_t i=0;i<blockCount;i++){
00836 BasicBlock* fromBlock = flowGraph->getBlock(i);
00837 LinkedList<uint32_t>* outgoingEdges = &(outgoingEdgeBags[fromBlock->getIndex()]);
00838 LinkedList<uint32_t>* incomingEdges = &(incomingEdgeBags[fromBlock->getIndex()]);
00839
00840 ASSERT(fromBlock && "FATAL : Basic block and its outgoing edges can not be NULL");
00841
00842 edgeSet->clear();
00843 while(!outgoingEdges->empty()){
00844 uint32_t bbidx = outgoingEdges->shift();
00845 edgeSet->insert(bbidx);
00846 }
00847 uint32_t numOfEdges = edgeSet->size();
00848 if(numOfEdges){
00849 fromBlock->setTargets(numOfEdges,edgeSet->duplicateMembers());
00850 }
00851
00852
00853 edgeSet->clear();
00854 while(!incomingEdges->empty()){
00855 uint32_t bbidx = incomingEdges->shift();
00856 edgeSet->insert(bbidx);
00857 }
00858 numOfEdges = edgeSet->size();
00859 if(numOfEdges){
00860 fromBlock->setSources(numOfEdges,edgeSet->duplicateMembers());
00861 }
00862 }
00863 delete[] outgoingEdgeBags;
00864 delete[] incomingEdgeBags;
00865
00866 TIMER(t2 = timer();cfg_s3+=(t2-t1);t1=t2);
00867
00868
00869 PRINT_DEBUG("Finding unreachable blocks in %d block for %d\n",blockCount,getIndex());
00870
00871 BasicBlock* root = allBlocks[0];
00872 edgeSet->setall();
00873
00874 flowGraph->depthFirstSearch(root,edgeSet,false);
00875
00876 uint32_t unreachableCount = edgeSet->size();
00877 if(unreachableCount){
00878 BasicBlock** unreachableBlocks = edgeSet->duplicateMembers();
00879 for(uint32_t i=0;i<unreachableCount;i++){
00880 unreachableBlocks[i]->setNoPath();
00881 PRINT_DEBUG("\tBlock %d is unreachable\n",unreachableBlocks[i]->getIndex());
00882 }
00883 delete[] unreachableBlocks;
00884 }
00885 PRINT_DEBUG("******** Found %d unreachable blocks for function %d with %d blocks\n",unreachableCount,getIndex(),blockCount);
00886
00887 delete edgeSet;
00888
00889 delete[] allBlocks;
00890
00891 TIMER(t2 = timer();cfg_s4+=(t2-t1);t1=t2);
00892
00893
00894 flowGraph->setImmDominatorBlocks(root);
00895
00896 DEBUG_MORE(
00897 print();
00898 PRINT_INFOR("********************************\n");
00899 );
00900
00901 TIMER(t2 = timer();cfg_s5=(t2-t1);t1=t2);
00902 }
00903
00904 void FlowGraph::setImmDominatorBlocks(BasicBlock* root){
00905
00906 if(!root){
00908 }
00909 ASSERT(root && root->isEntry() && "Fatal: The root node should be valid and entry to cfg");
00910
00911 LengauerTarjan dominatorAlg(getNumOfBasicBlocks(),root,getAllBlocks());
00912 dominatorAlg.immediateDominators();
00913 }
00914
00915 void FlowGraph::depthFirstSearch(BasicBlock* root,BitSet<BasicBlock*>* visitedSet,bool visitedMarkOnSet,
00916 BitSet<BasicBlock*>* completedSet,LinkedList<BasicBlock*>* backEdges)
00917 {
00918
00919 if(visitedMarkOnSet){
00920 visitedSet->insert(root->getIndex());
00921 } else {
00922 visitedSet->remove(root->getIndex());
00923 }
00924
00925 uint32_t numOfTargets = root->getNumOfTargets();
00926 for(uint32_t i=0;i<numOfTargets;i++){
00927 BasicBlock* target = root->getTargetBlock(i);
00928
00929 if(visitedMarkOnSet != visitedSet->contains(target->getIndex())){
00930 depthFirstSearch(target,visitedSet,visitedMarkOnSet,completedSet,backEdges);
00931 } else if(backEdges && completedSet &&
00932 (visitedMarkOnSet != completedSet->contains(target->getIndex())))
00933 {
00934 backEdges->insert(target);
00935 backEdges->insert(root);
00936 }
00937 }
00938
00939 if(completedSet){
00940 if(visitedMarkOnSet){
00941 completedSet->insert(root->getIndex());
00942 } else {
00943 completedSet->remove(root->getIndex());
00944 }
00945 }
00946 }
00947
00948 void Function::findMemoryFloatOps(){
00949 if(flowGraph){
00950 flowGraph->findMemoryFloatOps();
00951 }
00952 }
00953
00954 AddressIterator Function::getAddressIterator() {
00955 return AddressIterator::newAddressIteratorWord(baseAddress,sizeInBytes);
00956 }
00957
00958 AddressIterator Function::getInstructionIterator() {
00959 return AddressIterator::newAddressIteratorWord(baseAddress,insnSizeInBytes);
00960 }
00961
00962 XCoffFile* Function::getXCoffFile(){
00963 return rawSection->getXCoffFile();
00964 }
00965
00966 bool Function::isAnySymbolA(char* name){
00967 if(!name)
00968 return false;
00969
00970 SymbolTable* symbolTable = rawSection->getSymbolTable();
00971 for(uint32_t i=0;i<numOfAllSymbols;i++){
00972 char* symName = symbolTable->getSymbolName(allSymbols[i]);
00973 if(!strcmp(symName,name)){
00974 free(symName);
00975 return true;
00976 }
00977 free(symName);
00978 }
00979 return false;
00980 }
00981
00982 XCoffFile* FlowGraph::getXCoffFile(){
00983 return function->getXCoffFile();
00984 }
00985
00986 XCoffFile* BasicBlock::getXCoffFile(){
00987 return flowGraph->getXCoffFile();
00988 }
00989
00990 uint32_t FlowGraph::getNumOfMemoryOps() {
00991 uint32_t ret = 0;
00992 for(uint32_t i=0;i<numOfBasicBlocks;i++){
00993 BasicBlock* bb = basicBlocks[i];
00994 ret += bb->getNumOfMemoryOps();
00995 }
00996 return ret;
00997 }
00998
00999 uint32_t FlowGraph::getNumOfFloatPOps() {
01000 uint32_t ret = 0;
01001 for(uint32_t i=0;i<numOfBasicBlocks;i++){
01002 BasicBlock* bb = basicBlocks[i];
01003 ret += bb->getNumOfFloatPOps();
01004 }
01005 return ret;
01006 }
01007
01008 bool BasicBlock::findFirstInstPoint(uint64_t* addr){
01009 *addr = 0x0;
01010 AddressIterator ait = getInstructionIterator();
01011 while(ait.hasMore()){
01012 Instruction insn = getRawSection()->readInstruction(&ait);
01013 if(!insn.definesLeaders()){
01014 *addr = *ait;
01015 return true;
01016 }
01017 ait++;
01018 }
01019 return false;
01020 }
01021
01022 bool BasicBlock::isDominatedBy(BasicBlock* bb){
01023 if(!bb){
01024 return false;
01025 }
01026 BasicBlock* candidate = (BasicBlock*)this;
01027 while(candidate){
01028 if(candidate == bb){
01029 return true;
01030 }
01031 candidate = candidate->getImmDominator();
01032 }
01033 return false;
01034 }