我手头有一个指向C/C++变量的指针。是否可能确定该变量属于内存的哪个段?如果可以,如何确定?
注意:我只有这个变量的地址,没有进一步的信息,例如变量是本地的还是全局的等。
我手头有一个指向C/C++变量的指针。是否可能确定该变量属于内存的哪个段?如果可以,如何确定?
注意:我只有这个变量的地址,没有进一步的信息,例如变量是本地的还是全局的等。
查找您的架构是否有指向堆或栈区域的指针。通常有一些堆栈指针或帧指针。
然后将实际地址与这些地址进行比较,并确定它们属于哪个区域。
/proc/<pid>/maps
中找到相关信息。您可以首先确定可执行文件中不同部分的起始和结束位置。为此,您需要在链接器脚本中添加一些变量来标识每个部分,例如:
SECTIONS {
[...]
.data : {
data_start = .;
*(.data)
data_end = .;
}
[...]
}
然后,您可以在C/C++代码中将这些变量声明为外部变量,并直接使用它们来比较您想要识别的地址。
调整链接器脚本可能并不容易。使用gcc,您可以通过以下命令将其转储出来:
gcc -Wl,-verbose whatever.c
然后尝试在(混乱的)输出中查找已定义的变量。
要获取堆栈的边界,您可以在main()函数开头实例化一个虚拟变量,并将其地址保存为堆栈顶部,然后在当前位置实例化另一个变量,这将给您底部。但是,请注意编译器可能不会完全像这样行事(C语言中变量的堆栈顺序不能保证,甚至不能保证使用堆栈),因此这应该可以工作,但不具备可移植性。
最后,对于堆,我没有什么技巧。我只会推断出不在data/bss/derivated中且不在堆栈中的变量将在堆中(排除寄存器,但如果您可以获取地址,我敢打赌编译器永远不会使用仅寄存器存储)。
我不确定它是否适用于您的情况,但您可以尝试使用 objdump -t
来查看 ELF 文件的符号表。您只需要知道变量的地址即可。在那里,您可以找到显示每个变量所属部分的标志。有关更多详细信息,请参阅 objdump
的手册页面。
示例输出:
0804a020 g O .bss 00000004 var
它表示var
是一个g
lobal O
bject,位于地址0804a020
,部分为.bss