涨知识了,Linux的ld和ldd一起用,可以帮我们分析运行时加载库文件失败的原因

涨知识了,linux的ld和ldd一起用,可以帮我们分析运行时加载库文件失败的原因

通常,开发人员和运维人员在处理软件运行时报错找不到依赖库的问题时,可以使用一些工具来跟踪启动加载的过程,比如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一起用,可以帮我们分析运行时加载库文件失败的原因的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2290590.html

(0)
上一篇 2025年2月28日 00:24:32
下一篇 2025年2月28日 00:24:48

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • Stremio字幕不工作;加载字幕时出错

    字幕在你的windows pc上不能在stremio上运行吗?一些stremio用户报告说,视频中没有显示字幕。许多用户报告说遇到了一条错误消息,上面写着“加载字幕时出错”。以下是与此错误一起显示的完整错误消息: 加载字幕时出错加载字幕失败…

    2025年2月27日
    200
  • 如何在Linux中导出Ld_Library_Path

    在Linux系统中,快速查看环境变量可以帮助用户更好地理解系统的运作方式。这些变量让您能够有效地配置和优化系统。特定变量如”LD_LIBRARY_PATH”存储了关于共享库在系统中位置的信息,这对于程序的正确运行至关…

    2025年2月27日
    200
  • 简述Python的重新加载

    为防止两个模块互相导入的问题,python默认所有的模块都只导入一次,如果需要重新导入模块, Python2.7可以直接用reload(),Python3可以用下面几种方法: 方法一:基本方法 from imp import reload …

    编程技术 2025年2月27日
    200
  • Apache加载PHP模块加载不上

    apache加载php模块加载不上的解决方法是: 1、执行命令vi /etc/selinux/config SELINUX=enforcing 登录后复制登录后复制 修改为: 立即学习“PHP免费学习笔记(深入)”; SELINUX=dis…

    2025年2月25日
    200
  • 如何处理Vue开发中遇到的分页加载数据问题

    如何处理vue开发中遇到的分页加载数据问题 在现代Web应用程序中,数据的分页加载是一个常见的需求。特别是在Vue开发中,我们经常会遇到需要加载大量数据并按页进行展示的场景。然而,分页加载数据并不是一件简单的事情,特别是当数据量巨大或涉及到…

    编程技术 2025年2月23日
    200
  • 车厘子冷冻完解冻还能吃吗

    车厘子是生活中比较常见的一种水果,它含有多种营养成分,适量食用对身体有一定的好处,很多人都喜欢吃车厘子。车厘子冷冻后解冻了,如果没有变质,一般还是可以吃的,如果已经变质坏掉了,就不建议吃了。 车厘子冷冻完解冻还能吃吗 视情况而定。 车厘子是…

    2025年2月22日
    868.9K00
  • 自制的黄桃罐头可以放冰箱冷冻吗

    黄桃的吃法比较多,很多人都会用黄桃做罐头吃。黄桃罐头是比较受欢迎的一种罐头,它吃起来清甜可口,生津止渴,很多人都会自己在家做黄桃罐头。自制的黄桃罐头不建议放冰箱冷冻,直接放冰箱冷藏保存就可以了。 自制的黄桃罐头可以放冰箱冷冻吗 可以但不建议…

    2025年2月22日
    843.8K00
  • 解决SSIS的脚本任务编辑器加载超慢问题

    问题 问题 ,香港服务器,香港服务器,香港虚拟主机

    数据库 2025年2月22日
    200
  • 冻榴莲解冻后有水成糊糊能吃吗

    市面上的榴莲除了新鲜榴莲,还有冻榴莲,这个也是比较受欢迎的,它是将新鲜榴莲冷冻了的,这种更容易保鲜,防止变质坏掉。冻榴莲是需要解冻再吃的,有些解冻后有水成糊糊状,如果没有异味,没有变质,还是可以吃的。 冻榴莲解冻后有水成糊糊能吃吗 没变质的…

    2025年2月21日
    386.2K00
  • 冻榴莲用空气炸锅烤多少度多长时间

    榴莲一般都是吃新鲜的,不过市面上也有冻榴莲卖,这种也是很不错的,吃起来营养丰富,对身体有一定的好处。冷冻榴莲可以用空气炸锅烤着吃,一般设置两百度烤十五到二十分钟就可以了。 冻榴莲用空气炸锅烤多少度多长时间 一般情况下,200℃烤15-20分…

    2025年2月21日
    247.8K00

发表回复

登录后才能评论