简体   繁体   中英

How to determine end of call stack?

So I wrote two simple classes - X86StackFrame and X86CallStack:

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_;
};

The key method here is X86CallStack's ctor:

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);
}

And the problem is... how do I end that loop? I mean, checking frame/return address against 0 sometimes does the trick but not always (at least here on Windows).

Any suggestions?

On Windows, reading the Thread Information Block can give you the top and bottom of the stack so you can stop before reading anything beyond that range. I have no idea how to get similar info on other OSes, though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM