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);
}
問題如下:
[[email protected]]$ ls
lookup_dev lookup_dev.c
[[email protected]]$ gcc -g -o lookup_dev -lpcap lookup_dev.c-L/usr/local/lib
[[email protected] pcap]$./lookup_dev
./lookup_dev: errorwhile loading shared libraries: libpcap.so.1: cannot open sharedobject file: No such file or directory
[[email protected]]$ 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)
[[email protected]]$
2解決之道
2.1原因分析
原因1:共享庫不存在或安裝錯誤。
用rpm-qa | grep -i libpcap指令檢查是否安裝了libpcap和libpcap-devel。
[[email protected]]$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中,如下:
[[email protected]]$ cat /etc/ld.so.conf
includeld.so.conf.d/*.conf
[[email protected]]$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_profile或shell裡加入以下語句即可:
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,是可以向下相容的
建一個連結就好了
[[email protected]]$sudo ln -s /usr/local/lib/libpcap.so.1/usr/lib/libpcap.so.1
[[email protected]]$whereis libpcap.so.1
libpcap.so:/usr/lib/libpcap.so.1 /usr/local/lib/libpcap.so.1/usr/local/lib/libpcap.so
[[email protected]]$ 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正确結果
[[email protected]]$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)
[[email protected]]$ 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)
[[email protected]]$ 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
[[email protected] 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為字尾的檔案都能被識别到。
[[email protected]]$ ls /etc/ld.so.conf.d/
gmp.conf mpc.conf mpfr.conf qt-x86_64.conf
[[email protected] pcap]$ ls/etc/ld.so.conf.d/
gmp.conf mpc.conf mpfr.conf pcap.conf qt-x86_64.conf
[[email protected] pcap]$ cat/etc/ld.so.conf.d/pcap.conf
/usr/local/lib/
[[email protected]]$
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)