如何将函数符号映射到地址范围

时间:2011-03-03 21:58:05

标签: c linux

确定函数符号(字符串)的地址范围的正确方法是什么? 我将在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执行类似的操作,所以它应该是可能的,对吗?

感谢。

3 个答案:

答案 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()获取特定符号的地址。