ld-linux.so按什么顺序搜索共享库?

ld-linux.so按什么顺序搜索共享库?,linux,linker,shared-libraries,Linux,Linker,Shared Libraries,当ld linux解析一个符号时,它会按特定顺序搜索共享库,当它找到一个具有匹配符号的共享库时,它会停止 什么决定了它在库中搜索的顺序?如果未解析的符号在主程序中或在另一个共享库中,这会有区别吗 如何在不调用ldd等外部程序的情况下以编程方式确定搜索顺序?本书建议按照gcc命令行中给出的顺序从左到右进行搜索。(我很久以前就学会了总是将-lm作为链接库列表中的最后一个库,但我也早已忘记了货物崇拜的原因。) 编辑 啊哈,谢谢你的更新。您需要自己解析ELF;在中查找“共享对象依赖项”和“DT_RPAT

当ld linux解析一个符号时,它会按特定顺序搜索共享库,当它找到一个具有匹配符号的共享库时,它会停止

什么决定了它在库中搜索的顺序?如果未解析的符号在主程序中或在另一个共享库中,这会有区别吗

如何在不调用ldd等外部程序的情况下以编程方式确定搜索顺序?

本书建议按照
gcc
命令行中给出的顺序从左到右进行搜索。(我很久以前就学会了总是将
-lm
作为链接库列表中的最后一个库,但我也早已忘记了货物崇拜的原因。)

编辑

啊哈,谢谢你的更新。您需要自己解析ELF;在中查找“共享对象依赖项”和“DT_RPATH”。(我也推荐,但它不太适用于你的问题——只是有趣的阅读。)

/usr/include/linux/elf.h
具有所有typedef

来自(如sarnold所述):

在解析符号引用时, 动态链接器检查符号 具有广度优先搜索的表。 也就是说,它首先查看符号 可执行程序表 本身,然后在 DT_需要输入(按顺序),然后 在第二级,DT_需要输入, 等等


实际上,利用ldd可以推导出链路的阶数; 如果library1位于library2之前的链接器命令行中,则ldd将在library2之前显示library1

基于此,我编写了一个简短的python脚本,以链接顺序显示共享库——它对ldd显示的所有依赖项(对于给定的可执行文件)进行广度优先搜索

这是剧本

编辑:请注意,脚本使用ldd,仍然可能有用;-)

#/usr/bin/python
导入子流程
导入系统
进口稀土
访问_so={}
ssplit=re.compile('\S+'))
详细=0
def run_ldd(sopath):
ret=[]
pop=subprocess.Popen(['ldd',sopath],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
[out,err]=pop.communicate()
对于l in out.splitlines():
toks=ssplit.findall(l)
如果len(toks)>3:
ret.append(toks[2])
回程网
def加载顺序bfs(pqueue):
而len(pqueue)!=0:
nextex=pqueue.pop(0)
如果冗长:
打印“访问”+Nextex
如果未访问Nextex,请执行以下操作:
打印Nextex
已访问的_so[nextex]=1
依赖项=运行\u ldd(nextex)
对于受抚养人中的sopath:
如果未在访问中使用sopath,请执行以下操作:
如果冗长:
打印“\t下一步”+sopath
pqueue.append(sopath)
如果len(sys.argv)==1:
打印系统argv[0]+“”“
以符号搜索顺序显示可执行文件的从属项;
对可执行文件的依赖项执行广度优先搜索
"""
系统出口(1)
加载订单bfs([sys.argv[1]])

谢谢,但我需要它来处理任意程序,即使我不知道程序编译时使用的链接行。问题是“不调用像ldd这样的外部程序”。您的程序调用一个外部程序,即ldd。
#!/usr/bin/python

import subprocess
import sys
import re

visited_so = {}
ssplit = re.compile('\S+')
verbose = 0

def run_ldd( sopath ):
        ret = []

        pop = subprocess.Popen( [ 'ldd', sopath ], stdin = subprocess.PIPE, stdout = subprocess.PIPE)
        [out, err] = pop.communicate()

        for l in out.splitlines():
            toks = ssplit.findall( l )
            if len(toks) > 3:
                ret.append( toks[2] )
        return ret

def load_order_bfs( pqueue ):
    while len(pqueue) != 0:
        nextexe = pqueue.pop(0)
        if verbose:
            print 'visit ' + nextexe

        if not nextexe in visited_so:
            print nextexe
            visited_so[ nextexe ] = 1

            dependents = run_ldd( nextexe )
            for sopath in dependents:
                    if not sopath in visited_so:
                        if verbose:
                            print '\tnext ' + sopath
                        pqueue.append( sopath )

if len( sys.argv ) == 1:
    print sys.argv[0] + """ <path>
shows dependents of executable in symbol search order;
does a breadth first search over the dependents of the executable
"""
    sys.exit(1)

load_order_bfs( [ sys.argv[1] ] )