ld错误 error while loading shared libraries 处理以及相关内容

1问题描述

在学习有关libpcap的内容时,参考了文件《Programmingwith pcap》(链接:http://www.tcpdump.org/pcap.html),其中刚开始就遇到了问题,程序如下:

#include <stdio.h>
#include <pcap.h>

int main(int argc, char *argv[])
{
       char *dev, errbuf[PCAP_ERRBUF_SIZE];

        dev = pcap_lookupdev(errbuf);
   if (dev == NULL) {
              fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
          return(2);
      }
       printf("Device: %s\n", dev);
    return(0);
}

问题如下:

[zhaihf@localhostpcap]$ ls
lookup_dev  lookup_dev.c
[zhaihf@localhostpcap]$ gcc -g -o lookup_dev -lpcap lookup_dev.c-L/usr/local/lib
[zhaihf@localhost pcap]$./lookup_dev
./lookup_dev: errorwhile loading shared libraries: libpcap.so.1: cannot open sharedobject file: No such file or directory
[zhaihf@localhostpcap]$ ldd lookup_dev
       linux-vdso.so.1 =>  (0x00007fff66eea000)
       libpcap.so.1 => notfound
        libc.so.6=> /lib64/libc.so.6 (0x00000037e2800000)
       /lib64/ld-linux-x86-64.so.2 (0x00000037e2400000)
[zhaihf@localhostpcap]$

2解决之道

2.1原因分析

原因1:共享库不存在或安装错误。

rpm-qa  | grep -i libpcap命令检查是否安装了libpcaplibpcap-devel

[zhaihf@localhostpcap]$rpm -qa  | grep -ilibpcap
libpcap-0.9.4-15.el5



原因2:共享库已经正确安装,但程序按照默认共享库路径找不到该共享库文件。

加载共享库因路径出错,肯定与ld有关,查看连接器ld的内容。

连接器使用下面的搜索路径来定位需要的共享库:
1.
所有由'-rpath-link'选项指定的搜索路径.
2.
所有由'-rpath'指定的搜索路径.'-rpath''-rpath_link'的不同之处在于,'-rpath'指定的路径被包含在可执行文件中,并在运行时使用,'-rpath-link'选项仅仅在连接时起作用.它只用于本地连接器.
3.
在一个ELF系统中,如果'-rpath''rpath-link'选项没有被使用,会搜索环境变量'LD_RUN_PATH'的内容.它也只对本地连接器起作用.
4.
SunOS,'-rpath'选项不使用,只搜索所有由'-L'指定的目录.
5.
对于一个本地连接器,环境变量'LD_LIBRARY_PATH'的内容被搜索.
6.
对于一个本地ELF连接器,共享库中的`DT_RUNPATH'`DT_RPATH'操作符会被需要它的共享库搜索.如果'DT_RUNPATH'存在了,'DT_RPATH'就会被忽略.
7.
缺省目录,常规的,'/lib''/usr/lib'.
8.
对于ELF系统上的本地连接器,如果文件'/etc/ld.so.conf'存在,这个文件中有的目录会被搜索.

如果需要的共享库没有被找到,那连接器会发出一条警告信息,并继续执行连接.

共享库路径设置问题,如下:

1)
如果共享库文件安装到了/lib/usr/lib目录下,那么需执行一下ldconfig命令

ldconfig
命令的用途,主要是在默认搜寻目录(/lib/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件.缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表.

2)
如果共享库文件安装到了/usr/local/lib(很多开源的共享库都会安装到该目录下)或其它"/lib/usr/lib"目录下,那么在执行ldconfig命令前,还要把新共享库目录加入到共享库配置文件/etc/ld.so.conf,如下:

