10

想了解elf文件,但是一想到全局变量、全局静态变量和作用域静态变量,就有些疑惑了。例如:

int a = 2;
int b;

static int c = 4;
static int d;

void fun(){
  static int e = 6;
  static int f;
}


int main(void){
   fun();
}

谁能告诉每个变量属于哪个段?在我看来, b,df属于.bss段,a,ce属于数据段,但是我不知道全局静态变量和elf文件中的全局变量的区别。

4

2 回答 2

18

您可以使用objdump -t查看符号表:

$ objdump -t foo | grep -P '      \b(a|b|c|d|e|f)\b'
0000000000601034 l     O .data  0000000000000004              c
0000000000601040 l     O .bss   0000000000000004              d
0000000000601044 l     O .bss   0000000000000004              f.1710
0000000000601038 l     O .data  0000000000000004              e.1709
0000000000601048 g     O .bss   0000000000000004              b
0000000000601030 g     O .data  0000000000000004              a

你是对的b, d, and fare.bssa, c, and eare .data。符号是否是静态的被记录在符号表的一个单独的标志中——即第二列中的lorg标志。

elf(5) 手册页说这些是使用 符号表成员的STB_LOCALandSTB_GLOBAL值记录的。说是1,而是0。有一个宏来检索字段的绑定位。st_info/usr/include/elf.hSTB_GLOBALSTB_LOCALST_BINDst_info


还有很多其他的标志objdump——参见手册页objdump适用于所有架构,但还有一个elfdump工具可以更好地显示特定于精灵的东西。objdump并且底层BFD库在显示一些特定于文件格式的数据方面做得很糟糕。

于 2013-06-18T02:51:06.707 回答
9

通常,可执行文件的数据段包含已初始化的全局/静态变量,而 BSS 段包含未初始化的全局/静态变量。

当加载器将您的程序加载到内存中时,未初始化的全局/静态变量会自动填充零。

在 C 中,函数内部的静态变量(初始化与否)仅意味着变量具有局部/函数范围(有时称为内部静态),但它们仍然存在于 Data/BSS 段中,具体取决于它们是否被初始化。

所以无论 fun() 被调用多少次,静态变量只会在程序加载时初始化一次。

定义为静态且在任何函数之外的变量仍然存在于数据或 bss 段中,但仅具有文件范围。

编译代码时,每个目标文件都有一个导入和导出列表,供链接编辑器使用。您的静态变量将不在导出列表中,因此其他目标文件无法访问。

通过排除 static 关键字,您的全局变量被放置在导出列表中,并且可以被其他对象模块引用,并且链接编辑器将能够在创建可执行文件时找到符号。

对于图片视图:

+--------- TEXT ---------+  Low memory
| main()                 |
| fun()                  |
+--------- DATA ---------+
| int a (global scope)   |
| int c (file scope)     |
| int e (function scope) |
+---------- BSS ---------+
| int b (global scope)   |
| int d (file scope)     |
| int f (function scope) |
+------------------------+
于 2013-06-18T05:23:24.823 回答