跳至內容

漲知識了,Linux的ld和ldd一起用,可以幫我們分析運行時加載庫文件失敗的原因

更新時間
快连VPN:速度和安全性最佳的VPN服务
快连VPN:速度和安全性最佳的VPN服务

通常,開發人員和運維人員在處理軟件運行時報錯找不到依賴庫的問題時,可以使用一些工具來跟蹤啓動加載的過程,比如strace、gdb等。此外,還可以利用ld和ldd命令來幫助分析依賴庫的情況,以便更快地解決問題。這些工具可以幫助定位缺少的依賴庫,並指導用戶採取適當的措施來解決軟件運行時的問題。

這裏以分析 libmpi_usempif80.so 這個動態庫文件,依賴哪些其他動態庫,作爲問題起因。

首先介紹 ld 命令如何幫我們分析mpi_usempif80 庫依賴其他哪些庫?mpi_usempif80 庫被加載時,會從當前系統的哪些路徑下搜索這些庫?

#ld -lmpi_usempif08 –verbose

GNU ld (GNU Binutils for Ubuntu) 2.38Supported emulations: elf_x86_64 elf32_x86_64 elf_i386 elf_iamcu elf_l1om elf_k1om i386pep i386peusing internal linker script:==================================================/* Script for -z combreloc -z separate-code *//* Copyright (C) 2014-2022 Free Software Foundation, Inc. Copying and distribution of this script, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved.*/OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")OUTPUT_ARCH(i386:x86-64)ENTRY(_start)SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib");SECTIONS{PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;.interp : { *(.interp) }.note.gnu.build-id: { *(.note.gnu.build-id) }.hash : { *(.hash) }.gnu.hash : { *(.gnu.hash) }.dynsym : { *(.dynsym) }.dynstr : { *(.dynstr) }.gnu.version: { *(.gnu.version) }.gnu.version_d: { *(.gnu.version_d) }.gnu.version_r: { *(.gnu.version_r) }.rela.dyn :{*(.rela.init)*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)*(.rela.fini)*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)*(.rela.ctors)*(.rela.dtors)*(.rela.got)*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)*(.rela.ifunc)}.rela.plt :{*(.rela.plt)PROVIDE_HIDDEN (__rela_iplt_start = .);*(.rela.iplt)PROVIDE_HIDDEN (__rela_iplt_end = .);}.relr.dyn : { *(.relr.dyn) }. = ALIGN(CONSTANT (MAXPAGESIZE));.init :{KEEP (*(SORT_NONE(.init)))}.plt: { *(.plt) *(.iplt) }.plt.got: { *(.plt.got) }.plt.sec: { *(.plt.sec) }.text :{*(.text.unlikely .text.*_unlikely .text.unlikely.*)*(.text.exit .text.exit.*)*(.text.startup .text.startup.*)*(.text.hot .text.hot.*)*(SORT(.text.sorted.*))*(.text .stub .text.* .gnu.linkonce.t.*)/* .gnu.warning sections are handled specially by elf.em.*/*(.gnu.warning)}.fini :{KEEP (*(SORT_NONE(.fini)))}PROVIDE (__etext = .);PROVIDE (_etext = .);PROVIDE (etext = .);. = ALIGN(CONSTANT (MAXPAGESIZE));/* Adjust the address for the rodata segment.We want to adjust up to the same address within the page on the next page up.*/. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }.rodata1: { *(.rodata1) }.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }/* These sections are generated by the Sun/Oracle C++ compiler.*/.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }/* Adjust the address for the data segment.We want to adjust up to the same address within the page on the next page up.*/. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));/* Exception handling*/.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }.gnu_extab: ONLY_IF_RW { *(.gnu_extab) }.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }/* Thread Local Storage sections*/.tdata : { PROVIDE_HIDDEN (__tdata_start = .); *(.tdata .tdata.* .gnu.linkonce.td.*) }.tbss: { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }.preinit_array:{PROVIDE_HIDDEN (__preinit_array_start = .);KEEP (*(.preinit_array))PROVIDE_HIDDEN (__preinit_array_end = .);}.init_array:{PROVIDE_HIDDEN (__init_array_start = .);KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))PROVIDE_HIDDEN (__init_array_end = .);}.fini_array:{PROVIDE_HIDDEN (__fini_array_start = .);KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))PROVIDE_HIDDEN (__fini_array_end = .);}.ctors:{/* gcc uses crtbegin.o to find the start of the constructors, so we make sure it is first.Because this is a wildcard, it doesn't matter if the user does not actually link against crtbegin.o; the linker won't look for a file to match a wildcard.The wildcard also means that it doesn't matter which directory crtbegin.o is in.*/KEEP (*crtbegin.o(.ctors))KEEP (*crtbegin?.o(.ctors))/* We don't want to include the .ctor section from the crtend.o file until after the sorted ctors. The .ctor section from the crtend file contains the end of ctors marker and it must be last */KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))KEEP (*(SORT(.ctors.*)))KEEP (*(.ctors))}.dtors:{KEEP (*crtbegin.o(.dtors))KEEP (*crtbegin?.o(.dtors))KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))KEEP (*(SORT(.dtors.*)))KEEP (*(.dtors))}.jcr: { KEEP (*(.jcr)) }.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }.dynamic: { *(.dynamic) }.got: { *(.got) *(.igot) }. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);.got.plt: { *(.got.plt) *(.igot.plt) }.data :{*(.data .data.* .gnu.linkonce.d.*)SORT(CONSTRUCTORS)}.data1: { *(.data1) }_edata = .; PROVIDE (edata = .);. = .;__bss_start = .;.bss:{ *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) /* Align here to ensure that the .bss section occupies space up to_end.Align after .bss to ensure correct alignment even if the.bss section disappears because there are no input sections.FIXME: Why do we need it? When there is no .bss section, we do notpad the .data section.*/ . = ALIGN(. != 0 ? 64 / 8 : 1);}.lbss :{*(.dynlbss)*(.lbss .lbss.* .gnu.linkonce.lb.*)*(LARGE_COMMON)}. = ALIGN(64 / 8);. = SEGMENT_START("ldata-segment", .);.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :{*(.lrodata .lrodata.* .gnu.linkonce.lr.*)}.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :{*(.ldata .ldata.* .gnu.linkonce.l.*). = ALIGN(. != 0 ? 64 / 8 : 1);}. = ALIGN(64 / 8);_end = .; PROVIDE (end = .);. = DATA_SEGMENT_END (.);/* Stabs debugging sections.*/.stab0 : { *(.stab) }.stabstr 0 : { *(.stabstr) }.stab.excl 0 : { *(.stab.excl) }.stab.exclstr0 : { *(.stab.exclstr) }.stab.index0 : { *(.stab.index) }.stab.indexstr 0 : { *(.stab.indexstr) }.comment 0 : { *(.comment) }.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }/* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0.*//* DWARF 1.*/.debug0 : { *(.debug) }.line 0 : { *(.line) }/* GNU DWARF 1 extensions.*/.debug_srcinfo0 : { *(.debug_srcinfo) }.debug_sfnames0 : { *(.debug_sfnames) }/* DWARF 1.1 and DWARF 2.*/.debug_aranges0 : { *(.debug_aranges) }.debug_pubnames 0 : { *(.debug_pubnames) }/* DWARF 2.*/.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }.debug_abbrev 0 : { *(.debug_abbrev) }.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }.debug_frame0 : { *(.debug_frame) }.debug_str0 : { *(.debug_str) }.debug_loc0 : { *(.debug_loc) }.debug_macinfo0 : { *(.debug_macinfo) }/* SGI/MIPS DWARF 2 extensions.*/.debug_weaknames 0 : { *(.debug_weaknames) }.debug_funcnames 0 : { *(.debug_funcnames) }.debug_typenames 0 : { *(.debug_typenames) }.debug_varnames0 : { *(.debug_varnames) }/* DWARF 3.*/.debug_pubtypes 0 : { *(.debug_pubtypes) }.debug_ranges 0 : { *(.debug_ranges) }/* DWARF 5.*/.debug_addr 0 : { *(.debug_addr) }.debug_line_str 0 : { *(.debug_line_str) }.debug_loclists 0 : { *(.debug_loclists) }.debug_macro0 : { *(.debug_macro) }.debug_names0 : { *(.debug_names) }.debug_rnglists 0 : { *(.debug_rnglists) }.debug_str_offsets 0 : { *(.debug_str_offsets) }.debug_sup0 : { *(.debug_sup) }.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }}==================================================ld: mode elf_x86_64attempt to open /usr/local/lib/x86_64-linux-gnu/libmpi_usempif08.so failedattempt to open /usr/local/lib/x86_64-linux-gnu/libmpi_usempif08.a failedattempt to open /lib/x86_64-linux-gnu/libmpi_usempif08.so succeeded/lib/x86_64-linux-gnu/libmpi_usempif08.solibmpi_mpifh.so.40 needed by /lib/x86_64-linux-gnu/libmpi_usempif08.soattempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/ompi/mpi/fortran/mpif-h/.libs/libmpi_mpifh.so.40 failedattempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/ompi/.libs/libmpi_mpifh.so.40 failedattempt to open /usr/lib/x86_64-linux-gnu/openmpi/lib/libmpi_mpifh.so.40 failedattempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libmpi_mpifh.so.40 failedattempt to open /usr/local/lib/libmpi_mpifh.so.40 failedfound libmpi_mpifh.so.40 at /usr/lib/x86_64-linux-gnu/libmpi_mpifh.so.40libmpi.so.40 needed by /lib/x86_64-linux-gnu/libmpi_usempif08.soattempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/ompi/mpi/fortran/mpif-h/.libs/libmpi.so.40 failedattempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/ompi/.libs/libmpi.so.40 failedattempt to open /usr/lib/x86_64-linux-gnu/openmpi/lib/libmpi.so.40 failedattempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libmpi.so.40 failedattempt to open /usr/local/lib/libmpi.so.40 failedfound libmpi.so.40 at /usr/lib/x86_64-linux-gnu/libmpi.so.40libc.so.6 needed by /lib/x86_64-linux-gnu/libmpi_usempif08.soattempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/ompi/mpi/fortran/mpif-h/.libs/libc.so.6 failedattempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/ompi/.libs/libc.so.6 failedattempt to open /usr/lib/x86_64-linux-gnu/openmpi/lib/libc.so.6 failedattempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libc.so.6 failedattempt to open /usr/local/lib/libc.so.6 failedattempt to open /usr/lib/x86_64-linux-gnu/fortran/gfortran/libc.so.6 failedattempt to open /usr/lib/x86_64-linux-gnu/openmpi/lib/libc.so.6 failedattempt to open /usr/local/lib/x86_64-linux-gnu/libc.so.6 failedattempt to open /usr/local/lib/x86_64-linux-gnu/libc.so.6 failedattempt to open /usr/lib/x86_64-linux-gnu64/libc.so.6 failedattempt to open /usr/local/lib64/libc.so.6 failedattempt to open /lib64/libc.so.6 failedattempt to open /usr/lib64/libc.so.6 failedattempt to open /usr/local/lib/libc.so.6 failedattempt to open /lib/libc.so.6 failedattempt to open /usr/lib/libc.so.6 failedattempt to open /usr/x86_64-linux-gnu/lib64/libc.so.6 failedattempt to open /usr/x86_64-linux-gnu/lib/libc.so.6 failedattempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/ompi/mpi/fortran/mpif-h/.libs/libc.so.6 failedattempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/ompi/.libs/libc.so.6 failedattempt to open /usr/lib/x86_64-linux-gnu/openmpi/lib/libc.so.6 failedattempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libc.so.6 failedattempt to open /usr/local/lib/libc.so.6 failedfound libc.so.6 at /usr/lib/x86_64-linux-gnu/libc.so.6libopen-pal.so.40 needed by /usr/lib/x86_64-linux-gnu/libmpi_mpifh.so.40attempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/ompi/.libs/libopen-pal.so.40 failedattempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/opal/.libs/libopen-pal.so.40 failedattempt to open /usr/lib/x86_64-linux-gnu/openmpi/lib/libopen-pal.so.40 failedattempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libopen-pal.so.40 failedattempt to open /usr/local/lib/libopen-pal.so.40 failedfound libopen-pal.so.40 at /usr/lib/x86_64-linux-gnu/libopen-pal.so.40libopen-rte.so.40 needed by /usr/lib/x86_64-linux-gnu/libmpi.so.40attempt to open /usr/lib/x86_64-linux-gnu/openmpi/lib/libopen-rte.so.40 failedattempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libopen-rte.so.40 failedattempt to open /usr/local/lib/libopen-rte.so.40 failedfound libopen-rte.so.40 at /usr/lib/x86_64-linux-gnu/libopen-rte.so.40libm.so.6 needed by /usr/lib/x86_64-linux-gnu/libmpi.so.40attempt to open /usr/lib/x86_64-linux-gnu/openmpi/lib/libm.so.6 failedattempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libm.so.6 failedattempt to open /usr/local/lib/libm.so.6 failedfound libm.so.6 at /usr/lib/x86_64-linux-gnu/libm.so.6libhwloc.so.15 needed by /usr/lib/x86_64-linux-gnu/libmpi.so.40attempt to open /usr/lib/x86_64-linux-gnu/openmpi/lib/libhwloc.so.15 failedattempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libhwloc.so.15 failedattempt to open /usr/local/lib/libhwloc.so.15 failedfound libhwloc.so.15 at /usr/lib/x86_64-linux-gnu/libhwloc.so.15ld-linux-x86-64.so.2 needed by /usr/lib/x86_64-linux-gnu/libc.so.6attempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/ld-linux-x86-64.so.2 failedattempt to open /usr/local/lib/ld-linux-x86-64.so.2 failedfound ld-linux-x86-64.so.2 at /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2libevent_core-2.1.so.7 needed by /usr/lib/x86_64-linux-gnu/libopen-pal.so.40attempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libevent_core-2.1.so.7 failedattempt to open /usr/local/lib/libevent_core-2.1.so.7 failedfound libevent_core-2.1.so.7 at /usr/lib/x86_64-linux-gnu/libevent_core-2.1.so.7libevent_pthreads-2.1.so.7 needed by /usr/lib/x86_64-linux-gnu/libopen-pal.so.40attempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libevent_pthreads-2.1.so.7 failedattempt to open /usr/local/lib/libevent_pthreads-2.1.so.7 failedfound libevent_pthreads-2.1.so.7 at /usr/lib/x86_64-linux-gnu/libevent_pthreads-2.1.so.7libz.so.1 needed by /usr/lib/x86_64-linux-gnu/libopen-rte.so.40attempt to open /usr/lib/x86_64-linux-gnu/openmpi/lib/libz.so.1 failedattempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libz.so.1 failedattempt to open /usr/local/lib/libz.so.1 failedfound libz.so.1 at /usr/lib/x86_64-linux-gnu/libz.so.1libudev.so.1 needed by /usr/lib/x86_64-linux-gnu/libhwloc.so.15attempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libudev.so.1 failedattempt to open /usr/local/lib/libudev.so.1 failedfound libudev.so.1 at /usr/lib/x86_64-linux-gnu/libudev.so.1ld -lmpi_usempif08 --verbose | grep foundfound libmpi_mpifh.so.40 at /usr/lib/x86_64-linux-gnu/libmpi_mpifh.so.40found libmpi.so.40 at /usr/lib/x86_64-linux-gnu/libmpi.so.40ld: warning: cannot find entry symbol _start; not setting start addressfound libc.so.6 at /usr/lib/x86_64-linux-gnu/libc.so.6found libopen-pal.so.40 at /usr/lib/x86_64-linux-gnu/libopen-pal.so.40found libopen-rte.so.40 at /usr/lib/x86_64-linux-gnu/libopen-rte.so.40found libm.so.6 at /usr/lib/x86_64-linux-gnu/libm.so.6found libhwloc.so.15 at /usr/lib/x86_64-linux-gnu/libhwloc.so.15found ld-linux-x86-64.so.2 at /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2found libevent_core-2.1.so.7 at /usr/lib/x86_64-linux-gnu/libevent_core-2.1.so.7found libevent_pthreads-2.1.so.7 at /usr/lib/x86_64-linux-gnu/libevent_pthreads-2.1.so.7found libz.so.1 at /usr/lib/x86_64-linux-gnu/libz.so.1found libudev.so.1 at /usr/lib/x86_64-linux-gnu/libudev.so.1
登錄後複製

