extern shape_t* shapeConstructcircle( void* mem ) { void* adrs; shapecircle_t* circle = ( shapecircle_t* )mem; circle->shapeadt = circleAdt; adrs = nextAddress( mem, sizeof( shapecircle_t ), shapeSizeOf( "ellipse" ) ); circle->ellipse = shapeConstruct( adrs, "ellipse" ); return &circle->shapeadt; }
extern shape_t* shapeConstructellipse( void* mem ) { void* adrs; shapeellipse_t* ellipse = ( shapeellipse_t* )mem; ellipse->shapeadt = ellipseAdt; adrs = nextAddress( mem, sizeof( shapeellipse_t ), shapeSizeOf( "oval" ) ); ellipse->oval = shapeConstruct( adrs, "oval" ); return &ellipse->shapeadt; }
/*============================================================================== * FUNCTION: processProc * OVERVIEW: Process a procedure, given a native (source machine) address. * PARAMETERS: address - the address at which the procedure starts * delta - the offset of the above address from the logical * address at which the procedure starts (i.e. the one * given by dis) * uUpper - the highest address of the text segment * pProc - the procedure object * decoder - NJMCDecoder object * RETURNS: <nothing> *============================================================================*/ void processProc(ADDRESS uAddr, ptrdiff_t delta, ADDRESS uUpper, UserProc* pProc, NJMCDecoder& decoder) { PBB pBB; // Pointer to the current basic block INSTTYPE type; // Cfg type of instruction (e.g. IRET) // Declare a queue of targets not yet processed yet. This has to be // individual to the procedure! TARGETS targets; // Indicates whether or not the next instruction to be decoded is the // lexical successor of the current one. Will be true for all NCTs and for // CTIs with a fall through branch. bool sequentialDecode = true; Cfg* pCfg = pProc->getCFG(); // Initialise the queue of control flow targets that have yet to be decoded. targets.push(uAddr); // Clear the pointer used by the caller prologue code to access the last // call rtl of this procedure //decoder.resetLastCall(); while ((uAddr = nextAddress(targets, pCfg)) != 0) { // The list of RTLs for the current basic block list<HRTL*>* BB_rtls = new list<HRTL*>(); // Keep decoding sequentially until a CTI without a fall through branch // is decoded ADDRESS start = uAddr; DecodeResult inst; while (sequentialDecode) { // Decode and classify the current instruction if (progOptions.trace) cout << "*" << hex << uAddr << "\t" << flush; // Decode the inst at uAddr. inst = decoder.decodeInstruction(uAddr, delta, pProc); // Need to construct a new list of RTLs if a basic block has just // been finished but decoding is continuing from its lexical // successor if (BB_rtls == NULL) BB_rtls = new list<HRTL*>(); HRTL* pRtl = inst.rtl; if (inst.numBytes == 0) { // An invalid instruction. Most likely because a call did // not return (e.g. call _exit()), etc. Best thing is to // emit a INVALID BB, and continue with valid instructions ostrstream ost; ost << "invalid instruction at " << hex << uAddr; warning(str(ost)); // Emit the RTL anyway, so we have the address and maybe // some other clues BB_rtls->push_back(new RTL(uAddr)); pBB = pCfg->newBB(BB_rtls, INVALID, 0); sequentialDecode = false; BB_rtls = NULL; continue; } HLJump* rtl_jump = static_cast<HLJump*>(pRtl); // Display RTL representation if asked if (progOptions.rtl) pRtl->print(); ADDRESS uDest; switch (pRtl->getKind()) { case JUMP_HRTL: { uDest = rtl_jump->getFixedDest(); // Handle one way jumps and computed jumps separately if (uDest != NO_ADDRESS) { BB_rtls->push_back(pRtl); sequentialDecode = false; pBB = pCfg->newBB(BB_rtls,ONEWAY,1); // Exit the switch now and stop decoding sequentially if the // basic block already existed if (pBB == 0) { sequentialDecode = false; BB_rtls = NULL; break; } // Add the out edge if it is to a destination within the // procedure if (uDest < uUpper) { visit(pCfg, uDest, targets, pBB); pCfg->addOutEdge(pBB, uDest, true); } else { ostrstream ost; ost << "Error: Instruction at " << hex << uAddr; ost << " branches beyond end of section, to "; ost << uDest; error(str(ost)); } } break; } case NWAYJUMP_HRTL: { BB_rtls->push_back(pRtl); // We create the BB as a COMPJUMP type, then change // to an NWAY if it turns out to be a switch stmt pBB = pCfg->newBB(BB_rtls, COMPJUMP, 0); if (isSwitch(pBB, rtl_jump->getDest(), pProc, pBF)) { processSwitch(pBB, delta, pCfg, targets, pBF); } else // Computed jump { // Not a switch statement ostrstream ost; string sKind("JUMP"); if (type == I_COMPCALL) sKind = "CALL"; ost << "COMPUTED " << sKind << " at " << hex << uAddr << endl; warning(str(ost)); BB_rtls = NULL; // New HRTLList for next BB } sequentialDecode = false; break; } case JCOND_HRTL: { uDest = rtl_jump->getFixedDest(); BB_rtls->push_back(pRtl); pBB = pCfg->newBB(BB_rtls, TWOWAY, 2); // Stop decoding sequentially if the basic block already existed // otherwise complete the basic block if (pBB == 0) sequentialDecode = false; else { // Add the out edge if it is to a destination within the // procedure if (uDest < uUpper) { visit(pCfg, uDest, targets, pBB); pCfg->addOutEdge(pBB, uDest, true); } else { ostrstream ost; ost << "Error: Instruction at " << hex << uAddr; ost << " branches beyond end of section, to "; ost << uDest; error(str(ost)); } // Add the fall-through outedge pCfg->addOutEdge(pBB, uAddr + inst.numBytes); } // Create the list of RTLs for the next basic block and continue // with the next instruction. BB_rtls = NULL; break; } case CALL_HRTL: { HLCall* call = static_cast<HLCall*>(pRtl); // Treat computed and static calls seperately if (call->isComputed()) { BB_rtls->push_back(pRtl); pBB = pCfg->newBB(BB_rtls, COMPCALL, 1); // Stop decoding sequentially if the basic block already // existed otherwise complete the basic block if (pBB == 0) sequentialDecode = false; else pCfg->addOutEdge(pBB, uAddr + inst.numBytes); } else // Static call { BB_rtls->push_back(pRtl); // Find the address of the callee. ADDRESS uNewAddr = call->getFixedDest(); // Add this non computed call site to the set of call // sites which need to be analysed later. pCfg->addCall(call); // Record the called address as the start of a new // procedure if it didn't already exist. if ((uNewAddr != NO_ADDRESS) && prog.findProc(uNewAddr) == NULL) { prog.visitProc(uNewAddr); if (progOptions.trace) cout << "p" << hex << uNewAddr << "\t" << flush; } // Check if this is the _exit function. May prevent us from // attempting to decode invalid instructions. char* name = prog.pBF->SymbolByAddress(uNewAddr); if (name && strcmp(name, "_exit") == 0) { // Create the new basic block pBB = pCfg->newBB(BB_rtls, CALL, 0); // Stop decoding sequentially sequentialDecode = false; } else { // Create the new basic block pBB = pCfg->newBB(BB_rtls, CALL, 1); if (call->isReturnAfterCall()) { // Constuct the RTLs for the new basic block list<HRTL*>* rtls = new list<HRTL*>(); // The only RTL in the basic block is a high level // return that doesn't have any RTs. rtls->push_back(new HLReturn(0, NULL)); BasicBlock* returnBB = pCfg->newBB(rtls, RET, 0); // Add out edge from call to return pCfg->addOutEdge(pBB, returnBB); // Put a label on the return BB (since it's an // orphan); a jump will be reqd pCfg->setLabel(returnBB); pBB->setJumpReqd(); // Give the enclosing proc a dummy callee epilogue pProc->setEpilogue(new CalleeEpilogue("__dummy", list<string>())); // Mike: do we need to set return locations? // This ends the function sequentialDecode = false; } else { // Add the fall through edge if the block didn't // already exist if (pBB != NULL) pCfg->addOutEdge(pBB, uAddr + inst.numBytes); } } } // Create the list of RTLs for the next basic block and continue // with the next instruction. BB_rtls = NULL; break; } case RET_HRTL: // Stop decoding sequentially sequentialDecode = false; // Add the RTL to the list BB_rtls->push_back(pRtl); // Create the basic block pBB = pCfg->newBB(BB_rtls, RET, 0); // Create the list of RTLs for the next basic block and continue // with the next instruction. BB_rtls = NULL; // New HRTLList for next BB break; case SCOND_HRTL: // This is just an ordinary instruction; no control transfer // Fall through case LOW_LEVEL_HRTL: // We must emit empty RTLs for NOPs, because they could be the // destinations of jumps (and splitBB won't work) // Just emit the current instr to the current BB BB_rtls->push_back(pRtl); break; } // switch (pRtl->getKind()) uAddr += inst.numBytes; // Update the RTL's number of bytes for coverage analysis (only) inst.rtl->updateNumBytes(inst.numBytes); // If sequentially decoding, check if the next address happens to // be the start of an existing BB. If so, finish off the current BB // (if any RTLs) as a fallthrough, and no need to decode again // (unless it's an incomplete BB, then we do decode it). // In fact, mustn't decode twice, because it will muck up the // coverage, but also will cause subtle problems like add a call // to the list of calls to be processed, then delete the call RTL // (e.g. Pentium 134.perl benchmark) if (sequentialDecode && pCfg->existsBB(uAddr)) { // Create the fallthrough BB, if there are any RTLs at all if (BB_rtls) { PBB pBB = pCfg->newBB(BB_rtls, FALL, 1); // Add an out edge to this address if (pBB) { pCfg->addOutEdge(pBB, uAddr); BB_rtls = NULL; // Need new list of RTLs } } // Pick a new address to decode from, if the BB is complete if (!pCfg->isIncomplete(uAddr)) sequentialDecode = false; } } // while sequentialDecode // Add this range to the coverage pProc->addRange(start, uAddr); // Must set sequentialDecode back to true sequentialDecode = true; } // while nextAddress() // This pass is to remove up to 3 nops between ranges. // These will be assumed to be padding for alignments of BBs // Possibly removes a lot of ranges that could otherwise be combined ADDRESS a1, a2; COV_CIT ii; Coverage temp; if (pProc->getFirstGap(a1, a2, ii)) { do { int gap = a2 - a1; if (gap < 8) { bool allNops = true; for (int i=0; i < gap; i+= 2) { // Beware endianness! getWord will work properly if (getWord(a1+i+delta) != 0x4e71) { allNops = false; break; } } if (allNops) // Remove this gap, by adding a range equal to the gap // Note: it's not safe to add the range now, so we put // the range into a temp Coverage object to be added later temp.addRange(a1, a2); } } while (pProc->getNextGap(a1, a2, ii)); } // Now add the ranges in temp pProc->addRanges(temp); }