LD.SO - Linux手册页

时间:2019-08-20 18:02:05  来源:igfitidea点击:

Linux程序员手册 第8部分
更新日期: 2020-08-13

名称

ld.so,ld-linux.so-动态链接器/加载器

语法

动态链接程序可以间接地通过运行一些动态链接的程序或共享对象(在这种情况下,没有命令行选项来动态连接器可以被传递,并且在ELF情况下,被存储在.interp动态链接器上运行程序部分)或直接运行:

/lib/ld-linux.so.* [OPTIONS] [PROGRAM [ARGUMENTS]]

说明

程序ld.so和ld-linux.so *查找并加载程序所需的共享库(共享库),准备运行该程序,然后运行它。

除非在编译期间将-static选项提供给ld(1),否则Linux二进制文件需要动态链接(在运行时链接)。

程序ld.so处理a.out二进制文件,这是很久以前使用的二进制格式。程序ld-linux.so *(对于libc5是/lib/ld-linux.so.1,对于glibc2是/lib/ld-linux.so.2)处理采用更现代的ELF格式的二进制文件。这两个程序具有相同的行为,并使用相同的支持文件和程序(ldd(1),ldconfig(8)和/etc/ld.so.conf)。

当解析共享对象的依赖关系,动态连接器首先检查每个依赖字符串以确定它是否包含斜杠(如果在链接时被指定含有斜线的共享对象路径名可能发生这种情况)。如果找到斜线,则依赖项字符串将解释为(相对或绝对)路径名,并使用该路径名加载共享库。

如果共享库依赖项不包含斜杠,则将按以下顺序搜索它:

o
使用(如果存在)和DT_RUNPATH属性不存在的二进制的DT_RPATH动态部分的属性中指定的目录。不建议使用DT_RPATH。
o
使用环境变量LD_LIBRARY_PATH,除非可执行文件在安全执行模式下运行(请参见下文),在这种情况下,将忽略此变量。
o
使用二进制文件的DT_RUNPATH动态节属性中指定的目录(如果存在)。仅搜索此类目录以查找DT_NEEDED(直接依赖项)条目所需的那些对象,并且不适用于那些必须具有自己的DT_RUNPATH条目的对象的子对象。这与DT_RPATH不同,后者用于在依赖关系树中搜索所有子项。
o
从缓存文件/etc/ld.so.cache中,其中包含先前在增加库路径找到的候选共享对象的汇总列表。但是,如果二进制是用-z nodeflib链接器选项链接,在默认路径共享对象被跳过。硬件功能目录中安装的共享库(请参阅下文)比其他共享库更受青睐。
o
在默认路径/ lib中,然后在/ usr / lib中。 (在某些64位体系结构上,64位共享库的默认路径是/ lib64,然后是/ usr / lib64。)如果二进制文件是使用-z nodeflib链接器选项链接的,则跳过此步骤。

Dynamic string tokens

动态链接器在几个地方扩展了动态字符串标记:

o
在环境变量LD_LIBRARY_PATH,LD_PRELOAD和LD_AUDIT中,
o
动态部分标记DT_NEEDED值内,DT_RPATHDT_RUNPATHDT_AUDIT,和ELF二进制的DT_DEPAUDIT
o
在ld.so命令行选项的参数--audit,-library-path和--preload中(请参见下文),以及
o
dlopen(3)和dlmopen(3)函数的文件名参数中。

取代的令牌如下:

$ORIGIN(or equivalently ${ORIGIN})
这将扩展到包含程序或共享库的目录。因此,可以使用以下命令编译位于somedir / app中的应用程序:
gcc -Wl,-rpath,aq$ORIGIN/../libaq
这样,无论somedir在目录层次结构中位于何处,它都可以在somedir / lib中找到关联的共享对象。这有助于创建"交钥匙"应用程序,这些应用程序不需要安装到特殊目录中,而是可以解压缩到任何目录中,并且仍然可以找到自己的共享库。
$LIB(or equivalently ${LIB})
根据架构的不同,它可以扩展为lib或lib64(例如,在x86-64上,它扩展为lib64,在x86-32上,它扩展为lib)。
$PLATFORM(or equivalently ${PLATFORM})
这扩展为与主机系统的处理器类型相对应的字符串(例如" x86_64")。在某些体系结构上,Linux内核不向动态链接器提供平台字符串。该字符串的值来自辅助向量中的AT_PLATFORM值(请参见getauxval(3))。

