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

C 如何从编译器获取指针和变量大小-从编译代码外部?,c,compiler-construction,pointers,C,Compiler Construction,Pointers,我希望编译器输出一个文件,其中包含指向它正在编译的源代码中所有全局变量的指针,以及它们的大小 这可能吗?在任何c编译器中都有这样做的方法吗?类似于映射文件的东西?这将显示全局变量和静态变量的分配位置,而不是它们指向的位置。大多数编译器(链接器)将自动或通过简单语句输出一个。只需在文档中搜索地图文件。类似地图文件的内容?这将显示全局变量和静态变量的分配位置,而不是它们指向的位置。大多数编译器(链接器)将自动或通过简单语句输出一个。只需在文档中搜索映射文件。虽然输出此数据不需要编译器,但大多数链接器

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


这可能吗?在任何c编译器中都有这样做的方法吗?

类似于映射文件的东西?这将显示全局变量和静态变量的分配位置,而不是它们指向的位置。大多数编译器(链接器)将自动或通过简单语句输出一个。只需在文档中搜索地图文件。

类似地图文件的内容?这将显示全局变量和静态变量的分配位置,而不是它们指向的位置。大多数编译器(链接器)将自动或通过简单语句输出一个。只需在文档中搜索映射文件。

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


您可能还可以找到一种方法来检查为可执行文件生成的调试符号,因为调试器无论如何都必须这样做。

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


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

通常,您可以从链接器而不是编译器获得此信息——链接器是为对象分配地址的工具。大多数链接器可以生成一个映射文件,其中包含全局变量和函数的地址(以及它创建的可执行文件中的任何其他符号)。由你来决定哪些是哪些。我看到的所有链接都包含一些要告诉您的内容,但具体格式因所涉及的链接器而异。

通常,您会从链接器而不是编译器获得这些内容——链接器是为内容分配地址的工具。大多数链接器可以生成一个映射文件,其中包含全局变量和函数的地址(以及它创建的可执行文件中的任何其他符号)。由你来决定哪些是哪些。我看到的所有这些文件都包含一些要告诉您的内容,但具体格式因所涉及的链接器而异。

此信息可在二进制文件的符号表中找到,尽管它可能不是您所期望的

编译器获取一个或多个源文件,将代码编译为目标代码,并生成一个目标文件(.o在Unix上,.obj在Windows上)。符号表中提到了源文件中引用的所有变量和函数。源文件中定义的变量和函数具有特定的地址和大小,而源文件中未定义的符号标记为未定义,以后必须链接。列出了与特定节相关的所有符号。公共部分是“.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;
}
现在我可以查看符号表:

$ 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

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

此信息在二进制文件的符号表中可用,尽管它可能不是您所期望的

编译器获取一个或多个源文件,将代码编译为目标代码,并生成一个目标文件(.o在Unix上,.obj在Windows上)。符号表中提到了源文件中引用的所有变量和函数。源文件中定义的变量和函数具有特定的地址和大小,而源文件中未定义的符号标记为未定义,以后必须链接。列出了与特定节相关的所有符号。公共部分是可执行代码的“.text”,程序启动时初始化为零的变量的“.bss”,以及“.data”f
00000000 g     O .rodata        0000000e message