C++ 如何在Windows中以编程方式从调用堆栈帧读取函数参数?
我试图遍历调用堆栈帧并从中提取一些信息。我可以使用WinDBG中的C++ 如何在Windows中以编程方式从调用堆栈帧读取函数参数?,c++,windows,winapi,windbg,callstack,C++,Windows,Winapi,Windbg,Callstack,我试图遍历调用堆栈帧并从中提取一些信息。我可以使用WinDBG中的StackWalk64、SymGetSymFromAddr64和SymGetLineFromAddr64API提取文件名、行号和函数名 但是,STACKFRAME64中的DWORD64参数[4]是来自StackWalk64的返回值,它仅支持从帧中读回四个64位函数参数。更糟糕的是,在32位系统上,仅使用参数[4]的较低32位,因此超过32位的单个参数需要两个或更多元素 typedef struct _tagSTACKFRAME64
StackWalk64
、SymGetSymFromAddr64
和SymGetLineFromAddr64
API提取文件名、行号和函数名
但是,STACKFRAME64
中的DWORD64参数[4]
是来自StackWalk64
的返回值,它仅支持从帧中读回四个64位函数参数。更糟糕的是,在32位系统上,仅使用参数[4]
的较低32位,因此超过32位的单个参数需要两个或更多元素
typedef struct _tagSTACKFRAME64 {
ADDRESS64 AddrPC;
ADDRESS64 AddrReturn;
ADDRESS64 AddrFrame;
ADDRESS64 AddrStack;
ADDRESS64 AddrBStore;
PVOID FuncTableEntry;
DWORD64 Params[4];
BOOL Far;
BOOL Virtual;
DWORD64 Reserved[3];
KDHELP64 KdHelp;
} STACKFRAME64, *LPSTACKFRAME64;
我找不到任何API可以无限制地从堆栈帧读取所有参数
我正在考虑使用ebp
/rbp
从堆栈(x86/x64)和寄存器(x64)中提取值。但是,如果我这样做,仍然只能获得参数的“可能”值
有什么API可以用来获取准确的值吗?如果我能得到参数的类型和名称,那就更好了。它没有API。为什么会有,现代操作系统对一些人玩这种东西不感兴趣。 如前所述,编译器可以自由地进行优化,因此您不能使用任何确定性工具进行优化。 但是,这里有启发法!如果您在调用之前或调用之后解析assembly或ret,您可以知道函数中有多少参数,您总是有返回地址,可以检查它是否在CS中
最重要的是,您应该阅读术语“堆栈展开”。您无法获得准确的值,因为编译器可以自由地优化其参数使用,使原始参数不再存储在堆栈上。(例如,在X64上,参数在寄存器中传递,并且可能永远不会被写入堆栈。)从STACKFrAM64获得的值是最好的努力。<代码> SoGeSimulfDMADRS4< /COD>给您函数本身的符号名称,它是一个被损坏的C++名称。如果通过demangler运行该函数,则可以派生参数类型,尽管仅知道类型可能不足以解释
Params
成员。但我认为这是最接近的。这样一个API不可能存在的原因是@RaymondChen给出的原因。操作系统不知道编译器做了什么。参数可能已经不存在了。例如,如果在第10行之后没有使用参数,编译器可能会将内存重新用于其他用途。您在第14行调用另一个函数,然后询问“参数2的值是多少?”答案是“信息不再存在”。“即使是MSVC和WinDBG,如果它们不再存在,也无法获得这些参数。由于EH的要求,现在几乎——展开表是一件事,这些表需要参数数据,以便能够展开非平凡类型的传递值参数。