Порядок глобальных переменных в ELF - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть простая программа на 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, я был удивлен , потому что они были не организованы согласно их декларациям: x, y, z, w.Вместо этого это было 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

Это просто произвольно?Есть ли конкретная причина организовать их не в соответствии с их декларацией?спасибо!

1 Ответ

0 голосов
/ 21 декабря 2018

Вы используете предварительные определения (без ненулевых инициализаторов), поэтому компилятор фактически не определяет расположение данных.Где-то в файле может быть определение (возможно, написанное на ассемблере), которое устанавливает совершенно другой порядок, чем тот, который компилятор создает в файле ассемблера, и тогда редактор ссылок будет вынужден размещать объекты в определенном порядке в секции вывода.

В моем случае 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

В моей системе BFD ld из binutils превращает это в:

   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 это просто случайный порядок итераций в хэш-таблице, и золото использует лексикографический порядок символов.

Обратите внимание, что большая часть этого происходит из-за предварительных определений.и общие символы.Ассемблеру и редактору ссылок не разрешается переупорядочивать обычные определения объектов данных в одном и том же разделе, поэтому, если вы отключите использование общих символов, вы получите все, что компилятор произведет в выходных данных ассемблера.Порядок определения объекта все еще не определен языковым стандартом, но вы можете проверить руководство компилятора, если оно дает какие-либо дополнительные гарантии.

...