I have a C ++ tool that executes a call stack at one point. In the code, it first gets a copy of the active CPU registers (via RtlCaptureContext ()), then uses several #ifdef ... blocks to store the names of the processor-specific registers in stackframe.AddrPC.Offset , ... AddrStack .. . and ... AddrFrame ...; also for each of the 3 Addr ... members above, it sets stackframe.Addr ... .Mode = AddrModeFlat . (This was borrowed from some sample code that I came across a while ago.)
With x86 binary, this works great. Together with the x64 binary code, StackWalk64 () passes dummy addresses. (On the first API call, the only explicitly fake address value appears in AddrReturn (== 0xFFFFFFFF'FFFFFFFE - aka StackWalk64 () 3rd arg, the pseudo descriptor returned by GetCurrentThread ()). The API is called a second time, however, all the Addr variables ... get dummy addresses.) This happens regardless of how AddrFrame set:
- using any of the recommended x64 "base / frame pointers" CPU registers:
rbp (= 0xf ) or rdi (= 0x0 ) - using
rsp (did not expect it to work, but tried anyway) AddrPC and AddrStack usually, but leaving AddrFrame nullified outside (see another code example)- reset all
Addr ... values โโso that StackWalk64 () fills them from the passed-register context (see another example code)
FWIW, the contents of the physical contents of the stack are also different from x64 and x86 (after taking into account the different widths of the pointer and the location of the stack buffer, of course). Regardless of the reason, StackWalk64 () should still walk correctly along the call stack - hell, the debugger can still walk along the call stack and apparently uses StackWalk64 () itself backstage. The oddity is that the (correct) call stack reported by the debugger contains the values โโof the base address pointer and return address, whose component bytes do not actually exist in the stack buffer (lower or higher than the current stack pointer).
(FWIW # 2: Given the weirdness of the buffer stack above, I tried disabling ASLR ( /dynamicbase:no ) to see if this changed, but the binary still showed the same behavior.)
So. Any ideas why this will work well on x86, but have problems on x64? Any suggestions for fixing it?
source share