请注意,从外壳程序设置动态字符串令牌时必须正确引用该字符串,以防止将其扩展为外壳程序或环境变量。

选项

--auditlist
使用列表中命名的对象作为审核员。列表中的对象由冒号分隔。
--inhibit-cache
不要使用/etc/ld.so.cache。
--library-pathpath
使用路径而不是LD_LIBRARY_PATH环境变量设置(请参见下文)。名称ORIGIN,LIB和PLATFORM的解释与LD_LIBRARY_PATH环境变量相同。
--inhibit-rpathlist
忽略列表中对象名称中的RPATH和RUNPATH信息。在安全执行模式下运行时,将忽略此选项(请参见下文)。列表中的对象由冒号或空格分隔。
--list
列出所有依赖关系以及如何解决它们。
--preloadlist(since glibc 2.30)
预加载列表中指定的对象。列表中的对象由冒号或空格分隔。如下面的LD_PRELOAD环境变量的描述中所述,对象被预加载。
与LD_PRELOAD相比,--preload选项提供了一种对单个可执行文件执行预加载而又不影响在执行新程序的任何子进程中执行的预加载的方法。
--verify
验证程序是动态链接的,并且此动态链接器可以处理它。

环境

各种环境变量会影响动态链接器的操作。

Secure-execution mode

出于安全原因,如果动态链接程序确定二进制文件应在安全执行模式下运行,则某些环境变量的影响将被作废或修改,此外,这些环境变量也会从环境中剥离,因此程序甚至不会请参阅定义。这些环境变量中的一些会影响动态链接器本身的操作,下面将进行描述。以这种方式处理的其他环境变量包括:GCONV_PATHGETCONF_DIRHOSTALIASESLOCALDOMAINLOCPATHMALLOC_TRACENIS_PATHNLSPATHRESOLV_HOST_CONFRES_OPTIONS,TMPDIR和TZDIR。

如果辅助向量中的AT_SECURE项(请参见getauxval(3))具有非零值,则在安全执行模式下执行二进制文件。由于各种原因,该条目可能具有非零值,包括:

*
进程的真实和有效用户ID不同,或者真实和有效的组ID不同。这通常是由于执行设置用户ID或设置组ID程序而发生的。
*
具有非root用户ID的进程执行了二进制文件,该二进制文件赋予了该进程功能。
*
Linux安全模块可能已设置了非零值。

Environment variables

以下是更重要的环境变量:

