Làm thế nào để tìm ra các thư viện thực thi tải khi chạy?


Câu trả lời:


61

Bạn có thể làm điều này với lddlệnh:

NAME
       ldd - print shared library dependencies

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

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

Thí dụ:

$ ldd /bin/ls
    linux-vdso.so.1 =>  (0x00007fff87ffe000)
    libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007ff0510c1000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007ff050eb9000)
    libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x00007ff050cb0000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff0508f0000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff0506ec000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ff0512f7000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff0504ce000)
    libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007ff0502c9000)

1
Bất kỳ ý tưởng về những gì sẽ là một macOS tương đương với điều này? Không có lldtrên darwin, nó xuất hiện, tôi cũng không thể tìm thấy nó qua homebrew.
mz2

7
Trên macOS:otool -L <path-to-binary>
Richard Viney

lưu ý rằng điều này có thể thực thi nhị phân. Vì vậy, nếu nhị phân không đáng tin cậy, có thể tốt hơn là không sử dụng ldd. Xem trang người đàn ông .
Paul Rooney

46

readelf -d $executable | grep 'NEEDED'

Có thể được sử dụng nếu bạn không thể chạy tệp thực thi, ví dụ: nếu nó được biên dịch chéo hoặc nếu bạn không tin tưởng nó:

Trong trường hợp thông thường, ldd gọi trình liên kết động tiêu chuẩn (xem ld.so (8)) với biến môi trường LD_TRACE_LOADED_OB ProjectS được đặt thành 1, khiến trình liên kết hiển thị các phụ thuộc thư viện. Tuy nhiên, hãy lưu ý rằng trong một số trường hợp, một số phiên bản của ldd có thể cố gắng lấy thông tin phụ thuộc bằng cách trực tiếp thực hiện chương trình. Vì vậy, bạn không bao giờ nên sử dụng ldd trên một tệp thực thi không đáng tin cậy, vì điều này có thể dẫn đến việc thực thi mã tùy ý.

Thí dụ:

readelf -d /bin/ls | grep 'NEEDED'

Mẫu ouptut:

 0x0000000000000001 (NEEDED)             Shared library: [libselinux.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libacl.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Lưu ý rằng các thư viện có thể phụ thuộc vào các thư viện khác, vì vậy bây giờ bạn cần tìm các phụ thuộc.

Một cách tiếp cận ngây thơ thường làm việc là:

$ locate libselinux.so.1
/lib/i386-linux-gnu/libselinux.so.1
/lib/x86_64-linux-gnu/libselinux.so.1
/mnt/debootstrap/lib/x86_64-linux-gnu/libselinux.so.1

nhưng phương pháp chính xác hơn là hiểu lddđường dẫn tìm kiếm / bộ đệm. Tôi nghĩ ldconfiglà con đường để đi.

Chọn một và lặp lại:

readelf -d /lib/x86_64-linux-gnu/libselinux.so.1 | grep 'NEEDED'

Đầu ra mẫu:

0x0000000000000001 (NEEDED)             Shared library: [libpcre.so.3]
0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]

Và như vậy.

Xem thêm:

/proc/<pid>/maps để chạy các quy trình

Được đề cập bởi Basile , điều này rất hữu ích để tìm tất cả các thư viện hiện đang được sử dụng bằng cách chạy các tệp thực thi. Ví dụ:

sudo awk '/\.so/{print $6}' /proc/1/maps | sort -u

hiển thị tất cả các phụ thuộc động hiện đang được tải của init(PID 1):

/lib/x86_64-linux-gnu/ld-2.23.so
/lib/x86_64-linux-gnu/libapparmor.so.1.4.0
/lib/x86_64-linux-gnu/libaudit.so.1.0.0
/lib/x86_64-linux-gnu/libblkid.so.1.1.0
/lib/x86_64-linux-gnu/libc-2.23.so
/lib/x86_64-linux-gnu/libcap.so.2.24
/lib/x86_64-linux-gnu/libdl-2.23.so
/lib/x86_64-linux-gnu/libkmod.so.2.3.0
/lib/x86_64-linux-gnu/libmount.so.1.1.0
/lib/x86_64-linux-gnu/libpam.so.0.83.1
/lib/x86_64-linux-gnu/libpcre.so.3.13.2
/lib/x86_64-linux-gnu/libpthread-2.23.so
/lib/x86_64-linux-gnu/librt-2.23.so
/lib/x86_64-linux-gnu/libseccomp.so.2.2.3
/lib/x86_64-linux-gnu/libselinux.so.1
/lib/x86_64-linux-gnu/libuuid.so.1.3.0

