c-ELF中全局变量的顺序



我有一个简单的C程序,它有四个全局变量:

$ cat example.c
int x;
int y;
int z;
int w;
int main()
{
x = 5;
y = 6;
z = 7;
w = 8;
return x+y+z+w;
}

当我看到他们在ELF文件中的位置时,我感到惊讶,因为他们没有根据他们的声明进行组织:CCD_ 1。相反,它是z (0x60102c), x(0x601030), w(0x601034), y(0x601038):

$ clang -g -O0 -o example example.c
$ objdump -S example | cat -n | sed -n '100,123p;124q'
100  int main()
101  {
102    400460:   55                      push   %rbp
103    400461:   48 89 e5                mov    %rsp,%rbp
104    400464:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)
105      x = 5;
106    40046b:   c7 04 25 30 10 60 00    movl   $0x5,0x601030
107    400472:   05 00 00 00 
108      y = 6;
109    400476:   c7 04 25 38 10 60 00    movl   $0x6,0x601038
110    40047d:   06 00 00 00 
111      z = 7;
112    400481:   c7 04 25 2c 10 60 00    movl   $0x7,0x60102c
113    400488:   07 00 00 00 
114      w = 8;
115    40048c:   c7 04 25 34 10 60 00    movl   $0x8,0x601034
116    400493:   08 00 00 00 
117  
118      return x+y+z+w;
119    400497:   8b 04 25 30 10 60 00    mov    0x601030,%eax
120    40049e:   03 04 25 38 10 60 00    add    0x601038,%eax
121    4004a5:   03 04 25 2c 10 60 00    add    0x60102c,%eax
122    4004ac:   03 04 25 34 10 60 00    add    0x601034,%eax
123    4004b3:   5d                      pop    %rbp

这只是武断吗?有没有具体的理由不组织他们根据他们的声明?谢谢

您使用的是临时定义(没有非零初始化项),因此编译器实际上并不确定数据布局。文件中的某个地方可能有一个定义(可能是用汇编程序编写的),它强加了与编译器在汇编程序文件中产生的顺序完全不同的顺序,然后链接编辑器将被迫在输出部分按特定顺序分配对象。

在我的案例中,Clang实际上生产了这个:

.type   x,@object               # @x
.comm   x,4,4
.type   y,@object               # @y
.comm   y,4,4
.type   z,@object               # @z
.comm   z,4,4
.type   w,@object               # @w
.comm   w,4,4

外部汇编程序(来自GNU binutils)将其转换为(如eu-readelf -s所示;readelf -sW应该同样工作良好):

18: 0000000000000004      4 OBJECT  GLOBAL DEFAULT   COMMON x
19: 0000000000000004      4 OBJECT  GLOBAL DEFAULT   COMMON y
20: 0000000000000004      4 OBJECT  GLOBAL DEFAULT   COMMON z
21: 0000000000000004      4 OBJECT  GLOBAL DEFAULT   COMMON w

(由于暂定定义,COMMON。)

Clang中的内部汇编程序本身产生:

8: 0000000000000004      4 OBJECT  GLOBAL DEFAULT   COMMON w
9: 0000000000000004      4 OBJECT  GLOBAL DEFAULT   COMMON x
10: 0000000000000004      4 OBJECT  GLOBAL DEFAULT   COMMON y
11: 0000000000000004      4 OBJECT  GLOBAL DEFAULT   COMMON z

在我的系统上,来自binutils的BFD ld将其转换为:

54: 000000000060102c      4 OBJECT  GLOBAL DEFAULT       23 z
55: 0000000000601030      4 OBJECT  GLOBAL DEFAULT       23 x
65: 0000000000601034      4 OBJECT  GLOBAL DEFAULT       23 w
66: 0000000000601038      4 OBJECT  GLOBAL DEFAULT       23 y

奇怪的是,来自同一个binutils(2.28)版本的黄金产生了:

25: 0000000000402014      4 OBJECT  GLOBAL DEFAULT       24 w
26: 0000000000402020      4 OBJECT  GLOBAL DEFAULT       24 z
27: 000000000040201c      4 OBJECT  GLOBAL DEFAULT       24 y
28: 0000000000402018      4 OBJECT  GLOBAL DEFAULT       24 x

我的最佳猜测是,在BFD ld的情况下,它恰好是一些哈希表迭代顺序,而gold使用字典符号排序。

请注意,发生这种情况的大部分原因是暂定的定义和通用符号。汇编器和链接编辑器不允许对同一节中的常规数据对象定义进行重新排序,因此,如果禁用公共符号的使用,则编译器将在汇编器输出中生成任何内容。对象定义顺序仍然没有由语言标准定义,但如果编译器手册有任何额外的保证,您可以查看它。

相关内容

  • 没有找到相关文章

最新更新