LD_ASSUME_KERNEL(since glibc 2.2.3)
每个共享库都可以将其所需的最低内核ABI版本通知动态链接器。 (此要求编码在ELF注释部分中,该部分可通过readelf -n标记为NT_GNU_ABI_TAG的部分查看。)在运行时,动态链接程序确定正在运行的内核的ABI版本,并将拒绝加载指定最低ABI版本的共享对象超过该ABI版本。
LD_ASSUME_KERNEL可用于使动态链接器假定它在具有不同内核ABI版本的系统上运行。例如,以下命令行使动态链接器在加载myprog所需的共享库时假定其在Linux 2.2.5上运行:
$ LD_ASSUME_KERNEL=2.2.5 ./myprog
在提供共享对象的多个版本(在搜索路径中的不同目录中)且具有不同的最低内核ABI版本要求的系统上,可以使用LD_ASSUME_KERNEL选择所使用的对象的版本(取决于目录搜索顺序) 。
从历史上看,LD_ASSUME_KERNEL功能的最常见用法是在同时提供LinuxThreads和NPTL的系统上手动选择较早的LinuxThreads POSIX线程实现(后者通常是此类系统上的默认设置);参见pthreads(7)。
LD_BIND_NOW(since glibc 2.1.1)
如果设置为非空字符串,则使动态链接程序在程序启动时解析所有符号,而不是将函数调用解析延迟到首次引用它们时。使用调试器时,这很有用。
LD_LIBRARY_PATH
在执行时在其中搜索ELF库的目录列表。列表中的项目用冒号或分号分隔,并且不支持转义任何分隔符。长度为零的目录名称表示当前的工作目录。
在安全执行模式下将忽略此变量。
在LD_LIBRARY_PATH中指定的路径名​​内,动态链接器将扩展令牌$ ORIGIN,$ LIB和$ PLATFORM(或在名称周围使用花括号的版本),如上文动态字符串令牌中所述。因此,例如,以下操作将导致在包含要执行程序的目录下的lib或lib64子目录中搜索库:
$ LD_LIBRARY_PATH='$ORIGIN/$LIB' prog
(请注意使用单引号,这会阻止将$ ORIGIN和$ LIB扩展为shell变量!)
LD_PRELOAD
在所有其他对象之前要加载的其他用户指定的ELF共享对象的列表。此功能可用于有选择地覆盖其他共享库中的功能。
列表中的各项可以用空格或冒号分隔,并且不支持转义任何一个分隔符。使用在DESCRIPTION下给出的规则搜索对象。将按照列表中指定的从左到右的顺序搜索对象并将其添加到链接映射。
在安全执行模式下,将忽略包含斜杠的预加载路径名。此外,仅当共享对象启用了设置用户ID模式位(这不是典型的)时,才从标准搜索目录中预加载它们。
在LD_PRELOAD列表中指定的名称内,动态链接器理解标记$ ORIGIN,$ LIB和$ PLATFORM(或名称周围使用花括号的版本),如上文动态字符串标记中所述。 (另请参见在LD_LIBRARY_PATH的描述下对引用的讨论。)
There are various methods of specifying libraries to be preloaded, and these are handled in the following order:
(1)
LD_PRELOAD环境变量。
(2)
直接调用动态链接程序时的--preload命令行选项。
(3)
/etc/ld.so.preload文件(如下所述)。
LD_TRACE_LOADED_OBJECTS
如果设置为任何值,则使程序列出其动态依赖项,就像由ldd(1)运行一样,而不是正常运行。

然后有许多或多或少的模糊变量,许多已经过时或仅用于内部使用。

