确定函数符号(字符串)的地址范围的正确方法是什么? 我将在Linux上使用静态链接的,非剥离的C程序。
例如,我想做这样的事情:
char* func_name = get_string_from_user();
printf("start address: %p \n", get_addr_range(func_name).start);
printf("end address: %p \n", get_addr_range(func_name).end);
其中起始地址应该是当前在内存中布局的函数的实际地址。 我认为gdb和objdump执行类似的操作,所以它应该是可能的,对吗?
感谢。
答案 0 :(得分:2)
您可以查看随binutils提供的BFD库(使用objdump和其他文件)。我曾经简单地使用过它,就我记忆而言,这并不是一件微不足道的事。
有一些使用示例(搜索“使用libbfd”或类似的东西)。 我建议也阅读binutils实用程序源代码。
还有ELF和DWARF例程附带的elfutils。虽然没有使用那个,但文档看起来很稀疏。
答案 1 :(得分:1)
通常无法获得整个功能范围。
充其量,您可以获得起始地址。这是一个例子,它不是便携式的:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("fputs = %p\n", (void *)fputs);
return 0;
}
这是不可能的原因是因为通常,链接器使用的关于每个对象的唯一信息,无论是函数还是数据,都是它的地址和名称(以及一些其他数据)。链接器并不关心有多大。
现在,如果调试数据存在于给定函数中,那么可以通过检查调试数据来找出函数的大小。您可以使用库来解析数据,因为它可能有点复杂。以下是有关DWARF的一些信息的链接,如果这是您正在使用的格式:
请注意,您可以在编译程序时以任何您喜欢的格式放置调试数据,或者将其完全保留。 STABS和DWARF在Linux上很常见。但是,仅仅因为没有剥离可执行文件或库并不意味着调试数据存在。
答案 2 :(得分:1)
有可能获得起始地址,但很难获得一个函数的结束地址。 GTK的功能类似于动态Glade绑定的要求。
要自己执行此操作,请使用libtool将应用程序编译为动态加载的图像(如共享库),并使用libtool -export-dynamic
选项将图像设置为导出的名称。
了解更多信息see this link to Libtool documentation.
要使用的链接命令是:
libtool gcc -export-dynamic -o program main.o
使用所需的-export-dynamic
开关编译后,您可以调用dlopen()
动态打开可执行映像作为动态库,并dlsym()
获取特定符号的地址。