Phương pháp này cũng cho thấy các thư viện được mở bằng dlopen, được thử nghiệm với thiết lập tối thiểu này đã bị hack với sleep(1000)Ubuntu 18.04.

Xem thêm: Làm thế nào để xem các đối tượng chia sẻ hiện đang được tải trong Linux? | Siêu người dùng


1
Một phần thú vị về phương pháp readelf là nó hoạt động trên các nhị phân chéo (ví dụ: armhf trên amd64)
Ghostrider

13

ldd và lsof hiển thị các thư viện được tải trực tiếp hoặc tại một thời điểm nhất định . Họ không tính đến các thư viện được tải qua dlopen(hoặc bị loại bỏ bởidlclose ). Bạn có thể có được một hình ảnh tốt hơn về điều này bằng cách sử dụng strace, ví dụ,

strace -e trace=open myprogram

(vì dlopencuối cùng các cuộc gọi open- mặc dù tất nhiên bạn có thể có một hệ thống sử dụng các tên khác nhau để mở 64 bit ...).

Thí dụ:

strace -e trace=open date

cho tôi thấy điều này:

open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib/x86_64-linux-gnu/librt.so.1", O_RDONLY) = 3
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3
open("/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
open("/etc/localtime", O_RDONLY)        = 3
Wed Apr 12 04:56:32 EDT 2017

từ đó người ta có thể grep tên ".so" để chỉ nhìn thấy các đối tượng được chia sẻ.


3
Một cải tiến:strace -e trace=open,openat myprogram
Cyker

Phương pháp tốt đẹp. /proc/<pid>/mapscũng hiển thị dlopenlibs btw: unix.stackexchange.com/questions/120015/ ltrace -S Đầu ra thậm chí còn tuyệt hơn khi nó hiển thị cả tòa nhà và các cuộc gọi thư viện như dlopen: unix.stackexchange.com/questions/226524/ của
Ciro Santilli 改造

7

lsof cũng có thể cho bạn thấy những thư viện nào đang được sử dụng cho một quy trình cụ thể.

I E

$ pidof nginx
6920 6919

$ lsof -p 6919|grep mem
nginx   6919 root  mem    REG               0,64    65960     43 /lib64/libnss_files-2.12.so
nginx   6919 root  mem    REG               0,64    19536     36 /lib64/libdl-2.12.so
nginx   6919 root  mem    REG               0,64    10312   1875 /lib64/libfreebl3.so
nginx   6919 root  mem    REG               0,64  1923352     38 /lib64/libc-2.12.so
nginx   6919 root  mem    REG               0,64    88600   1034 /lib64/libz.so.1.2.3
nginx   6919 root  mem    REG               0,64  1967392   1927 /usr/lib64/libcrypto.so.1.0.1e
nginx   6919 root  mem    REG               0,64   183080   1898 /lib64/libpcre.so.0.0.1
nginx   6919 root  mem    REG               0,64    40400   1217 /lib64/libcrypt-2.12.so
nginx   6919 root  mem    REG               0,64   142688     77 /lib64/libpthread-2.12.so
nginx   6919 root  mem    REG               0,64   154664     31 /lib64/ld-2.12.so

2

Đối với quy trình pid 1234, bạn cũng có thể đọc /proc/1234/mapstệp giả (văn bản) (đọc Proc (5) ...) hoặc sử dụng pmap (1)

Điều này mang lại không gian địa chỉ ảo của quá trình đó, do đó các tệp (bao gồm các thư viện được chia sẻ, thậm chí là dlopen (3) -eded) được ánh xạ bộ nhớ

(tất nhiên, sử dụng ps auxhoặc pgrep (1) để tìm các quy trình chạy một số chương trình nhất định)


1

Đối với truy vấn hàng loạt:

  1. tạo một tập lệnh nhỏ ( useslib) và đưa vào PATH (chỉ định một đường dẫn đầy đủ trong lệnh bên dưới)

    #! /bin/bash
    ldd $1 | grep -q $2
    exit $?
    
  2. Sử dụng nó trong một findlệnh, ví dụ:

    find /usr/bin/ -executable -type f -exec useslib {} libgtk-x11-2.0 \; -print
    

(libgtk-x11-2.0 dường như là lib gtk2)


0

Nó có thể sử dụng pmap.

Ví dụ: bắt đầu một quy trình: $ watch date

Nhận pid: $ ps -ef | grep watch

Hiển thị bản đồ bộ nhớ: $ pmap <pid>

Hiển thị với đường dẫn đầy đủ: $ pmap <pid> -p

$ pmap 72770
72770:   watch date
00005613a32c9000     20K r-x-- watch
00005613a34cd000      4K r---- watch
00005613a34ce000      4K rw--- watch
00005613a4f6a000    264K rw---   [ anon ]
00007f2f3a7d5000 204616K r---- locale-archive
00007f2f46fa7000   1748K r-x-- libc-2.27.so
00007f2f4715c000   2048K ----- libc-2.27.so
00007f2f4735c000     16K r---- libc-2.27.so
00007f2f47360000      8K rw--- libc-2.27.so
00007f2f47362000     16K rw---   [ anon ]
00007f2f47366000     12K r-x-- libdl-2.27.so
00007f2f47369000   2044K ----- libdl-2.27.so
00007f2f47568000      4K r---- libdl-2.27.so
00007f2f47569000      4K rw--- libdl-2.27.so
00007f2f4756a000    160K r-x-- libtinfo.so.6.1
00007f2f47592000   2048K ----- libtinfo.so.6.1
00007f2f47792000     16K r---- libtinfo.so.6.1
00007f2f47796000      4K rw--- libtinfo.so.6.1
00007f2f47797000    232K r-x-- libncursesw.so.6.1
00007f2f477d1000   2048K ----- libncursesw.so.6.1
00007f2f479d1000      4K r---- libncursesw.so.6.1
00007f2f479d2000      4K rw--- libncursesw.so.6.1
00007f2f479d3000    148K r-x-- ld-2.27.so
00007f2f47bdb000     20K rw---   [ anon ]
00007f2f47bf1000     28K r--s- gconv-modules.cache
00007f2f47bf8000      4K r---- ld-2.27.so
00007f2f47bf9000      4K rw--- ld-2.27.so
00007f2f47bfa000      4K rw---   [ anon ]
00007ffd39404000    136K rw---   [ stack ]
00007ffd3959b000     12K r----   [ anon ]
00007ffd3959e000      8K r-x--   [ anon ]
ffffffffff600000      4K r-x--   [ anon ]
 total           215692K
$ pmap 72770 -p
72770:   watch date
00005613a32c9000     20K r-x-- /usr/bin/watch
00005613a34cd000      4K r---- /usr/bin/watch
00005613a34ce000      4K rw--- /usr/bin/watch
00005613a4f6a000    264K rw---   [ anon ]
00007f2f3a7d5000 204616K r---- /usr/lib/locale/locale-archive
00007f2f46fa7000   1748K r-x-- /usr/lib64/libc-2.27.so
00007f2f4715c000   2048K ----- /usr/lib64/libc-2.27.so
00007f2f4735c000     16K r---- /usr/lib64/libc-2.27.so
00007f2f47360000      8K rw--- /usr/lib64/libc-2.27.so
00007f2f47362000     16K rw---   [ anon ]
00007f2f47366000     12K r-x-- /usr/lib64/libdl-2.27.so
00007f2f47369000   2044K ----- /usr/lib64/libdl-2.27.so
00007f2f47568000      4K r---- /usr/lib64/libdl-2.27.so
00007f2f47569000      4K rw--- /usr/lib64/libdl-2.27.so
00007f2f4756a000    160K r-x-- /usr/lib64/libtinfo.so.6.1
00007f2f47592000   2048K ----- /usr/lib64/libtinfo.so.6.1
00007f2f47792000     16K r---- /usr/lib64/libtinfo.so.6.1
00007f2f47796000      4K rw--- /usr/lib64/libtinfo.so.6.1
00007f2f47797000    232K r-x-- /usr/lib64/libncursesw.so.6.1
00007f2f477d1000   2048K ----- /usr/lib64/libncursesw.so.6.1
00007f2f479d1000      4K r---- /usr/lib64/libncursesw.so.6.1
00007f2f479d2000      4K rw--- /usr/lib64/libncursesw.so.6.1
00007f2f479d3000    148K r-x-- /usr/lib64/ld-2.27.so
00007f2f47bdb000     20K rw---   [ anon ]
00007f2f47bf1000     28K r--s- /usr/lib64/gconv/gconv-modules.cache
00007f2f47bf8000      4K r---- /usr/lib64/ld-2.27.so
00007f2f47bf9000      4K rw--- /usr/lib64/ld-2.27.so
00007f2f47bfa000      4K rw---   [ anon ]
00007ffd39404000    136K rw---   [ stack ]
00007ffd3959b000     12K r----   [ anon ]
00007ffd3959e000      8K r-x--   [ anon ]
ffffffffff600000      4K r-x--   [ anon ]
 total           215692K
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.