我想学习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
,d
和f
属于.bss
段,a
,c
和e
属于数据段,但我不知道全局静态变量和elf文件中的全局变量之间的区别。
答案 0 :(得分:13)
您可以使用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
和f
.bss
a
,c
和e
,你是对的。是.data
。符号是否为静态记录在符号表的单独标志中 - 即第二列中的l
或g
标志。
elf(5) man page表示这些是使用符号表的STB_LOCAL
成员的STB_GLOBAL
和st_info
值记录的。 /usr/include/elf.h
表示STB_GLOBAL
为1,而STB_LOCAL
为0.有一个宏ST_BIND
可以检索st_info
字段的绑定位。
objdump
还有很多其他标志 - 请参阅man page。 objdump
适用于所有体系结构,但还有一个elfdump
工具可以更好地显示特定于elf的内容。 objdump
和基础BFD
库在显示某些特定于文件格式的数据方面做得不好。
答案 1 :(得分:7)
通常,可执行文件的数据段包含初始化的全局/静态变量,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) |
+------------------------+