我正在尝试理解共享库。据我所知,共享库的基址为零,因此可以在运行时在任何地址加载它们,因此在运行时或加载时间内正确地重定位变量。因此,在加载库之前,所有符号都会从库的基础中获得一些偏移量。因此,我尝试调查一些现有的库,并创建了一个库。但我发现了一些差异。对于libc.so,我发现的是:
$ objdump -D /lib64/libc.so.6
/lib64/libc.so.6: file format elf64-x86-64
Disassembly of section .note.gnu.build-id:
0000003b47a00270 <.note.gnu.build-id>:
3b47a00270: 04 00 add $0x0,%al
3b47a00272: 00 00 add %al,(%rax)
3b47a00274: 14 00 adc $0x0,%al
3b47a00276: 00 00 add %al,(%rax)
3b47a00278: 03 00 add (%rax),%eax
[More contents...]
据我所知,精灵标题占用了一些空间。但即使这样,它也不会占用从0到0x3b47a00270的地址。 所以,我创建了自己的库(使用-fPIC和-shared标志),我看到了这个:
$ objdump -D ./libvector.so
./libvector.so: file format elf64-x86-64
Disassembly of section .note.gnu.build-id:
00000000000001c8 <.note.gnu.build-id>:
1c8: 04 00 add $0x0,%al
1ca: 00 00 add %al,(%rax)
1cc: 14 00 adc $0x0,%al
1ce: 00 00 add %al,(%rax)
1d0: 03 00 add (%rax),%eax
[More contents...]
这个地址在地址方面似乎更合理。 .note.gnu.build-id从0x1c8开始。所以,伙计们有任何想法,为什么在libc或libpthread等其他现有库的情况下,情况有所不同?我正在使用fedora 18 x86_64。我认为这可能是一个预连接的情况,但我不确定,即使它是如何发现它是预先链接的? 非常感谢...
答案 0 :(得分:1)
objdump -D /lib64/libc.so.6
您正在反汇编不包含代码的部分。既然你还没有(还)理解你在做什么,那就坚持objdump -d
- 这会让你更加困惑。
据我所知,共享库的基地址为零
上述陈述不正确:共享库可能的基址为零,但他们没有。
为什么在libc或libpthread等其他现有库的情况下,情况不同
因为这些库已预先链接。参见“man prelink”,例如here
您可以使用readelf -l
更清楚地看到这一点。您想查看第一个VirtAddr
细分的LOAD
。
如果是非预链接库,则该地址为0.如果是预链接libc.so.6
,则为0x3b47a00000
。另请注意,RedHat系统通常设置为每两周重新运行预链接,因此libc.so.6
预先链接的地址可能会随时间而变化。