LD_AUDIT(since glibc 2.4)
用户指定的ELF共享对象的列表,这些对象将在单独的链接器命名空间中首先加载,而不要在其他所有链接器命名空间中加载(即,不干扰过程中将发生的常规符号绑定的对象)。动态链接器。列表中的项目以冒号分隔,不支持转义分隔符。
在安全执行模式下,将忽略LD_AUDIT。
动态链接器将通过在审核中调用适当的函数,在所谓的审核检查点(例如,加载新的共享对象,解析符号或从另一个共享对象中调用符号)通知审核共享对象。共享对象。有关详细信息,请参见rtld-audit(7)。审核界面与Solaris上提供的界面基本兼容,如其《链接器和库指南》的"运行时链接程序审核界面"一章中所述。
在LD_AUDIT列表中指定的名称内,动态链接器理解标记$ ORIGIN,$ LIB和$ PLATFORM(或名称周围使用花括号的版本),如上文动态字符串标记中所述。 (另请参见在LD_LIBRARY_PATH的描述下对引用的讨论。)
从glibc 2.13开始,在安全执行模式下,审核列表中包含斜杠的名称将被忽略,只有标准搜索目录中启用了set-user-ID模式位的共享对象才会被加载。
LD_BIND_NOT(since glibc 2.1.95)
如果此环境变量设置为非空字符串,则在解析功能符号后,请勿更新GOT(全局偏移表)和PLT(过程链接表)。通过将此变量与LD_DEBUG(带有类别绑定和符号)结合使用,可以观察到所有运行时函数绑定。
LD_DEBUG(since glibc 2.1)
Output verbose debugging information about operation of the dynamic linker. The content of this variable is one of more of the following categories, separated by colons, commas, or (if the value is quoted) spaces:
help
在此变量的值中指定帮助不会运行指定的程序,而是显示有关可以在此环境变量中指定哪些类别的帮助消息。
all
打印所有调试信息(统计信息和未使用的信息除外;请参见下文)。
bindings
显示有关每个符号绑定到的定义的信息。
files
显示输入文件的进度。
libs
显示库搜索路径。
reloc
显示重定位处理。
scopes
显示范围信息。
statistics
显示重定位统计信息。
symbols
显示每个符号查找的搜索路径。
unused
确定未使用的DSO。
versions
显示版本依赖性。
从glibc 2.3.4开始,除非文件/ etc / suid-debug存在(文件的内容无关),否则在安全执行模式下将忽略LD_DEBUG。
LD_DEBUG_OUTPUT(since glibc 2.1)
默认情况下,LD_DEBUG输出被写入标准错误。如果定义了LD_DEBUG_OUTPUT,则将输出写入由值后缀"。"指定的路径名​​。 (点),后跟附加到路径名的进程ID。
在安全执行模式下,将忽略LD_DEBUG_OUTPUT。
LD_DYNAMIC_WEAK(since glibc 2.1.91)
默认情况下,当搜索共享库以解析符号引用时,动态链接器将解析为其找到的第一个定义。
旧的glibc版本(2.2之前的版本)提供了不同的行为:如果链接程序发现一个弱符号,它将记住该符号并继续在其余共享库中进行搜索。如果随后找到了相同符号的强定义,则它将使用该定义。 (如果未找到其他符号,则动态链接器将使用其最初发现的弱符号。)
旧的glibc行为是不规范的。 (标准做法是,弱符号和强符号之间的区别仅应在静态链接时才有效。)在glibc 2.2中,对动态链接器进行了修改以提供当前行为(该行为是大多数其他实现在当时提供的行为)。时间)。
定义LD_DYNAMIC_WEAK环境变量(具有任何值)会提供旧的(非标准)glibc行为,从而一个共享库中的弱符号可能会被随后在另一个共享库中发现的强符号所覆盖。 (请注意,即使设置了此变量,共享库中的强符号也不会覆盖主程序中同一符号的弱定义。)
从glibc 2.3.4开始,在安全执行模式下将忽略LD_DYNAMIC_WEAK。
LD_HWCAP_MASK(since glibc 2.1)
硬件功能的掩码。
LD_ORIGIN_PATH(since glibc 2.1)
找到二进制文件的路径。
从glibc 2.4开始,在安全执行模式下将忽略LD_ORIGIN_PATH。
LD_POINTER_GUARD(glibc from 2.4 to 2.22)
设置为0将禁用指针防护。任何其他值都会启用指针防护,这也是默认设置。指针防护是一种安全机制,通过这种机制半随机地破坏了一些指向可写程序存储器中存储的代码的指针(由setjmp(3)保存的返回地址或各种glibc内部使用的函数指针),从而使攻击者更难劫持缓冲区溢出或堆栈破坏攻击时使用的指针。从glibc 2.23开始,不再可以使用LD_POINTER_GUARD禁用指针防护,而现在始终启用该功能。
LD_PROFILE(since glibc 2.1)
要进行概要分析的(单个)共享库的名称,指定为路径名或soname。分析输出将附加到名称为" $ LD_PROFILE_OUTPUT / $ LD_PROFILE.profile"的文件。
从glibc 2.2.5开始,在安全执行模式下将忽略LD_PROFILE。
LD_PROFILE_OUTPUT(since glibc 2.1)
LD_PROFILE输出应写入的目录。如果未定义此变量或将其定义为空字符串,则默认值为/ var / tmp。
LD_PROFILE_OUTPUT在安全执行模式下被忽略;而是始终使用/ var / profile。 (此详细信息仅在glibc 2.2.5之前相关,因为在更高版本的glibc中,在安全执行模式下也将忽略LD_PROFILE。)
LD_SHOW_AUXV(since glibc 2.1)
如果已定义此环境变量(具有任何值),则显示从内核传递的辅助数组(另请参见getauxval(3))。
从glibc 2.3.4开始,在安全执行模式下将忽略LD_SHOW_AUXV。
LD_TRACE_PRELINKING(since glibc 2.4)
如果定义了此环境变量,请跟踪名称已分配给该环境变量的对象的预链接。 (使用ldd(1)获取可能被跟踪的对象的列表。)如果未识别对象名称,则将跟踪所有预链接活动。
LD_USE_LOAD_BIAS(since glibc 2.3.3)
默认情况下(即,如果未定义此变量),可执行文件和预链接的共享库将遵循其依赖的共享库的基地址,而(非预链接的)位置无关的可执行文件(PIE)和其他共享库将不遵循它们。如果LD_USE_LOAD_BIAS的值设置为1,则可执行文件和PIE都将使用基地址。如果LD_USE_LOAD_BIAS的值定义为0,则可执行文件和PIE都不支持基地址。
从glibc 2.3.3开始,在安全执行模式下将忽略此变量。
LD_VERBOSE(since glibc 2.1)
如果设置为非空字符串,则在设置了LD_TRACE_LOADED_OBJECTS环境变量的情况下,输出有关程序的符号版本信息。
LD_WARN(since glibc 2.1.3)
如果设置为非空字符串,则警告未解析的符号。
LD_PREFER_MAP_32BIT_EXEC(x86-64 only; since glibc 2.23)
根据《英特尔Silvermont软件优化指南》,对于64位应用程序,当分支的目标距离分支超过4 GB时,分支预测性能可能会受到负面影响。如果将此环境变量设置为(任何值),则动态链接器将首先尝试使用mmap(2)MAP_32BIT标志映射可执行页面,如果尝试失败,则退回到没有该标志的映射。注意:MAP_32BIT将映射到地址空间的低2 GB(不是4 GB)。
由于MAP_32BIT缩小了可用于地址空间布局随机化(ASLR)的地址范围,因此在安全执行模式下始终禁用LD_PREFER_MAP_32BIT_EXEC。

