Вот фрагмент кода, который я написал в 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
Для этого примера я бегу Ubuntu Linux 64-бит; поэтому 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
, здесь все происходит. Файл, который у вас есть, - это архив; он содержит несколько объектных файлов, каждый из которых имеет собственный текстовый сегмент. В качестве примера здесь является частью нм против /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
Вы увидите, что несколько заходы сегмент текста - указывает Т во второй колонке отдыха по адресу 0x0, но каждый отдельный файл имеет только один текстовый сегментный символ в 0x0.
Что касается отдельных файлов, имеющих несколько символов, расположенных на одном и том же адресе, это похоже на то, что будет возможно возможно.В конце концов, это всего лишь запись в таблице, используемой для определения местоположения и размера части данных. Но я точно не знаю. Я никогда не видел несколько символов, ссылающихся на одну и ту же часть раздела. Любой, кто имеет больше знаний об этом, чем я, может перезвонить. :-)
Надеюсь, это поможет некоторым.
Если вы скомпилируете свой пример с помощью 'x86_64-w64-mingw32-g ++', вы увидите с помощью 'nm' несколько символов, которые ссылаются на нулевой адрес и имеют знак« A », то есть адрес не будет в будущем. Например. '0000000000000000 A __dll__ 0000000000000000 A __dll_characteristics__'. По сути - [я видел, что были] (http://unix.stackexchange.com/q/158162/59928) отображал фактически полезные функции. Мне интересно, что это могло означать? –