From 6616bc6e6a4c07aa2398373ee65563a3d80933bb Mon Sep 17 00:00:00 2001 From: clc5q <clc5q@git.zephyr-software.com> Date: Sat, 1 Mar 2014 01:52:39 +0000 Subject: [PATCH] Fix crashes in ffmpeg and other 64-bit binaries. --- SMPBasicBlock.cpp | 2 +- SMPFunction.cpp | 10 +++++++++- SMPFunction.h | 3 +++ SMPInstr.cpp | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/SMPBasicBlock.cpp b/SMPBasicBlock.cpp index 1a8b76ea..4f5a05ff 100644 --- a/SMPBasicBlock.cpp +++ b/SMPBasicBlock.cpp @@ -3696,8 +3696,8 @@ bool SMPBasicBlock::IsDefInvolvedInAddition(ea_t DefAddr, op_t DefOp, ea_t &Addi ++UseInstIter; while (UseInstIter != this->GetLastInst()) { SMPInstr *UseInst = (*UseInstIter); + AdditionAddr = UseInst->GetAddr(); if (UseInst->FindUse(DefOp) != UseInst->GetLastUse()) { - AdditionAddr = UseInst->GetAddr(); if (UseInst->MDIsAddition()) { // hash function value is accumulating in another DEF via addition. return true; diff --git a/SMPFunction.cpp b/SMPFunction.cpp index 9350ffb9..8fcca2f7 100644 --- a/SMPFunction.cpp +++ b/SMPFunction.cpp @@ -2339,6 +2339,14 @@ void SMPFunction::SemiNaiveLocalVarID(void) { // 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 @@ -2680,7 +2688,7 @@ void SMPFunction::FindOutgoingArgsSize(void) { ea_t InstAddr = CurrInst->GetAddr(); sval_t sp_delta = CurrInst->GetStackPtrOffset(); if (0 < sp_delta) { - // Stack underflow; about to assert + // 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; diff --git a/SMPFunction.h b/SMPFunction.h index 6779103d..3f01b8f6 100644 --- a/SMPFunction.h +++ b/SMPFunction.h @@ -255,6 +255,7 @@ public: return (KillSet.end() != KillSet.find(CurrOp)); } bool IsInStackPtrCopySet(op_t CurrOp); + inline bool DoesStackFrameExtendPastStackTop(void) const { return StackFrameExtendsPastStackTop; }; // Printing methods void Dump(void); // debug dump @@ -337,6 +338,7 @@ private: bool PossibleTailCallTarget; // function could be called by jump instruction acting as tail call bool OutgoingArgsComputed; // Were able to compute OutgoingArgsSize bool GoodLocalVarTable; // LocalVarTable was built successfully + bool StackFrameExtendsPastStackTop; // Locals are accessed from unallocated space beyond the top of stack. bool IsSpeculative; // Have we started the speculative portion of the analysis for this function. long TypedDefs; // How many DEFs in instructions were not UNINIT type after InferTypes() long UntypedDefs; // How many DEFs in instructions are UNINIT type after InferTypes() @@ -438,6 +440,7 @@ private: void UpdateMinMaxStackOffsets(SMPInstr *CurrInst, op_t 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(op_t DestOp); // Is DestOp direct stack write to caller's frame? bool MDGetStackOffsetAndSize(SMPInstr *Instr, op_t TempOp, sval_t BaseValue, ea_t &offset, size_t &DataSize, bool &FP, bool &Indexed, bool &Signed, bool &Unsigned); // Find any stack memory access in TempOp, return offset, size, diff --git a/SMPInstr.cpp b/SMPInstr.cpp index 03c0472d..f11162e9 100644 --- a/SMPInstr.cpp +++ b/SMPInstr.cpp @@ -2985,7 +2985,7 @@ void SMPInstr::MDGetUnnormalizedOp(op_t &NormOp) { // of a negative offset from the entry point of the function. SignedOffset = (sval_t) NormOp.addr; SignedOffset -= this->GetStackPtrOffset(); - assert(0 <= SignedOffset); + assert((0 <= SignedOffset) || this->GetBlock()->GetFunc()->DoesStackFrameExtendPastStackTop()); } NormOp.addr = (ea_t) SignedOffset; } -- GitLab