上面這段信息很長,有很多有價值的信息,如果你只想看關鍵部分,那麼我保留其中的關鍵內容,來一個精華版的輸出信息:

#ld -lmpi_usempif08 –verbose

GNU ld (GNU Binutils for Ubuntu) 2.38Supported emulations: elf_x86_64……using internal linker script: notice and this notice are preserved.*/OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")OUTPUT_ARCH(i386:x86-64)ENTRY(_start)# 運行時可執行文件從代碼段的 _start 位置開始運行。# 運行時需從哪些目錄找動態庫文件SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib");# 二進制文件有哪些的代碼段、數據段SECTIONS{PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;.interp : { *(.interp) }…….rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }……/* Thread Local Storage sections*/# 線程本地存儲區域.tdata : { PROVIDE_HIDDEN (__tdata_start = .); *(.tdata .tdata.* .gnu.linkonce.td.*) }.tbss: { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }.preinit_array:{PROVIDE_HIDDEN (__preinit_array_start = .);KEEP (*(.preinit_array))PROVIDE_HIDDEN (__preinit_array_end = .);}# 數據區.data :{*(.data .data.* .gnu.linkonce.d.*)SORT(CONSTRUCTORS)}.data1: { *(.data1) }_edata = .; PROVIDE (edata = .);. = .;__bss_start = .;# BSS區.bss:{ ……} ……}# 下面是本文的重點關注部分==================================================# 文件1:逐個目錄匹配是否找到被依賴的libmpi_usempif08.so 庫文件ld: mode elf_x86_64attempt to open /usr/local/lib/x86_64-linux-gnu/libmpi_usempif08.so failedattempt to open /usr/local/lib/x86_64-linux-gnu/libmpi_usempif08.a failedattempt to open /lib/x86_64-linux-gnu/libmpi_usempif08.so succeeded# 找到了 libmpi_usempif08.so 庫文件# 文件2:逐個目錄匹配是否找到被依賴的 libmpi_mpifh.so 庫文件libmpi_mpifh.so.40 needed by /lib/x86_64-linux-gnu/libmpi_usempif08.soattempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/ompi/mpi/fortran/mpif-h/.libs/libmpi_mpifh.so.40 failedattempt to open /build/openmpi-RCkqwI/openmpi-4.1.2/debian/build-gfortran/ompi/.libs/libmpi_mpifh.so.40 failedattempt to open /usr/lib/x86_64-linux-gnu/openmpi/lib/libmpi_mpifh.so.40 failedattempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libmpi_mpifh.so.40 failedattempt to open /usr/local/lib/libmpi_mpifh.so.40 failedfound libmpi_mpifh.so.40 at /usr/lib/x86_64-linux-gnu/libmpi_mpifh.so.40# 找到了 libmpi_mpifh.so 庫文件# 找 libmpi.so.40 libmpi.so.40 needed by /lib/x86_64-linux-gnu/libmpi_usempif08.so……found libmpi.so.40 at /usr/lib/x86_64-linux-gnu/libmpi.so.40# 找 libc.so.6 libc.so.6 needed by /lib/x86_64-linux-gnu/libmpi_usempif08.so……found libc.so.6 at /usr/lib/x86_64-linux-gnu/libc.so.6# 找 libopen-pal.so.40libopen-pal.so.40 needed by /usr/lib/x86_64-linux-gnu/libmpi_mpifh.so.40……found libopen-pal.so.40 at /usr/lib/x86_64-linux-gnu/libopen-pal.so.40# 找 libopen-rte.so.40libopen-rte.so.40 needed by /usr/lib/x86_64-linux-gnu/libmpi.so.40……found libopen-rte.so.40 at /usr/lib/x86_64-linux-gnu/libopen-rte.so.40# 找 libm.so.6libm.so.6 needed by /usr/lib/x86_64-linux-gnu/libmpi.so.40……found libm.so.6 at /usr/lib/x86_64-linux-gnu/libm.so.6libhwloc.so.15 needed by /usr/lib/x86_64-linux-gnu/libmpi.so.40# 找 libhwloc.so.15……略# 找 libudev.so.1libudev.so.1 needed by /usr/lib/x86_64-linux-gnu/libhwloc.so.15attempt to open /usr/lib/x86_64-linux-gnu/libfakeroot/libudev.so.1 failedattempt to open /usr/local/lib/libudev.so.1 failedfound libudev.so.1 at /usr/lib/x86_64-linux-gnu/libudev.so.1
登錄後複製