[zhaihf@localhostpcap]$ cat /etc/ld.so.conf
includeld.so.conf.d/*.conf

[zhaihf@localhostpcap]$echo "/usr/local/lib" >> /etc/ld.so.conf

3)
如果共享库文件安装到了其它"/lib/usr/lib"目录下但是又不想在/etc/ld.so.conf中加路径(或者是没有权限加路径).那可以export一个全局变量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找共享库.

LD_LIBRARY_PATH
的意思是告诉loader在哪些目录中可以找到共享库.可以设置多个搜索目录,这些目录之间用冒号分隔开.比如安装了一个mysql/usr/local/mysql目录下,其中有一大堆库文件在/usr/local/mysql/lib下面,则可以在.bashrc.bash_profileshell里加入以下语句即可:

exportLD_LIBRARY_PATH=/usr/local/mysql/lib:$LD_LIBRARY_PATH

一般来讲这只是一种临时的解决方案,在没有权限或临时需要的时候使用.

4
)如果程序需要的库文件比系统目前存在的文件版本低,可以做一个链接
比如:
errorwhile loading shared libraries: libncurses.so.4: cannot openshared
object file: No such file or directory

ls/usr/lib/libncu*
/usr/lib/libncurses.a  /usr/lib/libncurses.so.5
/usr/lib/libncurses.so  /usr/lib/libncurses.so.5.3

可见虽然没有libncurses.so.4,但有libncurses.so.5,是可以向下兼容的
建一个链接就好了

[zhaihf@localhostpcap]$sudo ln -s /usr/local/lib/libpcap.so.1/usr/lib/libpcap.so.1

[zhaihf@localhostpcap]$whereis libpcap.so.1
libpcap.so:/usr/lib/libpcap.so.1 /usr/local/lib/libpcap.so.1/usr/local/lib/libpcap.so

[zhaihf@localhostpcap]$ ls -l /usr/lib/libpcap.so.1
lrwxrwxrwx 1 root root 27 Nov12 18:04 /usr/lib/libpcap.so.1 -> /usr/local/lib/libpcap.so.1

2.2正确结果

[zhaihf@localhostpcap]$ldd lookup_dev
       linux-vdso.so.1 =>  (0x00007fff499ff000)
       libpcap.so.1 =>/usr/local/lib/libpcap.so.1 (0x00007fd8d3292000)
       libc.so.6 => /lib64/libc.so.6 (0x00000037e2800000)
       /lib64/ld-linux-x86-64.so.2 (0x00000037e2400000)
[zhaihf@localhostpcap]$ sudo ldd lookup_dev
       linux-vdso.so.1 =>  (0x00007fff223ff000)
       libpcap.so.1 => /usr/local/lib/libpcap.so.1(0x00007f7e6671b000)
       libc.so.6 => /lib64/libc.so.6 (0x00000037e2800000)
       /lib64/ld-linux-x86-64.so.2 (0x00000037e2400000)

[zhaihf@localhostpcap]$ readelf -d lookup_dev

Dynamic sectionat offset 0x900 contains 21 entries:
  Tag       Type                        Name/Value
 0x0000000000000001 (NEEDED)            Shared library:[libpcap.so.1]
 0x0000000000000001(NEEDED)            Shared library:[libc.so.6]
 0x000000000000000c (INIT)              0x400520
 0x000000000000000d (FINI)              0x4007c8
 0x000000006ffffef5 (GNU_HASH)          0x400240
 0x0000000000000005 (STRTAB)            0x4003b8
 0x0000000000000006 (SYMTAB)            0x400280
 0x000000000000000a (STRSZ)             155 (bytes)
 0x000000000000000b (SYMENT)            24 (bytes)
 0x0000000000000015 (DEBUG)             0x0
 0x0000000000000003 (PLTGOT)            0x600aa8
 0x0000000000000002 (PLTRELSZ)          96 (bytes)
 0x0000000000000014 (PLTREL)            RELA
 0x0000000000000017 (JMPREL)            0x4004c0
 0x0000000000000007 (RELA)              0x400490
 0x0000000000000008 (RELASZ)            48 (bytes)
 0x0000000000000009 (RELAENT)           24 (bytes)
 0x000000006ffffffe (VERNEED)           0x400470
 0x000000006fffffff (VERNEEDNUM)        1
 0x000000006ffffff0 (VERSYM)            0x400454
 0x0000000000000000 (NULL)              0x0
[zhaihf@localhost pcap]$

3相关内容

3相关内容

3.1LD_LIBRARY_PATH

把动态链接库的安装路径(如/usr/local/lib)放到变量LD_LIBRARY_PATH里。

用命令export

export LD_LIBRARY_PATH=/usr/local/lib

这只是临时设置变量LD_LIBRARY_PATH,下次开机,设置将不复存在;可以在~/.bashrc或者~/.bash_profile中加入export语句,

前者在每次登陆和每次打开shell都读取一次,

后者只在登陆时读取一次。

可采用如下语句来使设置生效:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

修改完后,记得关掉当前终端并重新打开一个新的终端,从而使上面的配置生效。



3.2 ld.so.conf

链接器ld默认的目录是/lib/usr/lib,如果放在其他路径也可以,需要让ld知道库文件在哪里。

1>编辑/etc/ld.so.conf文件,在新的一行中加入库文件所在目录;

运行ldconfig,以更新/etc/ld.so.cache文件;

2>/etc/ld.so.conf.d/目录下新建任何以.conf为后缀的文件,在该文件中加入库文件所在的目录;

运行ldconfig,以更新/etc/ld.so.cache文件;

第二种办法更为方便,对于原系统的改动最小。因为/etc/ld.so.conf文件的内容是include/etc/ld.so.conf.d/*.conf,所以,在/etc/ld.so.conf.d/目录下加入的任何以.conf为后缀的文件都能被识别到。

[zhaihf@localhostpcap]$ ls /etc/ld.so.conf.d/
gmp.conf  mpc.conf mpfr.conf  qt-x86_64.conf
[zhaihf@localhost pcap]$ ls/etc/ld.so.conf.d/
gmp.conf  mpc.conf  mpfr.conf pcap.conf  qt-x86_64.conf
[zhaihf@localhost pcap]$ cat/etc/ld.so.conf.d/pcap.conf
/usr/local/lib/
[zhaihf@localhostpcap]$



ld.so.cache的更新是递增式的,就像PATH系统环境变量一样,不是从头重新建立,而是向上累加。

除非重新开机,才是从零开始建立ld.so.cache文件。



3.3命令

NAME
      /sbin/ldconfig - configure dynamic linker runtime bindings

SYNOPSIS
      /sbin/ldconfig [ -nNvXV ] [ -f conf ] [ -C cache ] [ -r root ]directory ...
       /sbin/ldconfig-l [ -v ] library ...
      /sbin/ldconfig -p

DESCRIPTION
      ldconfig  creates  the  necessary links and cache tothe most recent shared libraries found inthedirectories
       specified on thecommand line, in  the  file  /etc/ld.so.conf, and  in  the  trusted  directories  (/lib and
       /usr/lib
).  The  cache  is used by the run-time linker, ld.so orld-linux.so.  ldconfig checks the header and
      filenames of the libraries it encounters when determining whichversions should have their links updated.

       ldconfigwill attempt to deduce the type of ELF libs (ie. libc5 orlibc6/glibc) based on what C libs, if  any,
      the  library  was  linked  against.  Therefore,  when making dynamic libraries, it is wise toexplicitly link
       against libc(use -lc).

       Someexisting libs do not contain enough information to allow thededuction  of  their  type.  Therefore, the
       /etc/ld.so.conf file  format  allows  the specification of an expectedtype.  This is only used for those ELF
      libs which we can not work out. The format is "dirname=TYPE",where TYPE can be libc4, libc5, or libc6.  (This
      syntax  also  works  on  the command line.) Spaces are not allowed.  Also see the -p option.  ldconfigshould
       normally be run by thesuperuser as it may require write permission on some root owneddirectories and  files.

OPTIONS
      -v     Verbose mode.  Print current versionnumber, the name of each directory as it is scanned, and anylinks
             that are created.  Overrides quiet mode.

       -n    Only process directories specified on the command line.  Don’tprocess the  trusted  directories  (/lib
             and /usr/lib) nor those specified in /etc/ld.so.conf.  Implies-N.

       -N    Don’t rebuild the cache.  Unless -X is also specified, linksare still updated.

       -X    Don’t update links.  Unless -N is also specified, the cache isstill rebuilt.

       -fconf
             Use conf instead of /etc/ld.so.conf.

       -Ccache
             Use cache instead of /etc/ld.so.cache.

       -rroot
             Change to and use root as the root directory.

       -l    Library mode. Manually link individual libraries. Intended for use byexperts only.

       -p    Print the lists of directories and candidate libraries stored in thecurrent cache.

FILES
      /lib/ld.so         run-time linker/loader
      /etc/ld.so.conf     File  containing a  list of colon, space, tab, newline, or comma-separateddirectories in
                          which to search for libraries.
      /etc/ld.so.cache    File containing an ordered list of  libraries  found  in  the  directories specified  in
                          /etc/ld.so.conf.



NAME
      ldd - print shared library dependencies

SYNOPSIS
      ldd [OPTION]...  FILE...

DESCRIPTION
      ldd prints the shared libraries required byeach program or shared library specified on the command line.

OPTIONS
      --version
             Print the version number of ldd.

       -v--verbose
             Print all information, including e.g. symbol versioning information.

       -u--unused
             Print unused direct dependencies.

       -d--data-relocs
             Perform relocations and report any missing objects (ELFonly).

       -r--function-relocs
             Perform  relocations  for  both data objects andfunctions, and report any missing objects or functions
             (ELF only).

       --helpUsage information.

NOTES
      The standard version of ldd comes with glibc2. Libc5 came with anolder version, still present  on  some  sys-
      tems. The long options are not supported by the libc5 version. On the other hand, the glibc2 version does not
      support -V and only has the equivalent --version.

       Thelibc5 version of this program will use the name of a library given onthe command line as-is when it  con-
      tains a ’/’; otherwise it searches for the library in thestandard locations. To run it on a shared library in
      the current directory, prefix the name with "./".

BUGS
      ldd does not work on a.out shared libraries.

       ldddoes not work with some extremely old a.out programs which were builtbefore ldd support was added to  the
      compiler releases.  If you use ldd on one of these programs, theprogram will attempt to run with argc = 0 and
      the results will be unpredictable.

SEE ALSO
      ld.so(8), ldconfig(8)



NAME
      ld.so, ld-linux.so* - dynamic linker/loader

DESCRIPTION
      The  programs ld.so and ld-linux.so* find and load the sharedlibraries
       needed by aprogram, prepare the program to run, and then run it.

       Linuxbinaries require dynamic linking (linking at run time) unlessthe
       -static option was givento ld during compilation.

       The program  ld.so handles a.out binaries, a format used long ago;ld-
       linux.so* handles ELF(/lib/ld-linux.so.1 for libc5, /lib/ld-linux.so.2
      for  glibc2),  which everybody has been using for yearsnow.  Otherwise
       bothhave the same behaviour, and use the same support files  and pro-
       grams ldd(1),ldconfig(8) and /etc/ld.so.conf.

       The shared libraries needed by the program are searched for invarious
       places:

       o     (ELF only) Using the DT_RPATH dynamic section attribute  of the
             binary  if present and DT_RUNPATH attribute does not exist. Use
             of DT_RPATH is deprecated.

       o     Using the environment variable LD_LIBRARY_PATH.  Except if  the
             executable  is  a set-user-ID/set-group-ID binary, in whichcase
             it is ignored.

       o     (ELF only) Using the DT_RUNPATH dynamic section attribute ofthe
             binary if present.

       o     From  the  cache file /etc/ld.so.cache which contains acompiled
             list of candidate libraries previously found  in  the augmented
             library  path.  If, however, the binary was linked with -znode-
             flib linker option, libraries in the default library  paths are
             skipped.

       o     In  the default path /lib, and then /usr/lib.  If thebinary was
             linked with -z nodeflib linker option, this step is skipped.

SYNOPSIS
      The dynamic linker can be run either indirectly  through running  some
      dynamically  linked  program  or library (in whichcase no command line
       optionsto the dynamic linker can be passed and, in the ELF  case, the
       dynamic linker which isstored in the .interp section of the program is
      executed) or directly by running:

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

COMMAND LINEOPTIONS
       --list List alldependencies and how they are resolved.

       --verify
             Verify that program  is  dynamically  linked and  this  dynamic
             linker can handle it.

       --library-pathPATH
             Override   LD_LIBRARY_PATH  environment variable  setting  (see
             below).

       --ignore-rpathLIST
             Ignore RPATH and RUNPATH information in object  names  in LIST.
             This  option  has  been  supported by glibc2 forabout one hour.
             Then it was renamed into:

       --inhibit-rpathLIST

ENVIRONMENT
      There are four important environment variables.

       LD_LIBRARY_PATH
             A colon-separated list of directories in which to search forELF
             libraries  at  execution-time.   Similar to thePATH environment
             variable.

       LD_PRELOAD
             A whitespace-separated list of additional,  user-specified, ELF
             shared  libraries  to  be loaded before all others. This can be
             used  to  selectively  override  functions  in   other   shared
             libraries.   For  set-user-ID/set-group-ID  ELF binaries,  only
             libraries in the standard search directories that are also set-
             user-ID will be loaded.

       LD_BIND_NOW
             (libc5;  glibc  since  2.1.1) If set to non-emptystring, causes
             the dynamic linker to resolve all  symbols  at program  startup
             instead  of  deferring  function call resolval to thepoint when
             they are first referenced.  This is useful when using  a debug-
             ger.

      LD_TRACE_LOADED_OBJECTS
             (ELF  only)  If  set  to non-empty string, causesthe program to
             list its dynamic library dependencies,  as  if  run by  ldd(1),
             instead of running normally.

       Thenthere are lots of more or less obscure variables, many obsoleteor
       only for internal use.

       LD_WARN
             (ELF only)(glibc since 2.1.3) If set to non-empty  string, warn
             about unresolved symbols.

       LD_NOWARN
             (a.out only)(libc5) Suppress warnings about a.out librarieswith
             incompatible minor version numbers.

       LD_BIND_NOT
             (glibc since 2.1.95) Do not update the GOT (global offsettable)
             and PLT (procedure linkage table) after resolving a symbol.

       LD_DEBUG
             (glibc since 2.1) Output verbose debugging information aboutthe
             dynamic linker.  If set to all prints all debugging information
             it  has,  if set to help prints a help message about whichcate-
             gories can be specified in this environment variable.

       LD_DEBUG_OUTPUT
             (glibc since 2.1) File where LD_DEBUG output should be fedinto,
             default is standard output.  LD_DEBUG_OUTPUT is ignored forset-
             user-ID/set-group-ID binaries.

       LD_VERBOSE
             (glibc since 2.1) If set to non-empty string, output symbolver-
             sioning  information  about  the program if queryinginformation
             about the program (ie. either LD_TRACE_LOADED_OBJECTS  has been
             set,  or  --list  or  --verify  options have  been given to the
             dynamic linker).

       LD_PROFILE
             (glibc since 2.1) Shared object to be profiled.

      LD_PROFILE_OUTPUT
             (glibc since 2.1) File where LD_PROFILE output should bestored,
             default  is  standard  output.  LD_PROFILE_OUTPUTis ignored for
             set-user-ID/set-group-ID binaries.

      LD_AOUT_LIBRARY_PATH
             (libc5) Version of LD_LIBRARY_PATH for a.out binaries only. Old
             versions of ld-linux.so.1 also supported LD_ELF_LIBRARY_PATH.

       LD_AOUT_PRELOAD
             (libc5) Version of LD_PRELOAD for a.out binaries only.  Oldver-
             sions of ld-linux.so.1 also supported LD_ELF_PRELOAD.

       LD_SHOW_AUXV
             (glibc since 2.1) Show auxiliary array passed up from  the ker-
             nel.

       LD_HWCAP_MASK
             (glibc since 2.1) Mask for hardware capabilities.

       LD_ORIGIN_PATH
             (glibc  since  2.1) Path where the binary is found (fornon-set-
             user-ID programs).

       LD_DYNAMIC_WEAK
             (glibc  since  2.1.91)  Allow  weak symbols  to  be  overridden
             (reverting to old glibc behaviour).

       LD_KEEPDIR
             (a.out  only)(libc5)  Don’t ignore the directory in thenames of
             a.out libraries to be loaded.  Use of this  option is  strongly
             discouraged.

       LDD_ARGV0
             (libc5) argv[0] to be used by ldd(1) when none is present.

FILES
      /lib/ld.so
             a.out dynamic linker/loader
      /lib/ld-linux.so.{1,2}
             ELF dynamic linker/loader
      /etc/ld.so.cache
             File  containing  a  compiled  list  of directories in which to
             search for libraries and an ordered list of candidatelibraries.
      /etc/ld.so.preload
             File  containing  a  whitespace  separated list  of  ELF shared
             libraries to be loaded before the program.
      lib*.so*
             shared libraries

NOTES
      The ld.so functionality is available  for  executables compiled  using
       libc version  4.4.3  or greater.  ELF functionality isavailable since
       Linux 1.1.52and libc5.

SEE ALSO
      ldd(1), ldconfig(8)



你可能感兴趣的:(elf,libpcap,ldd,ld,idconfig)