2012-04-04 2 views
4

Так что я написал два простых классов - X86StackFrame и 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_; 
}; 

Ключевой метод здесь X86CallStack т е р в:

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 может дать вам верхнюю и нижнюю часть стека, чтобы вы могли остановиться перед чтением чего-либо за пределами этого диапазона. Однако я понятия не имею, как получить подобную информацию о других ОС.

+0

Отлично, спасибо! – szx

Смежные вопросы