進一步,我們可以用 grep 過濾只顯示 mpi_usempif08 實際找到的庫的信息:

#ld -lmpi_usempif08 –verbose | grep found

found libmpi_mpifh.so.40 at /usr/lib/x86_64-linux-gnu/libmpi_mpifh.so.40found libmpi.so.40 at /usr/lib/x86_64-linux-gnu/libmpi.so.40ld: warning: cannot find entry symbol _start; not setting start addressfound libc.so.6 at /usr/lib/x86_64-linux-gnu/libc.so.6found libopen-pal.so.40 at /usr/lib/x86_64-linux-gnu/libopen-pal.so.40found libopen-rte.so.40 at /usr/lib/x86_64-linux-gnu/libopen-rte.so.40found libm.so.6 at /usr/lib/x86_64-linux-gnu/libm.so.6found libhwloc.so.15 at /usr/lib/x86_64-linux-gnu/libhwloc.so.15found ld-linux-x86-64.so.2 at /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2found libevent_core-2.1.so.7 at /usr/lib/x86_64-linux-gnu/libevent_core-2.1.so.7found libevent_pthreads-2.1.so.7 at /usr/lib/x86_64-linux-gnu/libevent_pthreads-2.1.so.7found libz.so.1 at /usr/lib/x86_64-linux-gnu/libz.so.1found libudev.so.1 at /usr/lib/x86_64-linux-gnu/libudev.so.1
登錄後複製

