代码之家  ›  专栏  ›  技术社区  ›  atomice

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

  •  9
  • atomice  · 技术社区  · 14 年前

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

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

    在不调用诸如ldd之类的外部程序的情况下,如何通过编程确定搜索顺序?

    3 回复  |  直到 9 年前
        1
  •  9
  •   Mark    14 年前

    http://www.muppetlabs.com/~breadbox/software/ELF.txt (如萨诺尔所述):

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

        2
  •  3
  •   sarnold    14 年前

    这本书 http://www.network-theory.co.uk/docs/gccintro/gccintro_18.html 建议从左到右的顺序 gcc 命令行。(我很久以前就学会了 -lm 作为图书馆名单上最后一个链接的图书馆,但我也早已忘记了货运邪教的原因。)

    编辑

    啊哈,谢谢你的更新。您将需要自己解析ELF;在 http://www.muppetlabs.com/~breadbox/software/ELF.txt . (我也推荐 http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html 但它不太适用于你的问题——只是有趣的阅读。)

    /usr/include/linux/elf.h 包含所有typedef。

        3
  •  -1
  •   MichaelMoser    9 年前

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

    基于此,我编写了一个简短的python脚本,该脚本按链接顺序显示共享库——它对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] ] )