Linux kernel ld linux.so*本身是如何链接和加载的?
出于好奇,Linux动态链接器/加载程序是如何链接和加载的Linux kernel ld linux.so*本身是如何链接和加载的?,linux-kernel,linker,ld,loader,Linux Kernel,Linker,Ld,Loader,出于好奇,Linux动态链接器/加载程序是如何链接和加载的 上面的屏幕截图显示,文件和ldd似乎给出了矛盾的结果:一个说静态链接,另一个说动态链接 那么加载程序本身是如何加载的呢 ld linux.so*不依赖于任何其他库。当加载到内存时,它可以自己运行 ldd是一个脚本,它通过加载程序加载对象文件,加载程序检查对象是动态链接还是静态链接,请尝试以下操作: LD_TRACE_LOADED_OBJECTS=1/lib64/LD-linux-x86-64.so.2/lib64/LD-linux-x8
文件
和ldd
似乎给出了矛盾的结果:一个说静态链接,另一个说动态链接ld linux.so*
不依赖于任何其他库。当加载到内存时,它可以自己运行ldd
是一个脚本,它通过加载程序加载对象文件,加载程序检查对象是动态链接还是静态链接,请尝试以下操作:LD_TRACE_LOADED_OBJECTS=1/lib64/LD-linux-x86-64.so.2/lib64/LD-linux-x86-64.so.2
文件
读取幻数或elf头以确定对象是动态链接还是静态链接,它可能会输出与ldd不同的值
ld linux.so
是静态链接的,因为它没有所有动态链接对象都必须具有的.interp
部分
ld linux.so*
不依赖于任何其他库。当加载到内存时,它可以自己运行ldd
是一个脚本,它通过加载程序加载对象文件,加载程序检查对象是动态链接还是静态链接,请尝试以下操作:LD_TRACE_LOADED_OBJECTS=1/lib64/LD-linux-x86-64.so.2/lib64/LD-linux-x86-64.so.2
文件
读取幻数或elf头以确定对象是动态链接还是静态链接,它可能会输出与ldd不同的值
ld linux.so
是静态链接的,因为它没有所有动态链接对象都必须具有的.interp
部分。@臧明杰
你的回答对我帮助很大,但下面的话可能会让一些人感到困惑:
在IMO中,ld-linux.so是静态链接的,因为它没有所有动态链接对象都必须具有的.interp>部分
我们应该将“所有动态链接对象”分为两部分,其中一类我们称为“共享对象”,如下所示:
gcc -c -o test.o test.c -fPIC
ld -o test.so test.o -shared
void foobar(void){ while(1); }
另一种称为“动态链接可执行文件”:
gcc -c -o test.o test.c -fPIC
ld -o test.so test.o
有两点很重要:
1,共享对象没有“.iNTERP”段,而动态链接的可执行文件有
2、Linux内核不关心ELF文件是由ELF头指示的EXEC文件还是DYN文件。他首先搜索.INTERP段,如果失败,他将为每个加载类型段添加一个mmap(),并将控制传递给eheader->e_条目,无论他加载的是可执行文件还是共享对象
由于ld-linux.so是一个常见的共享对象,所以她没有.INTERP段并不奇怪。她可以作为可执行文件运行并不奇怪。每个共享对象都可以
编写如下代码:
gcc -c -o test.o test.c -fPIC
ld -o test.so test.o -shared
void foobar(void){ while(1); }
将其编译为共享对象(使用上面的命令行)。
运行它:
您将使流程陷入死循环。
使用Ctrl-C中断它。您将看到(需要gcc的-g选项)
你可以走得更远:
(gdb) p $eip
$1 = (void (*)()) 0x80000183 <foobar+3>
(gdb)
(gdb)p$eip
$1=(无效(*)()0x80000183
(gdb)
如果您熟悉linux内核,您应该知道0x8000000与内核变量“mmap_min_addr”的值有关。因为test.so是一个共享对象,所以她的加载地址为零,所以内核为她找到了一个默认的虚拟地址,即0x8000000,而不是0x804000
我不知道我怎么会这么离题…@臧明杰
你的回答对我帮助很大,但下面的话可能会让一些人感到困惑:
在IMO中,ld-linux.so是静态链接的,因为它没有所有动态链接对象都必须具有的.interp>部分
我们应该将“所有动态链接对象”分为两部分,其中一类我们称为“共享对象”,如下所示:
gcc -c -o test.o test.c -fPIC
ld -o test.so test.o -shared
void foobar(void){ while(1); }
另一种称为“动态链接可执行文件”:
gcc -c -o test.o test.c -fPIC
ld -o test.so test.o
有两点很重要:
1,共享对象没有“.iNTERP”段,而动态链接的可执行文件有
2、Linux内核不关心ELF文件是由ELF头指示的EXEC文件还是DYN文件。他首先搜索.INTERP段,如果失败,他将为每个加载类型段添加一个mmap(),并将控制传递给eheader->e_条目,无论他加载的是可执行文件还是共享对象
由于ld-linux.so是一个常见的共享对象,所以她没有.INTERP段并不奇怪。她可以作为可执行文件运行并不奇怪。每个共享对象都可以
编写如下代码:
gcc -c -o test.o test.c -fPIC
ld -o test.so test.o -shared
void foobar(void){ while(1); }
将其编译为共享对象(使用上面的命令行)。
运行它:
您将使流程陷入死循环。
使用Ctrl-C中断它。您将看到(需要gcc的-g选项)
你可以走得更远:
(gdb) p $eip
$1 = (void (*)()) 0x80000183 <foobar+3>
(gdb)
(gdb)p$eip
$1=(无效(*)()0x80000183
(gdb)
如果您熟悉linux内核,您应该知道0x8000000与内核变量“mmap_min_addr”的值有关。因为test.so是一个共享对象,所以她的加载地址为零,所以内核为她找到了一个默认的虚拟地址,即0x8000000,而不是0x804000
我不知道我怎么会偏离主题…LD_TRACE_LOADED_OBJECTS=1/lib64/LD-linux-x86-64.so.2/lib64/LD-linux-x86-64.so.2加载加载程序本身并计算加载了多少个对象?顺便问一下,一般来说,loader/lib64/ld-linux-x86-64.so.2本身是如何进入内存的?内核加载loader.so.2,并且loader使用open()和mmap()调用sld_TRACE_LOADED_OBJECTS=1/lib64/ld-linux-x86-64.so.2/lib64/ld-linux-x86-64.so.2加载loader本身并计算加载了多少个对象?顺便问一下,一般来说,loader/lib64/ld-linux-x86-64.so.2本身是如何进入内存的?内核加载loader.and loader使用open()和mmap()调用hanks来解释!这不是那么离题。谢谢你的解释!这不是那么离题。