在 32 位应用程序中,我使用我正在开发的 dll。 在这个dll中,有一个函数(更准确地说,是一个类方法),我们将其称为my_function,它是my_class的一个方法。它的调用约定是 thiscall。
第一个参数是 this (对类实例的引用),它通过 ecx 寄存器传递。 第二个参数是我称之为 packet 的结构的地址。指向数据包的指针通过堆栈传递。
问题: 应用程序在我的 dll 中调用 my_function,传递对 my_class 类实例的引用,以及对 packet 的引用作为第二个参数。
void my_class::my_function(Packet* packet)
{
dump_stack(&packet);
}
我想获取第二个参数的地址。知道这是通过堆栈传递给 my_function 的参数,我从它的地址(堆栈上的地址)中减去 8 个字节,并得到堆栈上 ebp 所在的位置。我需要这个值来遍历所有堆栈帧并通过返回地址(位于附近)查看调用链。 代码调试完美,无需优化即可运行多年。 不久前,我决定启用优化,发现在 my_function 内部创建了一个局部变量,并且地址被传递给局部变量,而不是像以前那样实际上传递给第二个参数。
我在 dump_stack 函数中插入了 printf ,我看到它打印了返回地址下的参数地址。这太棒了,也应该是这样的。没有优化就是这样。
当我启用优化时,我看到其他代码在堆栈上分配内存并将对数据包的引用复制到分配的内存区域,然后将该内存区域的地址传递给 dump_stack 函数
还有其他方法可以使用更强大的东西来遍历调用堆栈吗?我知道这是不可移植的代码,并且它的级别较低,不必按我的预期工作。
或者我如何获取 &packet 以返回传递给 my_function 的参数最初所在的地址
指针
Packet* packet
根据定义是按值复制的,仅引用目标,因此您可以将packet
视为函数的局部变量。packet
的引用时,您将获得参数的地址,而不是输入指针的地址。
编译器可能会决定优化这个变量。
如果要访问输入参数的地址,请使用对指针的引用。
获取引用的地址将返回原始参数的地址。您需要一个 const 引用来实现相同的可用性。
#include <iostream>
#include <string>
#include <algorithm>
void my_function1(int* packet)
{
std::cout << &packet << "\n";
}
void my_function2(int* const& packet)
{
std::cout << &packet << "\n";
}
int main()
{
int i = 10;
my_function1(&i);
my_function2(&i);
return 0;
}
示例输出:
0x7ffc1623b318
0x7ffc1623b338