文件

/lib/ld.so
a.out动态链接器/加载器
/lib/ld-linux.so.{1,2}
ELF动态链接器/加载器
/etc/ld.so.cache
该文件包含在其中搜索共享库的目录的已编译列表以及候选共享库的有序列表。参见ldconfig(8)。
/etc/ld.so.preload
该文件包含空格分隔的ELF共享对象列表,要在程序之前加载。请参阅上面的LD_PRELOAD讨论。如果同时使用了LD_PRELOAD和/etc/ld.so.preload,则将首先预加载LD_PRELOAD指定的库。 /etc/ld.so.preload在整个系统范围内起作用,从而导致为系统上执行的所有程序预加载指定的库。 (这通常是不受欢迎的,通常仅用作紧急补救措施,例如,作为解决库配置错误的临时解决方法。)
lib*.so*
共享对象

备注

Hardware capabilities

某些共享库是使用特定于硬件的指令编译的,并非每个CPU都存在。此类对象应安装在名称定义了所需硬件功能的目录中,例如/ usr / lib / sse2 /。动态链接器根据计算机的硬件检查这些目录,并选择给定共享对象的最合适版本。硬件功能目录可以级联以结合CPU功能。支持的硬件功能名称的列表取决于CPU。当前可以识别以下名称:

Alpha
ev4,ev5,ev56,ev6,ev67
MIPS
loongson2e,loongson2f,octeon,octeon2
PowerPC
4xxmac,altivec,arch_2_05,arch_2_06,booke,cellbe,dfp,efpdouble,efpsingle,fpu,ic_snoop,mmu,notb,pa6t,power4,power5,power5 +,power6x,ppc32,ppc601,ppc64,smt,spe,upe,vsx
SPARC
刷新,muldiv,stbar,交换,ultra3,v9,v9v,v9v2
s390
dfp,eimm,esan3,etf3enh,g5,highgprs,hpage,ldisp,msa,stfle,z900,z990,z9-109,z10,zarch
x86 (32-bit only)
acpi,apic,clflush,cmov,cx8,dts,fxsr,ht,i386,i486,i586,i686,mca,mmx,mtrr,pat,pbe,pge,pn,pse36,sep,ss,sse,sse2,tm

另外参见

ld(1),ldd(1),pldd(1),sprof(1),dlopen(3),getauxval(3),elf(5),capabilities(7),rtld-audit(7),ldconfig(8) ),sln(8)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/