而ldd 與 ld是不同的。ldd是分析linux的運行庫的依賴關係、ld是可執行文件鏈接器常用於C/C++/Fortran等語言代碼生成可執行文件的鏈接階段。

我們看下 使用 ldd 對同一個動態庫所依賴的其他庫的分析:

#ldd/usr/lib/x86_64-linux-gnu/libmpi_usempif08.so.40.30.0

 linux-vdso.so.1 (0x00007ffd2f3fd000) libmpi_mpifh.so.40 => /usr/lib/x86_64-linux-gnu/libmpi_mpifh.so.40 (0x00007f34366bf000) libmpi.so.40 => /usr/lib/x86_64-linux-gnu/libmpi.so.40 (0x00007f3436588000) libc.so.6 => /usr/lib/x86_64-linux-gnu/libc.so.6 (0x00007f3436200000) libopen-pal.so.40 => /usr/lib/x86_64-linux-gnu/libopen-pal.so.40 (0x00007f34364d5000) libopen-rte.so.40 => /usr/lib/x86_64-linux-gnu/libopen-rte.so.40 (0x00007f3436143000) libm.so.6 => /usr/lib/x86_64-linux-gnu/libm.so.6 (0x00007f343605c000) libhwloc.so.15 => /usr/lib/x86_64-linux-gnu/libhwloc.so.15 (0x00007f3436477000) /lib64/ld-linux-x86-64.so.2 (0x00007f343677c000) libevent_core-2.1.so.7 => /usr/lib/x86_64-linux-gnu/libevent_core-2.1.so.7 (0x00007f3436442000) libevent_pthreads-2.1.so.7 => /usr/lib/x86_64-linux-gnu/libevent_pthreads-2.1.so.7 (0x00007f343643d000) libz.so.1 => /usr/lib/x86_64-linux-gnu/libz.so.1 (0x00007f3436040000) libudev.so.1 => /usr/lib/x86_64-linux-gnu/libudev.so.1 (0x00007f3436016000)
登錄後複製

這裏的順序與ld -lmpi_usempif08 –verbose | grep found 的結果是一致的。

以上就是漲知識了,Linux的ld和ldd一起用,可以幫我們分析運行時加載庫文件失敗的原因的詳細內容,更多請關注本站其它相關文章!

更新時間

發表留言

請注意,留言須先通過審核才能發佈。