天天看點

linux ldd指令學習

ldd指令用來顯示可執行程式的dependency,

sh-# ldd ./test_main

        libc.so.6 => /lib/libc.so.6 (0x40113000)

        /lib/ld-linux.so.3 (0x40022000)

sh-#

sh-# ldd -d ./test_main

        libc.so.6 => /lib/libc.so.6 (0x4011a000)

        /lib/ld-linux.so.3 (0x400f4000)

sh-#

sh-# ldd -r ./test_main

        libc.so.6 => /lib/libc.so.6 (0x401d4000)

        /lib/ld-linux.so.3 (0x400fb000)

sh-#

sh-# ldd -v ./test_main

        libc.so.6 => /lib/libc.so.6 (0x4009d000)

        /lib/ld-linux.so.3 (0x40077000)

        Version information:

        ./test_main:

                libc.so.6 (GLIBC_2.4) => /lib/libc.so.6

        /lib/libc.so.6:

                ld-linux.so.3 (GLIBC_2.4) => /lib/ld-linux.so.3

                ld-linux.so.3 (GLIBC_PRIVATE) => /lib/ld-linux.so.3

sh-#

ldd指令本身不是一個可執行程式,它隻是一個shell腳本,

sh-# which ldd

/usr/bin/ldd

sh-#

sh-# ldd /usr/bin/ldd

        not a dynamic executable

sh-#

sh-# ldd /bin/ln

        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x40061000)

        libc.so.6 => /lib/libc.so.6 (0x400cd000)

        /lib/ld-linux.so.3 (0x4003b000)

sh-#

sh-# ldd /bin/top

        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x401b6000)

        libc.so.6 => /lib/libc.so.6 (0x401c9000)

        /lib/ld-linux.so.3 (0x40013000)

sh-#

sh-# ls -lh /lib/libc.so.6

lrwxrwxrwx 1 root root 14 Nov  6 08:28 /lib/libc.so.6 -> libc-2.12.2.so

sh-# ls -lh /lib/libc-2.12.2.so

-rwxr-xr-x 1 root root 1.2M Nov  6 08:28 /lib/libc-2.12.2.so

sh-#

sh-# ls -lh /lib/ld-linux.so.3

lrwxrwxrwx 1 root root 12 Nov  6 08:28 /lib/ld-linux.so.3 -> ld-2.12.2.so

sh-# ls -lh /lib/ld-2.12.2.so

-rwxr-xr-x 1 root root 120K Nov  6 08:28 /lib/ld-2.12.2.so

sh-#

sh-# ./test_main &

31631

sh-#

<xulin>test_main

sh-#

sh-# ps aux | grep test_main

root      1304  0.0  0.1   1728   544 ?        S+   12:13   0:00 grep test_main

root      2324  0.0  0.1   1460   324 ?        S+   11:22   0:00 ./test_main

root     31631  0.0  0.1   1460   324 ?        S+   12:10   0:00 ./test_main

sh-#

ldd指令的工作原理是通過設定一些環境變量來實作的,這些環境變量包括:

LD_TRACE_LOADED_ONJECTS、LD_WARN、LD_DEBUG、LD_VERBOSE、...

比如預設情況下執行ldd指令就會設定LD_TRACE_LOADED_ONJECTS,是以就能檢視各個可執行程式的dependency。

sh-# ldd ./test_main

        libc.so.6 => /lib/libc.so.6 (0x400e7000)

        /lib/ld-linux.so.3 (0x40068000)

sh-#

可以手動設定這個環境變量,然後在執行test_main程式,

sh-# export LD_TRACE_LOADED_OBJECTS=1

sh-# ./test_main

        libc.so.6 => /lib/libc.so.6 (0x400ca000)

        /lib/ld-linux.so.3 (0x400a4000)

sh-#

使用unset指令将這個環境變量删除,即可恢複原狀了,

sh-# unset  LD_TRACE_LOADED_OBJECTS

sh-# ./test_main &

26003

sh-#

<xulin>test_main

sh-#

ldd指令工作原理其實質上是通過ld-linux.so來實作的,

ld-linux.so會先于可執行程式工作并獲得控制權。

實際上可以直接使用ld-linux.so來檢視可執行程式的共享庫依賴關系。

sh-# /lib/ld-linux.so.3 --list ./test_main

        libc.so.6 => /lib/libc.so.6 (0x40204000)

        /lib/ld-linux.so.3 (0x4005a000)

sh-#

sh-# ldd ./test_main

        libc.so.6 => /lib/libc.so.6 (0x40180000)

        /lib/ld-linux.so.3 (0x40077000)

sh-#

可以試驗将libc.so.6删除掉,再來看是否可以執行test_main這個程式。

通過确認發現,/lib/所在的檔案系統為隻讀檔案系統,是以無法進行删除操作。

sh-# rm /lib/libc.so.6

rm: cannot remove `/lib/libc.so.6': Read-only file system

sh-#

sh-# mountpoint /lib/

/lib/ is not a mountpoint

sh-#

sh-# stat -f /lib/

  File: "/lib/"

    ID: fe0000000000 Namelen: 256     Type: ooxx

Block size: 131072

Blocks: Total: 59         Free: 0          Available: 0

Inodes: Total: 1028       Free: 0

sh-#

但是基于試驗的目的,可以通過設定環境變量LD_LIBRARY_PATH來達到目的,

即将/lib/從LD_LIBRARY_PATH中删除掉,這樣在運作test_main程式時就會無法

找到動态連結庫,進而造成程式執行錯誤。

但是實際情況是:

1. sh-# echo $LD_LIBRARY_PATH中并沒有/lib目錄;

2. test_main測試程式仍然可以正确運作。

sh-# echo $LD_LIBRARY_PATH

sh-#

sh-# ./test_main &

6663

<xulin>test_main

sh-#

可以參考下面這篇了解LD_LIBRARY_PATH與動态連結庫的基本知識,

http://blog.csdn.net/boyxulin1986/article/details/11071671

關于ldd工作原理,本文先不做詳細的學習;

不過後面有機會的話,可能會進行ldd第二篇學習,屆時再對這一塊做更深入的學習。

繼續閱讀