Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在Windows中以编程方式从调用堆栈帧读取函数参数?_C++_Windows_Winapi_Windbg_Callstack - Fatal编程技术网

C++ 如何在Windows中以编程方式从调用堆栈帧读取函数参数?

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

我试图遍历调用堆栈帧并从中提取一些信息。我可以使用WinDBG中的
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的要求,现在几乎——展开表是一件事,这些表需要参数数据,以便能够展开非平凡类型的传递值参数。