diff --git a/include/base/SMPFunction.h b/include/base/SMPFunction.h index 2221cdc4cbb8ca761fed22a8dd4670b6bbca42ac..40efcd7afef061f60302fb27723237e7e87dba8c 100644 --- a/include/base/SMPFunction.h +++ b/include/base/SMPFunction.h @@ -507,12 +507,10 @@ private: std::vector<int> SSACounter; // SSA subscript #, indexed by GlobalNames op # std::vector<std::list<int> > SSAStack; // SSA stack of most recent SSA number, indexed by global # std::vector<struct LocalVar> LocalVarTable; // offset-sorted list of local vars / outgoing args - std::vector<struct StackFrameEntry> StackFrameMap; // memory map of every byte on stack frame std::vector<struct StackFrameEntry> PositiveOffsetStackFrameMap; // memory map of every byte on stack frame, return address and up (inargs, etc.) std::vector<struct StackFrameEntry> NegativeOffsetStackFrameMap; // memory map of every byte on stack frame, below return address (saved reg, locals, etc.) std::vector<struct FineGrainedInfo> PositiveOffsetFineGrainedStackTable; // Inferences based on instruction accesses of stack std::vector<struct FineGrainedInfo> NegativeOffsetFineGrainedStackTable; // Inferences based on instruction accesses of stack - std::vector<struct FineGrainedInfo> FineGrainedStackTable; // built using opcode analysis, not IDA stack info std::vector<int> SavedRegLoc; // indexed by reg #; offset from return address of callee-saved reg std::vector<SMPOperandType> ReturnRegTypes; // indexed by reg #; inferred types upon return std::vector<SMPOperandType> IncomingRegTypes; // indexed by reg #; types from call sites of callers of this func @@ -565,15 +563,10 @@ private: void FindAllAllocsAndDeallocs(void); // Find all stack frame allocating and deallocating instructions and stack ptr offsets void FindFramePointerDelta(void); // Compute FramePointerStackDelta void SetStackFrameInfo(void); // Figure out the stack frame regions, and locate the alloc/dealloc frame instructions. - STARS_ea_t FindAllocPoint(STARS_asize_t); // Deal with difficult to find stack frame allocations bool MDFixFrameInfo(void); // Redefine stack regions for our needs - bool MDFixUseFP(void); // Fix IDA errors affecting UseFP void BuildLocalVarTable(void); // Determine local variable boundaries on the stack void BuildStackAccessTables(void); // Build tables to characterize stack accesses. - void SemiNaiveLocalVarID(void); // Semi-naive algorithm for local var boundaries ID void UpdateMinMaxStackOffsets(SMPInstr *CurrInst, const STARSOpndTypePtr &TempOp); // Update MinStackAccessOffset and MaxStackAccessLimit if TempOp is stack access - bool AuditLocalVarTable(void); // Check and correct IDA Pro listing of local frame members. - void FindOutgoingArgsSize(void); // Find portion of local frame that is outgoing args inline void SetStackFrameExtendsPastStackTop(void) { StackFrameExtendsPastStackTop = true; }; bool IndexedWritesAboveLocalFrame(const STARSOpndTypePtr &DestOp); // Is DestOp direct stack write to caller's frame? bool MDGetStackOffsetAndSize(SMPInstr *Instr, const STARSOpndTypePtr &TempOp, STARS_sval_t BaseValue, STARS_ea_t &offset, std::size_t &DataSize, diff --git a/include/base/SMPProgram.h b/include/base/SMPProgram.h index 06c6c842a61d9d208a5f1ec991e16f447e1b7d2b..aa14f3cc237388d4f6880ee4c55fd05a7fa289d0 100644 --- a/include/base/SMPProgram.h +++ b/include/base/SMPProgram.h @@ -72,7 +72,7 @@ inline bool IsImmedGlobalAddress(STARS_ea_t ImmedValue) { bool IsDataAddress(STARS_ea_t Address); #endif -inline bool IsImmedNumeric(uintptr_t ImmedValue) { +inline bool IsImmedNumeric(STARS_ea_t ImmedValue) { return (!(IsImmedGlobalAddress(ImmedValue) || global_STARS_program->IsImmedCodeAddress(ImmedValue))); } diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp index 015f59d713d44d5ea683bc36a4ed0ea82ed079da..a735bf98b70daa3b74406b12861d2a2f079c0e9a 100644 --- a/src/base/SMPFunction.cpp +++ b/src/base/SMPFunction.cpp @@ -137,9 +137,6 @@ SMPFunction::SMPFunction(STARS_Function_t *Info, SMPProgram* pgm) { this->Program = pgm; this->FuncInfo = Info; this->FirstEA = this->FuncInfo->get_startEA(); -#if 0 - this->FuncName[0] = '\0'; -#endif this->BlockCount = 0; this->LoopCount = 0; this->FuncProcessed = false; @@ -254,8 +251,6 @@ SMPFunction::SMPFunction(STARS_Function_t *Info, SMPProgram* pgm) { this->SSACounter.clear(); this->SSAStack.clear(); this->LocalVarTable.clear(); - this->StackFrameMap.clear(); - this->FineGrainedStackTable.clear(); this->SavedRegLoc.clear(); this->ReturnRegTypes.clear(); this->LiveOutSet.clear(); @@ -1803,153 +1798,6 @@ void SMPFunction::FindAllAllocsAndDeallocs(void) { } this->CallsAlloca = FoundAlloca; - // As of July, 2015, the code below seems unnecessary and obsolete. - return; - - // Now, if LocalVarsSize is not zero, we need to find the instruction - // in the function prologue that allocates space on the stack for - // local vars. This code could be made more robust in the future - // by matching LocalVarsSize to the immediate value in the allocation - // instruction. However, IDA Pro is sometimes a little off on this - // number. **!!** - if (0 < this->GetLocalVarsSize()) { - if (DebugFlag) SMP_msg("Searching for alloc and dealloc\n"); - list<SMPInstr *>::iterator InstIter = this->Instrs.begin(); -#if SMP_USE_SSA_FNOP_MARKER - ++InstIter; // skip marker instruction -#endif - for ( ; InstIter != this->Instrs.end(); ++InstIter) { - SMPInstr *CurrInst = (*InstIter); - STARS_ea_t addr = CurrInst->GetAddr(); - - // Keep the most recent instruction in the DeallocInstr - // in case we reach the return without seeing a dealloc. - if (!FoundDeallocInstr) { - this->LocalVarsDeallocInstr = addr; - } - - if (!FoundAllocInstr - && CurrInst->MDIsFrameAllocInstr()) { -#if SMP_DEBUG_CONTROLFLOW - SMP_msg("Returned from MDIsFrameAllocInstr()\n"); -#endif - FoundAllocInstr = true; - if (DebugFlag) SMP_msg("Found alloc: %s\n", CurrInst->GetDisasm()); - } - else if (FoundAllocInstr) { - // We can now start searching for the DeallocInstr. - if (CurrInst->MDIsFrameDeallocInstr(UseFP, this->GetLocalVarsSize())) { - // Keep saving the most recent addr that looks - // like the DeallocInstr until we reach the - // end of the function. Last one to look like - // it is used as the DeallocInstr. -#if SMP_DEBUG_CONTROLFLOW - SMP_msg("Returned from MDIsFrameDeallocInstr()\n"); -#endif - this->LocalVarsDeallocInstr = addr; - FoundDeallocInstr = true; - } - else { - if (DebugFlag) SMP_msg("Not dealloc: %s\n", CurrInst->GetDisasm()); - } - } - } // end for (list<SMPInstr *>::iterator InstIter ... ) - if (!FoundAllocInstr) { - // Could not find the frame allocating instruction. Bad. - // See if we can find the point at which the stack allocation reaches - // a total of FuncInfo.frsize+frregs, regardless of whether it happened by push - // instructions or some other means. - this->LocalVarsAllocInstr = this->FindAllocPoint(this->FuncInfo->GetFrameSize() + this->FuncInfo->GetSavedRegSize()); -#if SMP_DEBUG_CONTROLFLOW - SMP_msg("Returned from FindAllocPoint()\n"); -#endif -#if SMP_DEBUG_FRAMEFIXUP - if (STARS_BADADDR == this->LocalVarsAllocInstr) { - SMP_msg("WARNING: Could not find stack frame allocation in %s\n", - this->GetFuncName()); - SMP_msg("LocalVarsSize: %lu SavedRegsSize: %u ArgsSize: %llu\n", - (unsigned long) this->GetLocalVarsSize(), CalleeSavedRegsSize, (unsigned long long) IncomingArgsSize); - } - else { - SMP_msg("FindAllocPoint found %lx for function %s\n", - (unsigned long) this->LocalVarsAllocInstr, this->GetFuncName()); - FoundAllocInstr = true; - } -#endif - } -#if SMP_DEBUG_FRAMEFIXUP - if (!FoundDeallocInstr) { - // Could not find the frame deallocating instruction. Bad. - // Emit diagnostic and use the last instruction in the - // function. - SMP_msg("WARNING: Could not find stack frame deallocation in %s\n", - this->GetFuncName()); - } -#endif - } - // else LocalVarsSize was zero, meaning that we need to search - // for the end of the function prologue code and emit stack frame - // annotations from that address (i.e. this method returns that - // address). We will approximate this by finding the end of the - // sequence of PUSH instructions at the beginning of the function. - // The last PUSH instruction should be the last callee-save-reg - // instruction. We can make this more robust in the future by - // making sure that we do not count a PUSH of anything other than - // a register. **!!** - // NOTE: 2nd prologue instr is usually mov ebp,esp - // THE ASSUMPTION THAT WE HAVE ONLY PUSH INSTRUCTIONS BEFORE - // THE ALLOCATING INSTR IS ONLY TRUE WHEN LOCALVARSSIZE == 0; - else { - STARS_ea_t SaveAddr = this->GetStartAddr(); - list<SMPInstr *>::iterator InstIter = this->Instrs.begin(); -#if SMP_USE_SSA_FNOP_MARKER - ++InstIter; // skip marker instruction -#endif - for ( ; InstIter != this->Instrs.end(); ++InstIter) { - SMPInstr *CurrInst = (*InstIter); - STARS_ea_t addr = CurrInst->GetAddr(); - if (CurrInst->GetIDAOpcode() == STARS_NN_push) - SaveAddr = addr; - else - break; - } - this->LocalVarsAllocInstr = SaveAddr; - FoundAllocInstr = true; - this->LocalVarsDeallocInstr = 0; - // As soon as we have found the local vars allocation, - // we can try to fix incorrect sets of UseFP by IDA. - // NOTE: We might want to extend this in the future to - // handle functions that have no locals. **!!** -#if 0 - bool FixedUseFP = this->MDFixUseFP(); -#if SMP_DEBUG_FRAMEFIXUP - if (FixedUseFP) { - SMP_msg("Fixed UseFP in %s\n", this->GetFuncName()); - } -#endif -#endif - } // end if (LocalVarsSize > 0) ... else ... - - if (!FoundAllocInstr && (0 < this->GetLocalVarsSize()) && this->IsLeaf()) { - // The x86-64 ABI saves time by not allocating a local frame for some leaf functions, - // and just accesses locations below the stack as if they were allocated local vars. - // We still want the UseFP and FramePointerDelta members to be properly set. -#if 0 - bool FixedUseFP = MDFixUseFP(); -#if SMP_DEBUG_FRAMEFIXUP - if (FixedUseFP) { - SMP_msg("Fixed UseFP in %s\n", this->GetFuncName()); - } -#endif -#endif - if (this->UsesFramePointer()) { // now that MDFixUseFP() has validated this flag ... - if (0 != this->GetFramePtrStackDelta()) { - SMP_msg("INFO: Found FramePointerStackDelta of %ld in frameless leaf function %s\n", - (long) this->GetFramePtrStackDelta(), this->GetFuncName()); - } - } - } - return; } // end of SMPFunction::FindAllAllocsAndDeallocs() @@ -2211,85 +2059,6 @@ bool SMPFunction::MDFixFrameInfo(void) { return true; } // end of SMPFunction::MDFixFrameInfo() -// Some functions have difficult to find stack allocations. For example, in some -// version of glibc, strpbrk() zeroes out register ECX and then pushes it more than -// 100 times in order to allocate zero-ed out local vars space for a character translation -// table. We will use the stack pointer analysis of IDA to find out if there is a point -// in the first basic block at which the stack pointer reaches the allocation total -// that IDA is expecting for the local vars region. -// If so, we return the address of the instruction at which ESP reaches its value, else -// we return STARS_BADADDR. -STARS_ea_t SMPFunction::FindAllocPoint(STARS_asize_t OriginalLocSize) { - STARS_sval_t TargetSize = - ((STARS_sval_t) OriginalLocSize); // negate; stack grows down - -#if SMP_DEBUG_FRAMEFIXUP - bool DebugFlag = (0 == strcmp("_dl_runtime_resolve", this->GetFuncName())); - if (DebugFlag) - SMP_msg("%s OriginalLocSize: %lu\n", this->GetFuncName(), (unsigned long) OriginalLocSize); -#endif - - if (this->AnalyzedSP) { - // Limit our analysis to the first basic block in the function. - list<SMPInstr *>::iterator InstIter = this->Instrs.begin(); -#if SMP_USE_SSA_FNOP_MARKER - ++InstIter; // skip marker instruction -#endif - for ( ; InstIter != this->Instrs.end(); ++InstIter) { - SMPInstr *CurrInst = (*InstIter); - STARS_ea_t addr = CurrInst->GetAddr(); - // get_spd() returns a cumulative delta of ESP - STARS_sval_t sp_delta = SMP_get_spd(this->GetFuncInfo(), addr); -#if SMP_DEBUG_FRAMEFIXUP - if (DebugFlag) - SMP_msg("%s delta: %ld at %lx\n", this->GetFuncName(), (long) sp_delta, (unsigned long) addr); -#endif - if (sp_delta == TargetSize) { // <= instead of == here? **!!** - // Previous instruction hit the frame size. - if (InstIter == this->Instrs.begin()) { - return STARS_BADADDR; // cannot back up from first instruction - } - else { - STARS_ea_t PrevAddr = (*(--InstIter))->GetAddr(); -#if SMP_USE_SSA_FNOP_MARKER - if ((*(this->Instrs.begin()))->GetAddr() == PrevAddr) - return STARS_BADADDR; // don't return marker instruction - else - return PrevAddr; -#else - return PrevAddr; -#endif - } - } - if (CurrInst->IsLastInBlock()) { - // It could be that the current instruction will cause the stack pointer - // delta to reach the TargetSize. sp_delta is not updated until after the - // current instruction, so we need to look ahead one instruction if the - // current block falls through. On the other hand, if the current block - // ends with a jump or return, we cannot hit TargetSize. - if (CurrInst->IsBasicBlockTerminator()) - return STARS_BADADDR; - list<SMPInstr *>::iterator NextInstIter = InstIter; - ++NextInstIter; - if (NextInstIter == this->Instrs.end()) - return STARS_BADADDR; - sp_delta = SMP_get_spd(this->GetFuncInfo(), (*NextInstIter)->GetAddr()); - if (sp_delta == TargetSize) { - // CurrInst will cause stack pointer delta to hit TargetSize. - return addr; - } - else { - return STARS_BADADDR; - } - } // end if LastInBlock - } // end for all instructions - } // end if (this->AnalyzedSP) -#if SMP_DEBUG_FRAMEFIXUP - else { - SMP_msg("AnalyzedSP is false for %s\n", this->GetFuncName()); - } -#endif - return STARS_BADADDR; -} // end of SMPFunction::FindAllocPoint() // IDA Pro is sometimes confused by a function that uses the frame pointer // register for other purposes. For the x86, a function that uses EBP @@ -2317,6 +2086,7 @@ STARS_ea_t SMPFunction::FindAllocPoint(STARS_asize_t OriginalLocSize) { // this case. // NOTE: This logic should work for both Linux and Windows x86 prologues. // NOTE As of July, 2015, this logic was incorporated into MDFixFrameInfo(). +#if 0 bool SMPFunction::MDFixUseFP(void) { bool OldUseFP = this->UsesFramePointer(); bool HasLocals = (0 < this->GetLocalVarsSize()); @@ -2393,6 +2163,7 @@ bool SMPFunction::MDFixUseFP(void) { return true; #endif } // end of SMPFunction::MDFixUseFP() +#endif // Find the callee-saved reg offsets (negative offset from return address) // for all registers pushed onto the stack before the stack frame allocation @@ -2550,13 +2321,7 @@ void SMPFunction::MDFindIncomingTypes(void) { // Determine boundaries in the stack frame. void SMPFunction::BuildLocalVarTable(void) { -#if 1 this->BuildStackAccessTables(); -#else - // Currently we just use the info that IDA Pro has inferred from the direct - // addressing of stack locations. - this->SemiNaiveLocalVarID(); -#endif return; } // end of SMPFunction::BuildLocalVarTable() @@ -3068,202 +2833,6 @@ void SMPFunction::BuildStackAccessTables(void) { } // end of SMPFunction::BuildStackAccessTables() -// Use the local variable offset list from IDA's stack frame structure to compute -// the table of local variable boundaries. -void SMPFunction::SemiNaiveLocalVarID(void) { - // NOTE: We use IDA Pro's offsets from this->FuncInfo (e.g. frsize) and NOT - // our own corrected values in our private data members. The offsets we - // read from the stack frame structure returned by get_frame() are consistent - // with other IDA Pro values, not with our corrected values. - list<SMPInstr *>::iterator InstIter; - this->SetLocalVarOffsetLimit(-20000); - - STARS_Function_t *FuncPtr = SMP_get_func(this->GetStartAddr()); - if (NULL == FuncPtr) { - SMP_msg("FATAL ERROR in SMPFunction::SemiNaiveLocalVarID; no func ptr\n"); - } - assert(NULL != FuncPtr); - - // We only get stack frame info from IDA Pro, not IRDB - FuncPtr->FillInLocalVarTable(this); - - // If AnalyzedSP is false, that is all we can do. - if (!this->AnalyzedSP) { - this->OutgoingArgsSize = 0; - this->MinStackDelta = 0; - this->AllocPointDelta = 0; - return; - } - - // Calculate min and max stack operand offsets accessed. - InstIter = this->Instrs.begin(); -#if SMP_USE_SSA_FNOP_MARKER - if ((*InstIter)->IsMarkerInst()) - ++InstIter; // skip marker instruction -#endif - for ( ; InstIter != this->Instrs.end(); ++InstIter) { - SMPInstr *CurrInst = (*InstIter); - STARS_ea_t addr = CurrInst->GetAddr(); - // Find the min and max stack offsets in DEFs and USEs. - if (CurrInst->HasDestMemoryOperand() || CurrInst->MDIsPushInstr() || CurrInst->MDIsEnterInstr()) { - set<DefOrUse, LessDefUse>::iterator CurrDef; - for (CurrDef = CurrInst->GetFirstDef(); CurrDef != CurrInst->GetLastDef(); ++CurrDef) { - STARSOpndTypePtr TempOp = CurrDef->GetOp(); - if ((! TempOp->IsMemNoDisplacementOp()) && (! TempOp->IsMemDisplacementOp())) - continue; - this->UpdateMinMaxStackOffsets(CurrInst, TempOp); - } // end for all DEFs - } - if (CurrInst->HasSourceMemoryOperand() || CurrInst->MDIsPopInstr() || CurrInst->MDIsLeaveInstr() || CurrInst->MDIsLoadEffectiveAddressInstr()) { - if (CurrInst->MDIsLoadEffectiveAddressInstr()) { - STARSOpndTypePtr TempOp = CurrInst->GetLeaMemUseOp(); - if (nullptr != TempOp) { - if (((TempOp->IsMemNoDisplacementOp()) || (TempOp->IsMemDisplacementOp())) && (!(CurrInst->IsRegClearIdiom() || CurrInst->IsNop()))) { - this->UpdateMinMaxStackOffsets(CurrInst, TempOp); - } - } - } - else { - set<DefOrUse, LessDefUse>::iterator CurrUse; - for (CurrUse = CurrInst->GetFirstUse(); CurrUse != CurrInst->GetLastUse(); ++CurrUse) { - STARSOpndTypePtr TempOp = CurrUse->GetOp(); - if ((! TempOp->IsMemNoDisplacementOp()) && (! TempOp->IsMemDisplacementOp())) - continue; - this->UpdateMinMaxStackOffsets(CurrInst, TempOp); - } // end for all USEs - } - } - } // end for all instructions - if (0 == this->MaxStackAccessLimit) { - // Never accessed any incoming args. However, we know the return address is on the stack, - // and it is almost never accessed, so we want to record its presence. - this->MaxStackAccessLimit = MD_DEFAULT_RETURN_ADDRESS_SIZE; - } - if (this->MinStackAccessOffset > this->MinStackDelta) { - // Some functions allocate space that is not visibly accessed. We still want to make - // our stack frame maps of maximum size, and MinStackDelta is used for normalizing offsets. - this->MinStackAccessOffset = this->MinStackDelta; - } - else if (this->MinStackAccessOffset < this->MinStackDelta) { - // x86-64 leaf functions are often optimized by not allocating a stack frame. Instead, - // negative displacements from the stack pointer are used to access locals. So the - // stack pointer (reflected in MinStackDelta) never goes down as far as the bottom of - // the frame (reflected by MinStackAccessOffset). We need to record that such a function - // has been detected so that we don't fail assertions unnecessarily later. - this->SetStackFrameExtendsPastStackTop(); - } - - // IDA Pro sometimes fails to add stack frame members for all incoming args, etc. - // Find and correct these omissions by examining stack accesses in instructions - // and extend the LocalVarTable to cover whatever is out of range. - if (!this->AuditLocalVarTable()) { - // Catastrophic error must have occurred, probably due to errors in IDA's - // stack pointer analysis, despite AnalyzedSP being true. - return; - } - - if (!(this->LocalVarTable.empty())) { - this->GoodLocalVarTable = true; - - // Sort the LocalVarTable so that we do not depend on IDA Pro - // presenting the stack frame members in order. - std::sort(this->LocalVarTable.begin(), this->LocalVarTable.end(), LocalVarCompare); - } - -#if SMP_DEBUG_STACK_GRANULARITY - SMP_msg("Computing %d local var sizes\n", this->LocalVarTable.size()); -#endif - // Now we want to audit the size field for each local - if (this->GoodLocalVarTable) { - std::size_t VarLimit = this->LocalVarTable.size() - 1; - assert(this->LocalVarTable.size() > 0); - for (std::size_t VarIndex = 0; VarIndex < VarLimit; ++VarIndex) { - struct LocalVar TempLocEntry = this->LocalVarTable[VarIndex]; - bool AboveLocalsRegion = (TempLocEntry.offset >= this->GetLocalVarsSize()); - std::size_t TempSize = this->LocalVarTable[VarIndex + 1].offset - TempLocEntry.offset; - int DiffSize = ((int) TempSize) - ((int) TempLocEntry.size); - // We don't have IDA Pro stack frame members for callee saved registers. This - // omission can make it seem that there is a gap between the uppermost local - // variable and the return address or saved frame pointer. Avoid expanding the - // last local variable into the callee saved registers region. - if (DiffSize > 0) { // We are expanding the size. - if (!AboveLocalsRegion && ((TempLocEntry.offset + TempLocEntry.size + DiffSize) > this->GetLocalVarsSize())) { - // Current local does not start above the locals region, but its new size will - // carry it above the locals region. - if ((TempLocEntry.offset + TempLocEntry.size) > this->GetLocalVarsSize()) { - // Weird. It already overlapped the callee saved regs region. - SMP_msg("WARNING: Local var at offset %ld size %zu in %s extends above local vars region.\n", - TempLocEntry.offset, TempLocEntry.size, this->GetFuncName()); - } - // Limit DiffSize to avoid overlapping callee saved regs. - DiffSize = this->GetLocalVarsSize() - (TempLocEntry.offset + TempLocEntry.size); - if (DiffSize < 0) - DiffSize = 0; // started out positive, cap it at zero. - } - } - if (DiffSize < 0) - DiffSize = 0; // should not happen with sorted LocalVarTable unless duplicate entries. - if (DiffSize != 0) { -#if SMP_DEBUG_STACK_GRANULARITY - SMP_msg("STACK INFO: Adjusted size for stack frame member at %ld in %s\n", - TempLocEntry.offset, this->GetFuncName()); -#endif - this->LocalVarTable[VarIndex].size += DiffSize; - } - } -#if 0 // Using Member->eoff seems to be working for all members, including the last one. -#if SMP_DEBUG_STACK_GRANULARITY - SMP_msg("Computing last local var size for frsize %d\n", this->FuncInfo->GetFrameSize()); -#endif - // Size of last local is total frsize minus savedregs in frame minus offset of last local - std::size_t SavedRegsSpace = 0; // portion of frsize that is saved regs, not locals. - if (this->CalleeSavedRegsSize > this->FuncInfo->GetSavedRegSize()) { - // IDA Pro counts the save of EBP in frregs, but then EBP gets its new - // value and callee saved regs other than the old EBP push get counted - // in frsize rather than frregs. CalleeSavedRegsSize includes all saved - // regs on the stack, both above and below the current EBP offset. - // NOTE: For windows, this has to be done differently, as callee saved regs - // happen at the bottom of the local frame, not the top. -#if 0 - SavedRegsSpace = this->CalleeSavedRegsSize - this->FuncInfo->GetSavedRegSize(); -#else - SavedRegsSpace = this->FuncInfo->GetFrameSize() - this->GetLocalVarsSize(); -#endif - } - - this->LocalVarTable.back().size = this->FuncInfo->GetFrameSize() - - SavedRegsSpace - this->LocalVarTable.back().offset; - this->SetLocalVarOffsetLimit(this->LocalVarTable.back().offset - + (STARS_adiff_t) this->LocalVarTable.back().size); -#endif - } - -#if 0 // AboveLocalsSize is not a reliable number. - // IDA Pro can have difficulty with some irregular functions such as are found - // in the C startup code. The frsize value might be bogus. Just punt on the - // local variable ID if that is the case. - if ((this->GetLocalVarOffsetLimit() - AboveLocalsSize) > (STARS_adiff_t) this->FuncInfo->GetFrameSize()) { - this->LocalVarTable.clear(); - this->GoodLocalVarTable = false; - SMP_msg("WARNING: Bad frsize %d for %s OffsetLimit: %d AboveLocalsSize: %d LocalVarsSize: %d ; abandoning SemiNaiveLocalVarID.\n", - this->FuncInfo->GetFrameSize(), this->GetFuncName(), this->GetLocalVarOffsetLimit(), AboveLocalsSize, this->GetLocalVarsSize()); - return; - } - assert((this->GetLocalVarOffsetLimit() - AboveLocalsSize) <= (STARS_adiff_t) this->FuncInfo->GetFrameSize()); -#endif - - // Find out how many of the locals are really outgoing args. - if (this->AnalyzedSP && !this->CallsAlloca && (STARS_BADADDR != this->LocalVarsAllocInstr)) { - this->FindOutgoingArgsSize(); - } - else { - SMP_msg("FindOutgoingArgsSize not called for %s ", this->GetFuncName()); - SMP_msg("AnalyzedSP: %d CallsAlloca: %d LocalVarsAllocInstr: %lx \n", - this->AnalyzedSP, this->CallsAlloca, (unsigned long) this->LocalVarsAllocInstr); - } - return; -} // end of SMPFunction::SemiNaiveLocalVarID() - // Update MinStackAccessOffset and MaxStackAccessLimit if TempOp is stack access void SMPFunction::UpdateMinMaxStackOffsets(SMPInstr *CurrInst, const STARSOpndTypePtr &TempOp) { STARS_ea_t offset; @@ -3286,485 +2855,6 @@ void SMPFunction::UpdateMinMaxStackOffsets(SMPInstr *CurrInst, const STARSOpndTy return; } // end of SMPFunction::UpdateMinMaxStackOffsets() -// Check and correct the LocalVarTable derived from IDA Pro stack frame members. -// Examine each instruction and see if any stack accesses are beyond the LocalVarTable -// and create new entries in the LocalVarTable if so. -bool SMPFunction::AuditLocalVarTable(void) { - // For some functions, IDA Pro does not base its stack frame at the MinStackDelta. This - // is detected by noting that the offset field for the saved return address is not - // the negation of the MinStackDelta, e.g. offset is 12 and MinStackDelta is -16 - // for a function such as call_gmon_start, which has a temporary 4-byte decrease - // in the stack delta for an internal thunk call that IDA Pro excludes from the - // stack frame analysis, because it does not represent any local variable: - // call next_instruction - // pop ebx - // Instead, IDA Pro typically bases its stack frame at the AllocPointDelta. For many - // functions, the MinStackDelta and the AllocPointDelta are the same. For some, they - // are not the same, and for some functions, IDA Pro has a stack frame that is not - // even based at the AllocPointDelta, because IDA Pro makes a mistake in its analyses - // when the first basic block is interrupted by odd code such as a function call - // before it reaches the frame allocation instruction. - // So, we need to align the local var table so that the base of the table is at the - // AllocPointDelta and the saved return address falls at normalized address zero, i.e. - // if AllocPointDelta is -28, then the LocalVarTable will start at offset zero as IDA - // computes offsets, and the saved return address will fall at offset 28, the negation - // of the AllocPointDelta. If the LocalVarTable does not conform to this pattern, we will - // need to add 4-byte entries at the bottom of the table and adjust offsets until the return address - // falls at the correct offset. - long IDAFrameAdjustment = (0 - this->IDAReturnAddressOffset - this->AllocPointDelta); - if (IDAFrameAdjustment != 0) { - SMP_msg("WARNING: %ld bytes IDAFrameAdjustment needed: Func at: %lx RetAddrOffset: %ld AllocPointDelta: %lld\n", - IDAFrameAdjustment, (unsigned long) this->GetFirstFuncAddr(), this->IDAReturnAddressOffset, (int64_t) this->AllocPointDelta); - // We need to subtract (IDAReturnAddressOffset + this->AllocPointDelta) from the local var table offsets. - // this->AllocPointDelta is negative, e.g. -44 for libc_csu_init in toy.exe, and IDAReturnAddressOffset - // should be its negation (44 in that example), but is a smaller number (20 in the toy.exe example), - // so we are subtracting (20 + -44) from each offset, meaning we are adding 24. We also add 24 to the - // value of this->LocalVarOffsetLimit, and create an entry at the bottom of the frame with a size of - // 24 in this example. - long LocalVarIncrement = (0 - (this->IDAReturnAddressOffset + this->AllocPointDelta)); - if (LocalVarIncrement <= 0) { - SMP_msg("SERIOUS WARNING: Unexpected non-positive value for LocalVarIncrement: %ld Func at: %lx\n", - LocalVarIncrement, (unsigned long) this->GetFirstFuncAddr()); - } - else { - for (std::size_t i = 0; i < this->LocalVarTable.size(); ++i) { - this->LocalVarTable[i].offset += LocalVarIncrement; - } - // Add dummy placeholders at bottom of LocalVarTable, four bytes each. - std::size_t TotalFillerSize = 0; - do { - struct LocalVar TempLocal; - char TempStr[20]; - TempLocal.offset = (long) TotalFillerSize; - TempLocal.size = 4; - if (((long)(TempLocal.size + TotalFillerSize)) > LocalVarIncrement) { - TempLocal.size = (std::size_t)(LocalVarIncrement - (long) TotalFillerSize); - } - TotalFillerSize += TempLocal.size; - SMP_strncpy(TempLocal.VarName, "SMP_IDA_FixVar", sizeof(TempLocal.VarName) - 1); - (void) SMP_snprintf(TempStr, 18, "%ld", TempLocal.offset); - SMP_strncat(TempLocal.VarName, TempStr, sizeof(TempLocal.VarName) - 1); - this->LocalVarTable.push_back(TempLocal); - } while (((long)TotalFillerSize) < LocalVarIncrement); - this->SetLocalVarOffsetLimit(this->GetLocalVarOffsetLimit() + LocalVarIncrement); - -/* wtf? changing ida info? - * from clc -- no, not updating idapro, just caching a change in stars. - this->FuncInfo->frsize += (STARS_asize_t) LocalVarIncrement; -*/ - this->FuncInfo->SetFrameSize(this->FuncInfo->GetFrameSize()+ (STARS_asize_t) LocalVarIncrement); - - } - } - - // We cannot depend on IDA Pro making Member - // entries for everything that is accessed on the stack. - // When an incoming arg is accessed but no Member is - // created, then LocalVarOffsetLimit will be too small - // and we will get ERROR messages. We already looped through the - // instructions to find the MaxStackAccessLimit. If LocalVarOffsetLimit - // is not big enough to reach from AllocPointDelta to MaxStackAccessLimit, - // then add 4-byte incoming arg entries until it reaches. - while (this->GetLocalVarOffsetLimit() < (long) this->MaxStackAccessLimit) { - // Extend LocalVarTable. - struct LocalVar TempLocal; - char TempStr[20]; - TempLocal.offset = this->GetLocalVarOffsetLimit(); - TempLocal.size = global_STARS_program->GetSTARS_ISA_Bytewidth(); - if ((TempLocal.size + TempLocal.offset) > ((long) this->MaxStackAccessLimit)) { - TempLocal.size = ((long) this->MaxStackAccessLimit) - TempLocal.offset; - } - SMP_strncpy(TempLocal.VarName, "SMP_InArg", sizeof(TempLocal.VarName) - 1); - (void) SMP_snprintf(TempStr, 18, "%ld", TempLocal.offset); - SMP_strncat(TempLocal.VarName, TempStr, sizeof(TempLocal.VarName) - 1); - this->LocalVarTable.push_back(TempLocal); - this->SetLocalVarOffsetLimit(this->GetLocalVarOffsetLimit() + TempLocal.size); - } - - // Fill in the gaps with new variables as well. SHOULD WE? WHY? - - return true; -} // end of SMPFunction::AuditLocalVarTable() - - -// Determine how many bytes at the bottom of the stack frame (i.e. at bottom of -// this->LocalVarsSize) are used for outgoing args. This is the case when the cdecl -// calling convention is used, e.g. gcc/linux allocates local var space + out args space -// in a single allocation and then writes outarg values directly to ESP+0, ESP+4, etc. -void SMPFunction::FindOutgoingArgsSize(void) { - // Compute the lowest value reached by the stack pointer. - list<SMPInstr *>::iterator InstIter; - unsigned short BitWidthMask; - bool DebugFlag = false; - int SignedOffset; -#if SMP_DEBUG_STACK_GRANULARITY - DebugFlag = (0 == strcmp("BZ2_blockSort", this->GetFuncName())); -#endif - - this->OutgoingArgsComputed = true; - - if (DebugFlag) { - SMP_msg("DEBUG: Entered FindOutgoingArgsSize for %s\n", this->GetFuncName()); -#if SMP_IDAPRO52_WORKAROUND - this->OutgoingArgsSize = 16; - return; -#endif - } - -#if SMP_DEBUG_STACK_GRANULARITY - SMP_msg("AllocPointDelta: %d MinStackDelta: %d\n", this->AllocPointDelta, this->MinStackDelta); -#endif - if ((0 <= this->MinStackDelta) || (0 <= this->AllocPointDelta)) { - // No allocations; sometimes happens in library functions. - this->OutgoingArgsSize = 0; - this->AllocPointDelta = 0; - if ((this->MinStackDelta > this->MaxStackDelta) || (0 < this->MinStackDelta)) { - this->MinStackDelta = 0; - } - } - assert(0 >= this->MinStackDelta); - - // Allocate a vector of stack frame entries, one for each byte of the stack frame. - // This will be our memory map for analyzing stack usage. - for (int i = this->MinStackAccessOffset; i < this->MaxStackAccessLimit; ++i) { - struct StackFrameEntry TempEntry; - TempEntry.VarPtr = NULL; - TempEntry.offset = (long) i; - TempEntry.Read = false; - TempEntry.Written = false; - TempEntry.AddressTaken = false; - TempEntry.ESPRelativeAccess = false; - TempEntry.EBPRelativeAccess = false; - TempEntry.IndexedAccess = false; - this->StackFrameMap.push_back(TempEntry); - struct FineGrainedInfo TempFineGrained; - TempFineGrained.SignMiscInfo = 0; - TempFineGrained.SizeInfo = 0; - this->FineGrainedStackTable.push_back(TempFineGrained); - } -#if 0 - for (int i = 0; i < this->GetLocalVarOffsetLimit(); ++i) { - struct FineGrainedInfo TempFineGrained; - TempFineGrained.SignMiscInfo = 0; - TempFineGrained.SizeInfo = 0; - this->FineGrainedStackTable.push_back(TempFineGrained); - } -#endif - - if (0 < this->AllocPointDelta) { - SMP_msg("FATAL ERROR: AllocPointDelta = %ld in %s\n", (long) this->AllocPointDelta, this->GetFuncName()); - } - assert(0 >= this->AllocPointDelta); - - // Fill in the VarPtr fields for each StackFrameMap entry. - - // We were not able to adjust the LocalVarTable for a negative IDAFrameAdjustment back - // in AuditLocalVarTable(), but we can use the negative adjustment value in this loop - // to properly match the StackFrameMap entries to the LocalVarTable entries and avoid - // an out of range error. - long IDAFrameAdjustment = (0 - this->IDAReturnAddressOffset - this->AllocPointDelta); - if (0 < IDAFrameAdjustment) { - IDAFrameAdjustment = 0; // only handling the negative case; positive was handled in AuditLocalVarTable() - } - for (std::size_t i = 0; i < this->LocalVarTable.size(); ++i) { - assert(this->LocalVarTable.at(i).offset >= 0); - // Picture that AllocPointDelta is -200, MinStackAccessOffset is -210, and - // the LocalVarTable[i].offset is +8 (i.e. 8 bytes above alloc point). - // Then base = 8 + (-200 - -210) = 8 + 10 = 18, the proper offset into - // the StackFrameMap. - std::size_t base = (std::size_t) (this->LocalVarTable.at(i).offset - + (this->AllocPointDelta - this->MinStackAccessOffset) + IDAFrameAdjustment); - std::size_t limit = base + this->LocalVarTable.at(i).size; - if (limit > this->StackFrameMap.size()) { - SMP_msg("WARNING: FindOutArgsSize: Unaccessed IDA Pro local var or inarg %s base = %zu limit = %zu in %s\n", - this->LocalVarTable.at(i).VarName, base, limit, this->GetFuncName()); - } - else { - assert(limit <= this->StackFrameMap.size()); - for (std::size_t MapIndex = base; MapIndex < limit; ++MapIndex) { - this->StackFrameMap[MapIndex].VarPtr = &(this->LocalVarTable.at(i)); - } - } - } - - // Iterate through all instructions and record stack frame accesses in the StackFrameMap. - InstIter = this->Instrs.begin(); -#if SMP_USE_SSA_FNOP_MARKER - if ((*InstIter)->IsMarkerInst()) - ++InstIter; // skip marker instruction -#endif - for ( ; InstIter != this->Instrs.end(); ++InstIter) { - SMPInstr *CurrInst = (*InstIter); - STARS_ea_t InstAddr = CurrInst->GetAddr(); - STARS_sval_t sp_delta = CurrInst->GetStackPtrOffset(); - if (0 < sp_delta) { - // Stack underflow. - SMP_msg("ERROR: Stack underflow at %lx %s sp_delta: %ld\n", (unsigned long) InstAddr, - CurrInst->GetDisasm(), (long) sp_delta); - this->OutgoingArgsComputed = false; - this->OutgoingArgsSize = 0; - return; - } - assert(0 >= sp_delta); - STARS_ea_t offset; - std::size_t DataSize; - bool UsedFramePointer; - bool IndexedAccess; - bool SignedMove; - bool UnsignedMove; - if (CurrInst->HasDestMemoryOperand()) { - set<DefOrUse, LessDefUse>::iterator CurrDef; - for (CurrDef = CurrInst->GetFirstDef(); CurrDef != CurrInst->GetLastDef(); ++CurrDef) { - STARSOpndTypePtr TempOp = CurrDef->GetOp(); - if ((!TempOp->IsMemNoDisplacementOp()) && (!TempOp->IsMemDisplacementOp())) - continue; - if (this->MDGetStackOffsetAndSize(CurrInst, TempOp, this->MinStackAccessOffset, offset, DataSize, UsedFramePointer, - IndexedAccess, SignedMove, UnsignedMove)) { - SignedOffset = (int) offset; - if (IndexedAccess && ((0 > SignedOffset) || ((SignedOffset + DataSize) > this->StackFrameMap.size()))) { - continue; // Indexed expressions can be within frame even when offset is outside frame - } - assert(0 <= SignedOffset); -#if 0 - if (offset >= this->FuncInfo->GetFrameSize()) - continue; // limit processing to outgoing args and locals -#endif - if ((offset + DataSize) > this->StackFrameMap.size()) { - SMP_msg("ERROR: offset = %lu DataSize = %zu FrameMapSize = %zu\n", - (unsigned long) offset, DataSize, this->StackFrameMap.size()); - continue; - } - assert((offset + DataSize) <= this->StackFrameMap.size()); - bool ESPRelative = (!(UsedFramePointer || CurrInst->HasFPNormalizedToSP())); - for (int j = 0; j < (int) DataSize; ++j) { - this->StackFrameMap[offset + j].Written = true; - this->StackFrameMap[offset + j].IndexedAccess = IndexedAccess; - if (ESPRelative) { - this->StackFrameMap[offset + j].ESPRelativeAccess = true; - } - else { - this->StackFrameMap[offset + j].EBPRelativeAccess = true; - } - } - struct FineGrainedInfo StackDefFG; - BitWidthMask = ComputeOperandBitWidthMask(TempOp, DataSize); - this->FineGrainedStackTable.at(offset).SizeInfo |= BitWidthMask; - StackDefFG.SizeInfo = BitWidthMask; - this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_WRITTEN; - StackDefFG.SignMiscInfo = FG_MASK_WRITTEN; - if (IndexedAccess) { - this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_INDEXED_ACCESS; - StackDefFG.SignMiscInfo |= FG_MASK_INDEXED_ACCESS; - } - if (ESPRelative) { - this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_SP_RELATIVE; - StackDefFG.SignMiscInfo |= FG_MASK_SP_RELATIVE; - } - else { - this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_FP_RELATIVE; - StackDefFG.SignMiscInfo |= FG_MASK_FP_RELATIVE; - } - // We will process the signedness of stores later, so that loads can take precedence - // over stores in determining signedness in the table. We go ahead and process - // signedness for the separate DEF and USE maps by InstAddr. - if (SignedMove) { - StackDefFG.SignMiscInfo |= FG_MASK_SIGNED; - } - else if (UnsignedMove) { - StackDefFG.SignMiscInfo |= FG_MASK_UNSIGNED; - } - // Insert the StackDefFG into the map of InstAddr to DEF FG info. - pair<map<STARS_ea_t, struct FineGrainedInfo>::iterator, bool> InsertResult; - pair<STARS_ea_t, struct FineGrainedInfo> InsertValue(InstAddr, StackDefFG); - InsertResult = this->StackDefFGInfo.insert(InsertValue); - assert(InsertResult.second); - } // end if MDGetStackOffsetAndSize() - } // end for all DEFs - } // end if DestMemoryOperand - - if (CurrInst->HasSourceMemoryOperand()) { - set<DefOrUse, LessDefUse>::iterator CurrUse; - for (CurrUse = CurrInst->GetFirstUse(); CurrUse != CurrInst->GetLastUse(); ++CurrUse) { - STARSOpndTypePtr TempOp = CurrUse->GetOp(); - if ((!TempOp->IsMemNoDisplacementOp()) && (!TempOp->IsMemDisplacementOp())) - continue; - if (this->MDGetStackOffsetAndSize(CurrInst, TempOp, this->MinStackAccessOffset, offset, DataSize, UsedFramePointer, - IndexedAccess, SignedMove, UnsignedMove)) { - SignedOffset = (int) offset; - if (IndexedAccess && ((0 > SignedOffset) || ((SignedOffset + DataSize) > this->StackFrameMap.size()))) { - continue; // Indexed expressions can be within frame but offset is outside frame - } - assert(0 <= SignedOffset); -#if 0 - if (offset >= this->FuncInfo->GetFrameSize()) - continue; // limit processing to outgoing args and locals -#endif - if ((SignedOffset + DataSize) > this->StackFrameMap.size()) { - SMP_msg("ERROR: offset = %lu DataSize = %zu FrameMapSize = %zu\n", - (unsigned long) offset, DataSize, this->StackFrameMap.size()); - continue; - } - assert((SignedOffset + DataSize) <= this->StackFrameMap.size()); - bool ESPRelative = (!(UsedFramePointer || CurrInst->HasFPNormalizedToSP())); - for (int j = 0; j < (int) DataSize; ++j) { - this->StackFrameMap[offset + j].Read = true; - this->StackFrameMap[offset + j].IndexedAccess |= IndexedAccess; - if (ESPRelative) - this->StackFrameMap[offset + j].ESPRelativeAccess = true; - else - this->StackFrameMap[offset + j].EBPRelativeAccess = true; - } - struct FineGrainedInfo StackUseFG; - BitWidthMask = ComputeOperandBitWidthMask(TempOp, DataSize); - this->FineGrainedStackTable.at(offset).SizeInfo |= BitWidthMask; - StackUseFG.SizeInfo = BitWidthMask; - this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_READ; - StackUseFG.SignMiscInfo = FG_MASK_READ; - if (IndexedAccess) { - this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_INDEXED_ACCESS; - StackUseFG.SignMiscInfo |= FG_MASK_INDEXED_ACCESS; - } - if (ESPRelative) { - this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_SP_RELATIVE; - StackUseFG.SignMiscInfo |= FG_MASK_SP_RELATIVE; - } - else { - this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_FP_RELATIVE; - StackUseFG.SignMiscInfo |= FG_MASK_FP_RELATIVE; - } - if (SignedMove) { - this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_SIGNED; - StackUseFG.SignMiscInfo |= FG_MASK_SIGNED; - } - else if (UnsignedMove) { - this->FineGrainedStackTable.at(offset).SignMiscInfo |= FG_MASK_UNSIGNED; - StackUseFG.SignMiscInfo |= FG_MASK_UNSIGNED; - } - // Insert the StackUseFG into the map of InstAddr to USE FG info. - pair<map<STARS_ea_t, struct FineGrainedInfo>::iterator, bool> InsertResult; - pair<STARS_ea_t, struct FineGrainedInfo> InsertValue(InstAddr, StackUseFG); - InsertResult = this->StackUseFGInfo.insert(InsertValue); - assert(InsertResult.second); - } // end if MDGetStackOffsetAndSize() - } // end for all USEs - } // end if SourceMemoryOperand - // NOTE: Detect taking the address of stack locations. **!!** - } // end for all instructions - - // If function is a leaf function, set OutgoingArgsSize to zero and return. - // If function has no local frame allocation, ditto. - if ((this->IsLeaf() && !(this->IsDirectlyRecursive())) - || (this->AllocPointDelta == 0)) { - this->OutgoingArgsSize = 0; - return; - } - - // For non-leaf functions, set the OutgoingArgsSize to the write-only, ESP-relative - // region of the bottom of the StackFrameMap. - bool OutgoingArgsRegionFinished = false; - bool IndexedOutgoingArgs = false; // Any indexed accesses to outgoing args? - std::size_t FramePadSize = 0; - std::size_t AlignmentPadSize = 0; // bottom of frame, unused space below outargs - for (std::size_t MapIndex = 0; MapIndex < this->StackFrameMap.size(); ++MapIndex) { - // Some of the bottom of the stack frame might be below the local frame allocation. - // These are pushes that happened after allocation, etc. We skip over these - // locations and define the outgoing args region to start strictly at the bottom - // of the local frame allocation. - struct StackFrameEntry TempEntry = this->StackFrameMap.at(MapIndex); - if (DebugFlag) { - SMP_msg("StackFrameMap entry %zu: offset: %ld Read: %d Written: %d ESP: %d EBP: %d\n", - MapIndex, TempEntry.offset, TempEntry.Read, TempEntry.Written, - TempEntry.ESPRelativeAccess, TempEntry.EBPRelativeAccess); - } - if (TempEntry.offset < this->AllocPointDelta) - continue; - if ((NULL != TempEntry.VarPtr) && ((0 == strcmp(" s", TempEntry.VarPtr->VarName)) || (0 == strcmp(" r", TempEntry.VarPtr->VarName)))) { - // We have reached saved regs or the return address. - break; - } - - if (OutgoingArgsRegionFinished) { - // We are just processing the stack frame padding. - if (!TempEntry.Read && !TempEntry.Written) { - // Could be stack frame padding. - ++FramePadSize; - } - else { - break; // No more padding region - } - } - else if ((this->OutgoingArgsSize == 0) && (!TempEntry.Read) && (!TempEntry.Written)) { - // We have not started accumulating outgoing args bytes, we have reached the - // AllocPointDelta, yet we find space that is neither written nor read. This - // empty space at the bottom of the stack frame could just be for stack alignment - // purposes, especially in the new x86-64 ABI, so it should not prevent us from - // finding outgoing args space above it. - ++AlignmentPadSize; - } - else if (TempEntry.Read || TempEntry.EBPRelativeAccess || !TempEntry.Written - || !TempEntry.ESPRelativeAccess) { - OutgoingArgsRegionFinished = true; - if (!TempEntry.Read && !TempEntry.Written) { - // Could be stack frame padding. - ++FramePadSize; - } - else { - break; // No padding region - } - } - else { - this->OutgoingArgsSize++; - if (TempEntry.IndexedAccess) { - IndexedOutgoingArgs = true; - } - } - } - - // Add in the alignment padding below the written outargs region. - if (this->OutgoingArgsSize > 0) { - this->OutgoingArgsSize += AlignmentPadSize; - } - - // If any outgoing arg was accessed using an index register, then we don't know how high - // the index register value went. It could potentially consume the so-called padding - // region, which might be just the region we did not detect direct accesses to because - // the accesses were indirect. To be safe, we expand the outgoing args region to fill - // the padding region above it in this indexed access case. - if (IndexedOutgoingArgs) { - this->OutgoingArgsSize += FramePadSize; - } - -#if 0 - // Sometimes we encounter unused stack space above the outgoing args. Lump this space - // in with the outgoing args. We detect this by noting when the outgoing args space - // has only partially used the space assigned to a local var. - // NOTE: This is usually just stack padding to maintain stack alignment. It could - // also be the case that the lowest local variable is accessed indirectly and we missed - // seeing its address taken, in which case it would be unsound to lump it into the - // outgoing args region. We might want to create a local var called STACKPAD - // to occupy this space. - if ((0 < this->OutgoingArgsSize) && (this->OutgoingArgsSize < this->FuncInfo->GetFrameSize())) { - long MapIndex = (this->AllocPointDelta - this->MinStackDelta); - assert(0 <= MapIndex); - MapIndex += (((long) this->OutgoingArgsSize) - 1); - struct StackFrameEntry TempEntry = this->StackFrameMap.at((std::size_t) MapIndex); - if (NULL == TempEntry.VarPtr) { // Gap in stack frame; IDA 6.0 - SMP_msg("Gap in stack frame: %s\n", this->GetFuncName()); - } - else if (this->OutgoingArgsSize < (TempEntry.VarPtr->offset + TempEntry.VarPtr->size)) { -#if SMP_DEBUG_FRAMEFIXUP - SMP_msg("OutGoingArgsSize = %d", this->OutgoingArgsSize); -#endif - this->OutgoingArgsSize = TempEntry.VarPtr->offset + TempEntry.VarPtr->size; -#if SMP_DEBUG_FRAMEFIXUP - SMP_msg(" adjusted to %d\n", this->OutgoingArgsSize); -#endif - } - } -#endif - - return; -} // end of SMPFunction::FindOutgoingArgsSize() // If TempOp reads or writes to a stack location, return the offset (relative to the initial // stack pointer value) and the size in bytes of the data access. Also return whether the @@ -3811,7 +2901,8 @@ bool SMPFunction::MDGetStackOffsetAndSize(SMPInstr *Instr, const STARSOpndTypePt Signed = (opcode == STARS_NN_movsx); if ((0 > SignedOffset) && (!Indexed) && (BaseValue == this->MinStackAccessOffset)) { // Consider asserting here. - SMP_msg("ERROR: Negative offset in MDGetStackOffsetAndSize for inst dump: \n"); + SMP_msg("ERROR: Negative offset in MDGetStackOffsetAndSize at %llx for inst dump: \n", + (unsigned long long) Instr->GetAddr()); Instr->Dump(); } return true;