void FlowGraph::interposeBlock(BasicBlock* bb){ ASSERT(bb->getNumberOfSources() == 1 && bb->getNumberOfTargets() == 1); BasicBlock* sourceBlock = bb->getSourceBlock(0); BasicBlock* targetBlock = bb->getTargetBlock(0); //sourceBlock->print(); //targetBlock->print(); bool linkFound = false; for (uint32_t i = 0; i < sourceBlock->getNumberOfTargets(); i++){ if (sourceBlock->getTargetBlock(i)->getIndex() == targetBlock->getIndex()){ linkFound = true; break; } } if (!linkFound){ function->print(); print(); sourceBlock->print(); targetBlock->print(); } ASSERT(linkFound && "There should be a source -> target block relationship between the blocks passed to this function"); ASSERT(sourceBlock->getBaseAddress() + sourceBlock->getNumberOfBytes() != targetBlock->getBaseAddress() && "Source shouldn't fall through to target"); bb->setBaseAddress(blocks.back()->getBaseAddress() + blocks.back()->getNumberOfBytes()); bb->setIndex(basicBlocks.size()); basicBlocks.append(bb); //PRINT_INFOR("now there are %d bbs in function %s", basicBlocks.size(), function->getName()); //PRINT_INFOR("new block has base addres %#llx", bb->getBaseAddress()); blocks.append(bb); sourceBlock->removeTargetBlock(targetBlock); sourceBlock->addTargetBlock(bb); targetBlock->removeSourceBlock(sourceBlock); targetBlock->addSourceBlock(bb); X86Instruction* jumpToTarget = bb->getLeader(); jumpToTarget->setBaseAddress(blocks.back()->getBaseAddress() + blocks.back()->getSizeInBytes()); jumpToTarget->setIndex(0); ASSERT(sourceBlock->getExitInstruction()); ASSERT(sourceBlock->getExitInstruction()->getAddressAnchor()); ASSERT(sourceBlock->getExitInstruction()->getTargetAddress() == targetBlock->getBaseAddress()); sourceBlock->getExitInstruction()->getAddressAnchor()->updateLink(jumpToTarget); //bb->print(); //bb->printInstructions(); }
void LengauerTarjan::immediateDominators(){ uint32_t dfsNo = 0; depthFirstSearch(rootLoc,&dfsNo); size[0] = 0; label[0] = 0; semi[0] = 0; for(int32_t i=reachableCount;i>1;i--){ uint32_t vertexW = vertex[i]; BasicBlock* bb = locToBasicBlock[vertexW]; ASSERT(bb && "Basic Block should be initialized"); uint32_t numberOfSources = bb->getNumberOfSources(); for(uint32_t j=0;j<numberOfSources;j++){ BasicBlock* source = bb->getSourceBlock(j); if(!source->isUnreachable()){ uint32_t vertexV = basicBlockToLoc[source->getIndex()]; uint32_t vertexU = EVAL(vertexV); if(semi[vertexU] < semi[vertexW]){ semi[vertexW] = semi[vertexU]; } } } bucket[vertex[semi[vertexW]]].insert(vertexW); LINK(parent[vertexW],vertexW); LinkedList<uint32_t>* bs = &(bucket[parent[vertexW]]); while(!bs->empty()){ uint32_t vertexV = bs->shift(); uint32_t vertexU = EVAL(vertexV); dom[vertexV] = ( semi[vertexU] < semi[vertexV] ) ? vertexU : parent[vertexW]; } } for(uint32_t i=2;i<=reachableCount;i++){ uint32_t vertexW = vertex[i]; if(dom[vertexW] != vertex[semi[vertexW]]){ dom[vertexW] = dom[dom[vertexW]]; } } dom[rootLoc] = 0; PRINT_DEBUG("ROOT is %d",rootLoc); for(uint32_t i=1;i<=reachableCount;i++){ uint32_t vertexW = vertex[i]; BasicBlock* bb = locToBasicBlock[vertexW]; ASSERT(!bb->isUnreachable()); BasicBlock* immDom = locToBasicBlock[dom[vertexW]]; if(immDom){ PRINT_DEBUG("Reachable : Immediate Dominator of %d is %d",bb->getIndex(),immDom->getIndex()); bb->setImmDominator(immDom); } else { PRINT_DEBUG("Reachable : Immediate Dominator of %d is Entry",bb->getIndex()); } } for(int32_t i=nodeCount;i>reachableCount;i--){ BasicBlock* bb = locToBasicBlock[i]; ASSERT(bb->isUnreachable()); BasicBlock* immDom = locToBasicBlock[rootLoc]; PRINT_DEBUG("Un-Reachable : Immediate Dominator of %d is %d",bb->getIndex(),immDom->getIndex()); bb->setImmDominator(immDom); } }
void LengauerTarjan::depthFirstSearch(uint32_t vertexV,uint32_t* dfsNo){ semi[vertexV] = ++(*dfsNo); vertex[*dfsNo] = vertexV; label[vertexV] = vertexV; ancestor[vertexV] = 0; child[vertexV] = 0; size[vertexV] = 1; BasicBlock* bb = locToBasicBlock[vertexV]; PRINT_DEBUG_CFG("Mark %d with %d (vertex[%d] = %d)",bb->getIndex(),*dfsNo,*dfsNo,vertexV); uint32_t numberOfTargets = bb->getNumberOfTargets(); for(uint32_t i=0;i<numberOfTargets;i++){ BasicBlock* target = bb->getTargetBlock(i); uint32_t vertexW = basicBlockToLoc[target->getIndex()]; if(semi[vertexW] == 0){ parent[vertexW] = vertexV; depthFirstSearch(vertexW,dfsNo); } } ASSERT(!bb->isUnreachable()); #if 0 LinkedList<uint32_t> searchStack; searchStack.insert(vertexV); while(!searchStack.empty()){ vertexV = searchStack.shift(); if(semi[vertexV] != 0){ continue; } semi[vertexV] = ++(*dfsNo); vertex[*dfsNo] = vertexV; label[vertexV] = vertexV; ancestor[vertexV] = 0; child[vertexV] = 0; size[vertexV] = 1; BasicBlock* bb = locToBasicBlock[vertexV]; ASSERT(!bb->isUnreachable()); uint32_t numberOfTargets = bb->getNumberOfTargets(); // for(int32_t i=numberOfTargets-1;i>=0;i--){ for(uint32_t i=0;i<numberOfTargets;i++){ BasicBlock* target = bb->getTargetBlock(i); uint32_t vertexW = basicBlockToLoc[target->getIndex()]; if(semi[vertexW] == 0){ parent[vertexW] = vertexV; searchStack.insert(vertexW); } } PRINT_DEBUG("Mark %d with %d\n",bb->getIndex(),*dfsNo); ASSERT(!bb->isUnreachable()); } #endif }
void TauFunctionTrace::instrument(){ //InstrumentationTool::instrument(); LineInfoFinder* lineInfoFinder = NULL; if (hasLineInformation()){ lineInfoFinder = getLineInfoFinder(); } InstrumentationPoint* p; uint64_t nameAddr = reserveDataOffset(sizeof(uint64_t)); uint64_t fileAddr = reserveDataOffset(sizeof(uint64_t)); uint64_t lineAddr = reserveDataOffset(sizeof(uint32_t)); uint64_t siteIndexAddr = reserveDataOffset(sizeof(uint32_t)); uint32_t site = functionEntry->addConstantArgument(); ASSERT(site == functionExit->addConstantArgument()); std::pebil_map_type<uint64_t, ControlInfo> functions; std::vector<uint64_t> orderedfuncs; uint32_t sequenceId = 0; if (doIntro){ // go over all functions and intrument entries/exits for (uint32_t i = 0; i < getNumberOfExposedFunctions(); i++){ Function* function = getExposedFunction(i); uint64_t addr = function->getBaseAddress(); if (instrumentList && !instrumentList->functionMatches(function->getName())){ continue; } if (!strcmp(function->getName(), "_fini")){ continue; } BasicBlock* entryBlock = function->getFlowGraph()->getEntryBlock(); Vector<BasicBlock*>* exitPoints = function->getFlowGraph()->getExitBlocks(); std::string c; c.append(function->getName()); if (c == "_start"){ exitPoints->append(getProgramExitBlock()); PRINT_INFOR("Special case: inserting exit for _start inside _fini since control generally doesn't reach its exit"); } ASSERT(functions.count(addr) == 0 && "Multiple functions have the same base address?"); PRINT_INFOR("[FUNCTION index=%d] internal instrumentation: %s", sequenceId, function->getName()); ControlInfo f = ControlInfo(); f.name = c; f.file = ""; f.line = 0; f.index = sequenceId++; f.baseaddr = addr; f.type = ControlType_Function; LineInfo* li = NULL; if (lineInfoFinder){ li = lineInfoFinder->lookupLineInfo(addr); } if (li){ f.file.append(li->getFileName()); f.line = li->GET(lr_line); } functions[addr] = f; orderedfuncs.push_back(addr); InstrumentationPoint* prior = addInstrumentationPoint(entryBlock->getLeader(), functionEntry, InstrumentationMode_tramp, InstLocation_prior); prior->setPriority(InstPriority_custom3); assignStoragePrior(prior, f.index, site); for (uint32_t j = 0; j < exitPoints->size(); j++){ InstrumentationPoint* after = addInstrumentationPoint((*exitPoints)[j]->getExitInstruction(), functionExit, InstrumentationMode_tramp, InstLocation_prior); after->setPriority(InstPriority_custom5); if (c == "_start" && j == exitPoints->size() - 1){ after->setPriority(InstPriority_custom6); } assignStoragePrior(after, f.index, site); } delete exitPoints; } } else { // go over all instructions. when we find a call, instrument it for (uint32_t i = 0; i < getNumberOfExposedInstructions(); i++){ X86Instruction* x = getExposedInstruction(i); ASSERT(x->getContainer()->isFunction()); Function* function = (Function*)x->getContainer(); if (x->isFunctionCall()){ uint64_t addr = x->getTargetAddress(); Symbol* functionSymbol = getElfFile()->lookupFunctionSymbol(addr); if (functionSymbol){ if (instrumentList && !instrumentList->functionMatches(functionSymbol->getSymbolName())){ continue; } ASSERT(x->getSizeInBytes() == Size__uncond_jump); std::string c; c.append(functionSymbol->getSymbolName()); if (functions.count(addr) == 0){ PRINT_INFOR("[FUNCTION index=%d] call site instrumentation: %#lx(%s) -> %s", sequenceId, addr, function->getName(), functionSymbol->getSymbolName()); ControlInfo f = ControlInfo(); f.name = c; f.file = ""; f.line = 0; f.index = sequenceId++; f.baseaddr = addr; f.type = ControlType_Function; LineInfo* li = NULL; if (lineInfoFinder){ li = lineInfoFinder->lookupLineInfo(addr); } if (li){ f.file.append(li->getFileName()); f.line = li->GET(lr_line); } functions[addr] = f; orderedfuncs.push_back(addr); } uint32_t idx = functions[addr].index; Base* exitpoint = (Base*)x; if (c == "__libc_start_main"){ PRINT_INFOR("Special case: inserting exit for __libc_start_main inside _fini since this call generally doesn't return"); exitpoint = (Base*)getProgramExitBlock(); } InstrumentationPoint* prior = addInstrumentationPoint(x, functionEntry, InstrumentationMode_tramp, InstLocation_prior); InstrumentationPoint* after = addInstrumentationPoint(exitpoint, functionExit, InstrumentationMode_tramp, InstLocation_after); assignStoragePrior(prior, idx, site); assignStoragePrior(after, idx, site); } } } } // set up argument passing for function registration functionRegister->addArgument(nameAddr); functionRegister->addArgument(fileAddr); functionRegister->addArgument(lineAddr); uint32_t siteReg = functionRegister->addConstantArgument(); // go over every function that was found, insert a registration call at program start for (std::vector<uint64_t>::iterator it = orderedfuncs.begin(); it != orderedfuncs.end(); it++){ uint64_t addr = *it; ControlInfo f = functions[addr]; ASSERT(f.baseaddr == addr); InstrumentationPoint* p = addInstrumentationPoint(getProgramEntryBlock(), functionRegister, InstrumentationMode_tramp); p->setPriority(InstPriority_custom1); const char* cstring = f.name.c_str(); uint64_t storage = reserveDataOffset(strlen(cstring) + 1); initializeReservedData(getInstDataAddress() + storage, strlen(cstring), (void*)cstring); assignStoragePrior(p, getInstDataAddress() + storage, getInstDataAddress() + nameAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); const char* cstring2 = f.file.c_str(); if (f.file == ""){ assignStoragePrior(p, NULL, getInstDataAddress() + fileAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); } else { storage = reserveDataOffset(strlen(cstring2) + 1); initializeReservedData(getInstDataAddress() + storage, strlen(cstring2), (void*)cstring2); assignStoragePrior(p, getInstDataAddress() + storage, getInstDataAddress() + fileAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); } assignStoragePrior(p, f.line, getInstDataAddress() + lineAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); assignStoragePrior(p, f.index, siteReg); } if (!instrumentList){ return; } // instrument loops std::pebil_map_type<uint64_t, ControlInfo> loops; std::vector<uint64_t> orderedloops; loopRegister->addArgument(nameAddr); loopRegister->addArgument(fileAddr); loopRegister->addArgument(lineAddr); ASSERT(siteReg == loopRegister->addConstantArgument()); for (uint32_t i = 0; i < getNumberOfExposedFunctions(); i++){ Function* function = getExposedFunction(i); FlowGraph* flowgraph = function->getFlowGraph(); if (!instrumentList->loopMatches(function->getName())){ continue; } for (uint32_t j = 0; j < flowgraph->getNumberOfLoops(); j++){ Loop* loop = flowgraph->getLoop(j); uint32_t depth = flowgraph->getLoopDepth(loop); BasicBlock* head = loop->getHead(); uint64_t addr = head->getBaseAddress(); // only want outer-most (depth == 1) loops if (depth != 1){ continue; } BasicBlock** allLoopBlocks = new BasicBlock*[loop->getNumberOfBlocks()]; loop->getAllBlocks(allLoopBlocks); // reject any loop that contains an indirect branch since it is difficult to guarantee that we will find all exits bool badLoop = false; for (uint32_t k = 0; k < loop->getNumberOfBlocks() && !badLoop; k++){ BasicBlock* bb = allLoopBlocks[k]; if (bb->getExitInstruction()->isIndirectBranch()){ badLoop = true; } } if (badLoop){ PRINT_WARN(20, "Loop at %#lx in %s contains an indirect branch so we can't guarantee that all exits will be found. skipping!", addr, function->getName()); delete[] allLoopBlocks; continue; } std::string c; c.append(function->getName()); uint32_t entryc = 0; Vector<LoopPoint*>* points = NULL; // if addr already exists, it means that two loops share a head and we are going to merge them logically here if (loops.count(addr) == 0){ ControlInfo f = ControlInfo(); f.name = c; f.file = ""; f.line = 0; f.index = sequenceId++; f.baseaddr = addr; f.type = ControlType_Loop; points = new Vector<LoopPoint*>(); f.info = points; LineInfo* li = NULL; if (lineInfoFinder){ li = lineInfoFinder->lookupLineInfo(addr); } if (li){ f.file.append(li->getFileName()); f.line = li->GET(lr_line); } loops[addr] = f; orderedloops.push_back(addr); // find entries into this loop for (uint32_t k = 0; k < head->getNumberOfSources(); k++){ BasicBlock* source = head->getSourceBlock(k); if (!loop->isBlockIn(source->getIndex())){ LoopPoint* lp = new LoopPoint(); points->append(lp); lp->flowgraph = flowgraph; lp->source = source; lp->target = NULL; lp->entry = true; lp->interpose = false; if (source->getBaseAddress() + source->getNumberOfBytes() != head->getBaseAddress()){ lp->interpose = true; lp->target = head; } entryc++; } } } ControlInfo f = loops[addr]; points = f.info; // find exits from this loop uint32_t exitc = 0; for (uint32_t k = 0; k < loop->getNumberOfBlocks(); k++){ BasicBlock* bb = allLoopBlocks[k]; if (bb->endsWithReturn()){ LoopPoint* lp = new LoopPoint(); points->append(lp); lp->flowgraph = flowgraph; lp->source = bb; lp->target = NULL; lp->entry = false; lp->interpose = false; exitc++; } for (uint32_t m = 0; m < bb->getNumberOfTargets(); m++){ BasicBlock* target = bb->getTargetBlock(m); if (!loop->isBlockIn(target->getIndex())){ LoopPoint* lp = new LoopPoint(); points->append(lp); lp->flowgraph = flowgraph; lp->source = bb; lp->target = NULL; lp->entry = false; lp->interpose = false; if (target->getBaseAddress() != bb->getBaseAddress() + bb->getNumberOfBytes()){ lp->interpose = true; lp->target = target; } exitc++; } } } PRINT_INFOR("[LOOP index=%d] loop instrumentation %#lx(%s) has %d entries and %d exits", sequenceId-1, addr, function->getName(), entryc, exitc); delete[] allLoopBlocks; } } // go over every loop that was found, insert a registration call at program start // [source_addr -> [target_addr -> interposed]] std::pebil_map_type<uint64_t, std::pebil_map_type<uint64_t, BasicBlock*> > idone; for (std::vector<uint64_t>::iterator it = orderedloops.begin(); it != orderedloops.end(); it++){ uint64_t addr = *it; ControlInfo f = loops[addr]; ASSERT(f.baseaddr == addr); InstrumentationPoint* p = addInstrumentationPoint(getProgramEntryBlock(), loopRegister, InstrumentationMode_tramp); p->setPriority(InstPriority_custom2); const char* cstring = f.name.c_str(); uint64_t storage = reserveDataOffset(strlen(cstring) + 1); initializeReservedData(getInstDataAddress() + storage, strlen(cstring), (void*)cstring); assignStoragePrior(p, getInstDataAddress() + storage, getInstDataAddress() + nameAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); const char* cstring2 = f.file.c_str(); if (f.file == ""){ assignStoragePrior(p, NULL, getInstDataAddress() + fileAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); } else { storage = reserveDataOffset(strlen(cstring2) + 1); initializeReservedData(getInstDataAddress() + storage, strlen(cstring2), (void*)cstring2); assignStoragePrior(p, getInstDataAddress() + storage, getInstDataAddress() + fileAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); } assignStoragePrior(p, f.line, getInstDataAddress() + lineAddr, X86_REG_CX, getInstDataAddress() + getRegStorageOffset()); assignStoragePrior(p, f.index, siteReg); // now add instrumentation for each loop entry/exit Vector<LoopPoint*>* v = (Vector<LoopPoint*>*)f.info; for (uint32_t i = 0; i < v->size(); i++){ LoopPoint* lp = (*v)[i]; ASSERT(lp->flowgraph && lp->source); BasicBlock* bb = lp->source; if (lp->interpose){ ASSERT(lp->target); if (idone.count(lp->source->getBaseAddress()) == 0){ idone[lp->source->getBaseAddress()] = std::pebil_map_type<uint64_t, BasicBlock*>(); } if (idone[lp->source->getBaseAddress()].count(lp->target->getBaseAddress()) == 0){ idone[lp->source->getBaseAddress()][lp->target->getBaseAddress()] = initInterposeBlock(lp->flowgraph, lp->source->getIndex(), lp->target->getIndex()); } bb = idone[lp->source->getBaseAddress()][lp->target->getBaseAddress()]; } else { ASSERT(lp->target == NULL); } Base* pt = (Base*)bb; InstLocations loc = InstLocation_prior; // if exit block falls through, we must place the instrumentation point at the very end of the block if (!lp->entry && !lp->interpose){ pt = (Base*)bb->getExitInstruction(); if (!bb->getExitInstruction()->isReturn()){ loc = InstLocation_after; } } InstrumentationFunction* inf = functionExit; if (lp->entry){ inf = functionEntry; } InstrumentationPoint* p = addInstrumentationPoint(pt, inf, InstrumentationMode_tramp, loc); p->setPriority(InstPriority_custom4); assignStoragePrior(p, f.index, site); delete lp; } delete v; } }
void FlowGraph::computeDefUseDist(){ uint32_t fcnt = function->getNumberOfInstructions(); std::pebil_map_type<uint64_t, X86Instruction*> imap; std::pebil_map_type<uint64_t, BasicBlock*> bmap; std::pebil_map_type<uint64_t, LinkedList<X86Instruction::ReachingDefinition*>*> alliuses; std::pebil_map_type<uint64_t, LinkedList<X86Instruction::ReachingDefinition*>*> allidefs; for (uint32_t i = 0; i < basicBlocks.size(); i++){ BasicBlock* bb = basicBlocks[i]; for (uint32_t j = 0; j < bb->getNumberOfInstructions(); j++){ X86Instruction* x = bb->getInstruction(j); for (uint32_t k = 0; k < x->getSizeInBytes(); k++){ ASSERT(imap.count(x->getBaseAddress() + k) == 0); ASSERT(bmap.count(x->getBaseAddress() + k) == 0); imap[x->getBaseAddress() + k] = x; bmap[x->getBaseAddress() + k] = bb; } ASSERT(alliuses.count(x->getBaseAddress()) == 0); ASSERT(allidefs.count(x->getBaseAddress()) == 0); alliuses[x->getBaseAddress()] = x->getUses(); allidefs[x->getBaseAddress()] = x->getDefs(); } } // For each loop for (uint32_t i = 0; i < loops.size(); ++i) { BasicBlock** allLoopBlocks = new BasicBlock*[loops[i]->getNumberOfBlocks()]; loops[i]->getAllBlocks(allLoopBlocks); uint64_t loopLeader = loops[i]->getHead()->getBaseAddress(); // For each block for (uint32_t j = 0; j < loops[i]->getNumberOfBlocks(); ++j){ BasicBlock* bb = allLoopBlocks[j]; // For each instruction for (uint32_t k = 0; k < bb->getNumberOfInstructions(); ++k){ X86Instruction* ins = bb->getInstruction(k); // Skip the instruction if it can't define anything if (!ins->isIntegerOperation() && !ins->isFloatPOperation() && !ins->isMoveOperation()) { continue; } ASSERT(!ins->usesControlTarget()); singleDefUse(this, ins, bb, loops[i], imap, bmap, alliuses, allidefs, k, loopLeader, fcnt); } } delete[] allLoopBlocks; } // handle all non-loop blocks for (uint32_t i = 0; i < getNumberOfBasicBlocks(); i++){ BasicBlock* bb = basicBlocks[i]; if (!isBlockInLoop(bb->getIndex())){ for (uint32_t k = 0; k < bb->getNumberOfInstructions(); ++k){ X86Instruction* ins = bb->getInstruction(k); if (!ins->isIntegerOperation() && !ins->isFloatPOperation() && !ins->isMoveOperation()) { continue; } ASSERT(!ins->usesControlTarget()); singleDefUse(this, ins, bb, NULL, imap, bmap, alliuses, allidefs, k, 0, fcnt); } } } for (uint32_t i = 0; i < basicBlocks.size(); i++){ BasicBlock* bb = basicBlocks[i]; for (uint32_t j = 0; j < bb->getNumberOfInstructions(); j++){ X86Instruction* x = bb->getInstruction(j); uint64_t addr = x->getBaseAddress(); ASSERT(alliuses.count(addr) == 1); LinkedList<X86Instruction::ReachingDefinition*>* l = alliuses[addr]; alliuses.erase(addr); while (!l->empty()){ delete l->shift(); } delete l; ASSERT(allidefs.count(addr) == 1); l = allidefs[addr]; allidefs.erase(addr); while (!l->empty()){ delete l->shift(); } delete l; } } ASSERT(alliuses.size() == 0); ASSERT(allidefs.size() == 0); }
inline void singleDefUse(FlowGraph* fg, X86Instruction* ins, BasicBlock* bb, Loop* loop, std::pebil_map_type<uint64_t, X86Instruction*>& ipebil_map_type, std::pebil_map_type<uint64_t, BasicBlock*>& bpebil_map_type, std::pebil_map_type<uint64_t, LinkedList<X86Instruction::ReachingDefinition*>*>& alliuses, std::pebil_map_type<uint64_t, LinkedList<X86Instruction::ReachingDefinition*>*>& allidefs, int k, uint64_t loopLeader, uint32_t fcnt){ // Get defintions for this instruction: ins LinkedList<X86Instruction::ReachingDefinition*>* idefs = ins->getDefs(); LinkedList<X86Instruction::ReachingDefinition*>* allDefs = idefs; // Skip instruction if it doesn't define anything if (idefs == NULL) { return; } if (idefs->empty()) { delete idefs; return; } set<LinkedList<X86Instruction::ReachingDefinition*>*> allDefLists; allDefLists.insert(idefs); PriorityQueue<struct path*, uint32_t> paths = PriorityQueue<struct path*, uint32_t>(); bool blockTouched[fg->getFunction()->getNumberOfBasicBlocks()]; bzero(&blockTouched, sizeof(bool) * fg->getFunction()->getNumberOfBasicBlocks()); // Initialize worklist with the path from this instruction // Only take paths inside the loop. Since the definitions are in a loop, uses in the loop will be most relevant. if (k == bb->getNumberOfInstructions() - 1){ ASSERT(ins->controlFallsThrough()); if (bb->getNumberOfTargets() > 0){ ASSERT(bb->getNumberOfTargets() == 1); if (flowsInDefUseScope(bb->getTargetBlock(0), loop)){ // Path flows to the first instruction of the next block paths.insert(new path(bb->getTargetBlock(0)->getLeader(), idefs), 1); } } } else { // path flows to the next instruction in this block paths.insert(new path(bb->getInstruction(k+1), idefs), 1); } // while there are paths in worklist while (!paths.isEmpty()) { // take the shortest path in list uint32_t currDist; struct path* p = paths.deleteMin(&currDist); X86Instruction* cand = p->ins; idefs = p->defs; delete p; LinkedList<X86Instruction::ReachingDefinition*>* i2uses, *i2defs, *newdefs; i2uses = alliuses[cand->getBaseAddress()]; // Check if any of idefs is used if(i2uses != NULL && anyDefsAreUsed(idefs, i2uses)){ // Check if use is shortest uint32_t duDist; duDist = trueDefUseDist(currDist, fcnt); if (!ins->getDefUseDist() || ins->getDefUseDist() > duDist) { ins->setDefUseDist(duDist); } // If dist has increased beyond size of function, we must be looping? if (currDist > fcnt) { ins->setDefXIter(); break; } // Stop searching along this path continue; } // Check if any defines are overwritten i2defs = allidefs[cand->getBaseAddress()]; newdefs = removeInvalidated(idefs, i2defs); // If all definitions killed, stop searching along this path if (newdefs == NULL) continue; allDefLists.insert(newdefs); // end of block that is a branch if (cand->usesControlTarget() && !cand->isCall()){ BasicBlock* tgtBlock = bpebil_map_type[cand->getTargetAddress()]; if (tgtBlock && !blockTouched[tgtBlock->getIndex()] && flowsInDefUseScope(tgtBlock, loop)){ blockTouched[tgtBlock->getIndex()] = true; if (tgtBlock->getBaseAddress() == loopLeader){ paths.insert(new path(tgtBlock->getLeader(), newdefs), loopXDefUseDist(currDist + 1, fcnt)); } else { paths.insert(new path(tgtBlock->getLeader(), newdefs), currDist + 1); } } } // non-branching control if (cand->controlFallsThrough()){ BasicBlock* tgtBlock = bpebil_map_type[cand->getBaseAddress() + cand->getSizeInBytes()]; if (tgtBlock && flowsInDefUseScope(tgtBlock, loop)){ X86Instruction* ftTarget = ipebil_map_type[cand->getBaseAddress() + cand->getSizeInBytes()]; if (ftTarget){ if (ftTarget->isLeader()){ if (!blockTouched[tgtBlock->getIndex()]){ blockTouched[tgtBlock->getIndex()] = true; if (ftTarget->getBaseAddress() == loopLeader){ paths.insert(new path(ftTarget, newdefs), loopXDefUseDist(currDist + 1, fcnt)); } else { paths.insert(new path(ftTarget, newdefs), currDist + 1); } } } else { paths.insert(new path(ftTarget, newdefs), currDist + 1); } } } } } if (!paths.isEmpty()){ ins->setDefUseDist(0); } while (!paths.isEmpty()){ delete paths.deleteMin(NULL); } while (!allDefs->empty()){ delete allDefs->shift(); } for(set<LinkedList<X86Instruction::ReachingDefinition*>*>::iterator it = allDefLists.begin(); it != allDefLists.end(); ++it){ delete *it; } }