2012-04-04 9 views
4

だから私は2つの単純なクラスを書いた - X86StackFrameとX86CallStack:ここで重要な方法はX86CallStackのctorのあるコールスタックの終了を判断する方法は?

class X86StackFrame { 
public: 
    X86StackFrame(void *frmAddr, void *retAddr); 

    inline void *GetFrameAddress() const 
     { return frmAddr_; } 
    inline void *GetReturnAddress() const 
     { return retAddr_; } 

private: 
    void *frmAddr_; 
    void *retAddr_; 
}; 

class X86CallStack { 
public: 
    X86CallStack(); 

    inline std::deque<X86StackFrame> GetFrames() const { 
     return frames_; 
    } 

private: 
    std::deque<X86StackFrame> frames_; 
}; 

を:

static inline void *GetReturnAddress(void *frmAddr) { 
    return *reinterpret_cast<void**>(reinterpret_cast<char*>(frmAddr) + 4); 
} 

static inline void *GetNextFrame(void *frmAddr) { 
    return *reinterpret_cast<void**>(frmAddr); 
} 

X86CallStack::X86CallStack() 
    : frames_() 
{ 
    void *frmAddr; 
    void *retAddr; 

    #if defined _MSC_VER 
     __asm mov dword ptr [frmAddr], ebp 
    #elif defined __GNUC__ 
     __asm__ __volatile__(
      "movl %%ebp, %0;" : "=r"(frmAddr) : :); 
    #endif 

    do { 
     if (frmAddr == 0) { 
      break; 
     } 
     retAddr = GetReturnAddress(frmAddr); 
     if (retAddr == 0) { 
      break; 
     } 
     frmAddr = GetNextFrame(frmAddr); 
     frames_.push_back(X86StackFrame(frmAddr, retAddr)); 
    } while (true); 
} 

そして問題は、私がループすることを終わらんか...でしょうか?つまり、フレーム/リターンアドレスを0と照合することは、時にはトリックですが、必ずしもそうではありません(少なくともここではWindows)。

提案がありますか?

+0

gcc.tgz/gcc/config/ia64/unwind-ia64.cが見つかりました。また、getcontextとpthreadライブラリからの何かがスレッドスタックメモリ領域を与えるでしょう。 –

+0

AFAIKはスタックフレームのみに依存しているため、この標準に準拠していない(標準スタックフレームを作成する)関数があるため、完璧な解決策ではありません。 MSVCデバッガには、コールスタックを完全に回復するためのシンボルも必要です。とにかく、スタックフレームが一貫しているならば、スタックの終わりは実際にゼロリターンアドレスによってマークされます。 – valdo

答えて

3

Windowsの場合、Thread Information Blockを読むとスタックの上部と下部がわかるので、その範囲を超えるものを読み取る前に停止することができます。私は他のOSと同様の情報を得る方法を知らない。

+0

よかった、ありがとう!! – szx

関連する問題