如何从编译器中获取指针和变量大小 - 从编译代码外部?

时间:2010-07-01 17:15:15

标签: c compiler-construction pointers

我希望编译器输出一个文件,其中包含指向它正在编译的源代码中的所有全局变量的指针,以及它们的大小。

这可能吗?有没有办法在任何c编译器中执行此操作?

4 个答案:

答案 0 :(得分:3)

像地图文件?这将显示全局和静态分配的位置,但不会显示它们所指向的位置。大多数编译器(链接器)将自动输出一个或使用简单的语句。只需在文档中搜索地图文件即可。

答案 1 :(得分:1)

虽然输出此数据不需要编译器,但大多数链接器可以转储此信息。例如,Microsoft的链接器mapfile包含可执行文件/ dll中的所有公共符号以及它们相对于它们放入的部分(只读,读写,代码,零初始化等)的地址。大小可以从虽然它主要是近似值。

您也可以找到一种方法来检查为可执行文件生成的调试符号,因为这正是调试器必须要做的事情。

答案 2 :(得分:1)

通常你会从链接器而不是编译器得到这个 - 链接器就是为事物分配地址的东西。大多数链接器可以生成一个映射文件,该文件将包含全局变量函数的地址(以及它创建的可执行文件中的任何其他符号)。由你来决定哪些是哪个。我所看到的所有内容都包含了一些内容,但确切的格式因所涉及的链接器而异。

答案 3 :(得分:1)

此信息可在二进制文件的符号表中找到,但它可能并不代表您的预期。

编译器获取一个或多个源文件,将代码编译为目标代码,并生成目标文件(Unix上为.o,Windows上为.obj)。在源文件中引用的所有变量和函数都在符号表中提及。源文件中定义的变量和函数具有特定的地址和大小,而源文件中未定义的符号标记为未定义,必须稍后链接。所有符号都是相对于特定部分列出的。常用部分是可执行代码的“.text”,“。bss”表示程序启动时初始化为零的变量,“.data”表示用非零值初始化的变量。

链接器接受一个或多个目标文件,组合这些部分(将每个目标文件中的所有代码和数据放入代码和数据的一个大部分),并写入输出文件。此输出文件可以是可执行文件,也可以是共享库。磁盘上的可执行文件仍然没有每个变量的指针;它仍然存储从该部分开头到变量的偏移量。

运行可执行文件时,操作系统的动态加载程序将读取可执行文件,查找每个部分,并为该部分分配内存。 (它也可能在每个部分设置不同的权限 - “。text”段通常标记为只读,并且(在支持它的处理器上)数据段有时被标记为不可执行。)变量获取指针 - 当代码需要访问某个特定变量时,它会将该部分开头的地址添加到该部分开头的偏移处以获取指针。

您可以使用各种工具来调查每个二进制文件的符号表。 GNU工具链的objdump(在Linux上使用)就是这样一种工具。

对于一个简单的C hello-world程序:

#include <stdio.h>

const char message[] = "Hello world!\n";

int main(int argc, char ** argv) {
        printf(message);
        return 0;
}

我在Linux机器上编译(但不要链接):

$ gcc -c hello.c -o hello.o

现在我可以查看符号表:

$ objdump -t hello.o
hello.o:     file format elf32-i386

SYMBOL TABLE:
00000000 l    df *ABS*  00000000 hello.c
00000000 l    d  .text  00000000 .text
00000000 l    d  .data  00000000 .data
00000000 l    d  .bss   00000000 .bss
00000000 l    d  .rodata        00000000 .rodata
00000000 l    d  .note.GNU-stack        00000000 .note.GNU-stack
00000000 l    d  .comment       00000000 .comment
00000000 g     O .rodata        0000000e message
00000000 g     F .text  0000002b main
00000000         *UND*  00000000 puts

第一列是每个符号的地址,相对于该部分的开头。每个符号都有各种标志,一些符号用作工具链和调试器其余部分的提示。 (如果我使用调试符号构建,我会看到许多条目也专门用于它们。)我的简单程序只有一个变量:

00000000 g     O .rodata        0000000e message

第五列告诉我符号message的大小为0xe - 14个字节。