Что означает значение символа из команды nm?

Когда вы перечислите таблицу символов в статической библиотеке, например nm mylib.a, что означает 8-значный шест, который отображается рядом с каждым символом? Это относительное расположение каждого символа в коде?

Кроме того, может ли несколько символов иметь одинаковое значение символа? Что-то не так с пучком разных символов, имеющих значение символа 00000000?

Ответы

Ответ 1

Вот фрагмент кода, который я написал в C:


#include 
#include 

void foo();

int main(int argc, char* argv[]) {
    foo();
}

void foo() {
   printf("Foo bar baz!");
}

Я запустил gcc -c foo.c в этом коде. Вот что показал nm foo.o:

000000000000001b T foo
0000000000000000 T main
                 U printf

В этом примере я запускаю 64-разрядную версию Ubuntu Linux; поэтому 8-значный гекс, который вы видите, здесь 16 цифр.: -)

Шестнадцатеричная цифра, которую вы видите, является адресом рассматриваемого кода в объектном файле относительно начала раздела .text.. (предполагая, что мы адресуем разделы объектного файла, начинающегося с 0x0). Если вы запустите objdump -td foo.o, на выходе вы увидите следующее:

Disassembly of section .text:

0000000000000000 :
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 10             sub    $0x10,%rsp
   8:   89 7d fc                mov    %edi,-0x4(%rbp)
   b:   48 89 75 f0             mov    %rsi,-0x10(%rbp)
   f:   b8 00 00 00 00          mov    $0x0,%eax
  14:   e8 00 00 00 00          callq  19 
  19:   c9                      leaveq
  1a:   c3                      retq

000000000000001b :
  1b:   55                      push   %rbp
  1c:   48 89 e5                mov    %rsp,%rbp
  1f:   b8 00 00 00 00          mov    $0x0,%eax
  24:   48 89 c7                mov    %rax,%rdi
  27:   b8 00 00 00 00          mov    $0x0,%eax
  2c:   e8 00 00 00 00          callq  31 
  31:   c9                      leaveq
  32:   c3                      retq

Обратите внимание, что эти два символа располагаются справа от записей, которые мы видели в таблице символов из nm. Однако, если вы связываете этот объектный файл с другими объектными файлами, эти адреса могут измениться. Кроме того, не забывайте, что callq в 0x2c изменится, когда вы свяжете этот файл с любым libc, который предоставляет ваша система, поскольку в настоящее время это неполный вызов printf (он не знает, где он сейчас).

Что касается вашего mylib.a, здесь происходит больше. Файл, который у вас есть, - это архив; он содержит несколько объектных файлов, каждый из которых имеет собственный текстовый сегмент. Например, вот часть nm от /usr/lib/libm.a на моем поле здесь

e_sinh.o:
0000000000000000 r .LC0
0000000000000008 r .LC1
0000000000000010 r .LC2
0000000000000018 r .LC3
0000000000000000 r .LC4
                 U __expm1
                 U __ieee754_exp
0000000000000000 T __ieee754_sinh

e_sqrt.o:
0000000000000000 T __ieee754_sqrt

e_gamma_r.o:
0000000000000000 r .LC0
                 U __ieee754_exp
0000000000000000 T __ieee754_gamma_r
                 U __ieee754_lgamma_r
                 U __rint

Вы увидите, что множественный текстовый сегмент задан - обозначается символом T во втором столбце, остающимся по адресу 0x0, но каждый отдельный файл имеет только один текстовый сегментный символ в 0x0.

Что касается отдельных файлов, содержащих несколько символов, расположенных на одном и том же адресе, похоже, возможно, это возможно. В конце концов, это всего лишь запись в таблице, используемой для определения местоположения и размера части данных. Но я точно не знаю. Я никогда не видел несколько символов, ссылающихся на одну и ту же часть раздела. Любой, кто имеет больше знаний об этом, чем я, может перезвонить.: -)

Надеюсь, это поможет некоторым.

Ответ 2

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

Это значение используется компоновщиком для поиска и копирования копии значения символа. Обычно вы можете увидеть, как это сделать, если вы добавите параметр -S в nm, который покажет вам размер значения для каждого символа.

Ответ 3

nm показывает значения символов. Некоторые символы в библиотеке или объектном файле могут отображаться как ноль просто потому, что они еще не получили значения. Они получат свое фактическое значение во время соединения.

Некоторые символы являются кодовыми символами, некоторые - данными и т.д. Прежде чем связывать значение символа часто является смещением в разделе, в котором он находится,