Làm cách nào để hiển thị tất cả các thư viện dùng chung được sử dụng bởi các tệp thực thi trong Linux?


225

Tôi muốn biết thư viện nào được sử dụng bởi các tệp thực thi trên hệ thống của tôi. Cụ thể hơn, tôi muốn xếp hạng thư viện nào được sử dụng nhiều nhất, cùng với các tệp nhị phân sử dụng chúng. Tôi có thể làm cái này như thế nào?


Bạn có thể sẽ không thể có được một con số chính xác nếu thực thi sử dụng dlopen.
jxh

Câu trả lời:


271
  1. Sử dụng lddđể liệt kê các thư viện chia sẻ cho mỗi thực thi.
  2. Dọn dẹp đầu ra
  3. Sắp xếp, tính toán, sắp xếp theo số lượng

Để tìm câu trả lời cho tất cả các tệp thực thi trong thư mục "/ bin":

find /bin -type f -perm /a+x -exec ldd {} \; \
| grep so \
| sed -e '/^[^\t]/ d' \
| sed -e 's/\t//' \
| sed -e 's/.*=..//' \
| sed -e 's/ (0.*)//' \
| sort \
| uniq -c \
| sort -n

Thay đổi "/ bin" ở trên thành "/" để tìm kiếm tất cả các thư mục.

Đầu ra (chỉ cho thư mục / bin) sẽ trông giống như thế này:

  1 /lib64/libexpat.so.0
  1 /lib64/libgcc_s.so.1
  1 /lib64/libnsl.so.1
  1 /lib64/libpcre.so.0
  1 /lib64/libproc-3.2.7.so
  1 /usr/lib64/libbeecrypt.so.6
  1 /usr/lib64/libbz2.so.1
  1 /usr/lib64/libelf.so.1
  1 /usr/lib64/libpopt.so.0
  1 /usr/lib64/librpm-4.4.so
  1 /usr/lib64/librpmdb-4.4.so
  1 /usr/lib64/librpmio-4.4.so
  1 /usr/lib64/libsqlite3.so.0
  1 /usr/lib64/libstdc++.so.6
  1 /usr/lib64/libz.so.1
  2 /lib64/libasound.so.2
  2 /lib64/libblkid.so.1
  2 /lib64/libdevmapper.so.1.02
  2 /lib64/libpam_misc.so.0
  2 /lib64/libpam.so.0
  2 /lib64/libuuid.so.1
  3 /lib64/libaudit.so.0
  3 /lib64/libcrypt.so.1
  3 /lib64/libdbus-1.so.3
  4 /lib64/libresolv.so.2
  4 /lib64/libtermcap.so.2
  5 /lib64/libacl.so.1
  5 /lib64/libattr.so.1
  5 /lib64/libcap.so.1
  6 /lib64/librt.so.1
  7 /lib64/libm.so.6
  9 /lib64/libpthread.so.0
 13 /lib64/libselinux.so.1
 13 /lib64/libsepol.so.1
 22 /lib64/libdl.so.2
 83 /lib64/ld-linux-x86-64.so.2
 83 /lib64/libc.so.6

Chỉnh sửa - Đã xóa "grep -P"


2
Đây là một câu trả lời tuyệt vời (tôi đã bình chọn nó) nhưng bạn có thể giải thích lệnh "grep -P '\ t. * So'" không? Theo con người, điều này diễn giải mô hình như một biểu thức chính quy perl, nhưng phiên bản grep của tôi không hỗ trợ nó (người đàn ông chỉ ra đây là vấn đề chung). Những gì của regex là cụ thể perl?
Bobby Jack

2
Tôi nghĩ rằng bạn có thể cần phải sử dụngldd -v
MountainX

58
Xin lưu ý rằng lddthực sự chạy tệp thực thi với một biến môi trường đặc biệt và trình liên kết động Linux nhận ra cờ này và chỉ xuất ra các thư viện thay vì chạy tệp thực thi. Nhìn vào nguồn để ldd; trên hệ thống của tôi, đó là một tập lệnh bash. Nếu tệp thực thi được liên kết tĩnh và sử dụng các tòa nhà, và chỉ định một trình tải khác, nó có thể làm những việc xấu tùy ý. Vì vậy, không sử dụng lddtrên một thực thi mà bạn không tin tưởng.
Barry Kelly

'ldd' không hoạt động đối với tôi trên các nhị phân được biên dịch chéo. Câu hỏi là về việc tìm kiếm các thư viện được sử dụng bởi các chương trình trên hệ thống hiện tại (đó sẽ là các chương trình gốc, như cụm từ). Đây là một câu trả lời tốt cho điều đó. Tuy nhiên, tôi nghĩ rằng tôi đã đề cập rằng bạn cần sử dụng một cái gì đó khác nếu tìm kiếm các lib được chia sẻ cho các chương trình cho một hệ thống khác ('readelf' được đề cập trong một câu trả lời khác, hoạt động cho tôi)
Tim Bird

68

Tôi không có ldd trên chuỗi công cụ ARM của mình nên tôi đã sử dụng objdump:

$ (CROSS_COMPILE) objdump -p

Ví dụ:

objdump -p /usr/bin/python:

Dynamic Section:
  NEEDED               libpthread.so.0
  NEEDED               libdl.so.2
  NEEDED               libutil.so.1
  NEEDED               libssl.so.1.0.0
  NEEDED               libcrypto.so.1.0.0
  NEEDED               libz.so.1
  NEEDED               libm.so.6
  NEEDED               libc.so.6
  INIT                 0x0000000000416a98
  FINI                 0x000000000053c058
  GNU_HASH             0x0000000000400298
  STRTAB               0x000000000040c858
  SYMTAB               0x0000000000402aa8
  STRSZ                0x0000000000006cdb
  SYMENT               0x0000000000000018
  DEBUG                0x0000000000000000
  PLTGOT               0x0000000000832fe8
  PLTRELSZ             0x0000000000002688
  PLTREL               0x0000000000000007
  JMPREL               0x0000000000414410
  RELA                 0x0000000000414398
  RELASZ               0x0000000000000078
  RELAENT              0x0000000000000018
  VERNEED              0x0000000000414258
  VERNEEDNUM           0x0000000000000008
  VERSYM               0x0000000000413534

2
Điều này cũng nên an toàn, không giống như không lddnên sử dụng trên các tệp thực thi không đáng tin cậy.
PSkocik

Ngoài ra, obbjdump -phiển thị thông tin bổ sung như RPATH, có thể hữu ích khi điều tra các vấn đề liên kết động với thực thi của bạn.
sitaktif

+1 cho phương thức thực sự an toàn và đáng tin cậy (bằng cách nào đó tôi đã có một hệ thống musl-gccthường xuyên tạo ra các nhị phân sao cho việc gọi lddnhị phân chỉ thực hiện nhị phân , vì vậy ngày nay tôi thường xuyên nhắc nhở về việc không an toàn như thế nào ldd).
mtraceur

54

Trên Linux tôi sử dụng:

lsof -P -T -p Application_PID

Điều này hoạt động tốt hơn so với lddkhi thực thi sử dụng trình tải không mặc định


Đã sử dụng điều này để tìm hiểu xem mariadb có thực sự sử dụng tc-malloc , được tải bởi LD_PRELOAD hay không. Công trình tuyệt vời.
cmc

2
Tôi đang tìm kiếm thứ gì đó sẽ cho tôi thấy '.so' cho một pid nhất định. Đây chính xác là những gì tôi cần. Cảm ơn!
Leo Ufimtsev

48

để tìm hiểu những thư viện sử dụng nhị phân, sử dụng ldd

ldd path/to/the/tool

Bạn sẽ phải viết một tập lệnh shell nhỏ để phân tích toàn hệ thống.


19

Kiểm tra các phụ thuộc thư viện chia sẻ của một chương trình thực thi

Để tìm ra những thư viện mà một thực thi cụ thể phụ thuộc vào, bạn có thể sử dụng lệnh ldd. Lệnh này gọi trình liên kết động để tìm ra các phụ thuộc thư viện của một tệp thực thi.

> $ ldd / đường dẫn / đến / chương trình

Lưu ý rằng KHÔNG nên chạy ldd với bất kỳ bên thứ ba không đáng tin cậy nào vì một số phiên bản của ldd có thể trực tiếp gọi tệp thực thi để xác định các phụ thuộc thư viện của nó, có thể gây rủi ro bảo mật.

Thay vào đó, một cách an toàn hơn để hiển thị các phụ thuộc thư viện của tệp nhị phân ứng dụng không xác định là sử dụng lệnh sau.

$ objdump -p / đường dẫn / đến / chương trình | grep CẦN

để biết thêm


14

readelf -d đệ quy

redelf -dtạo ra sản lượng tương tự objdump -pđược đề cập tại: https://stackoverflow.com/a/15520982/895245

Nhưng hãy cẩn thận rằng các thư viện động có thể phụ thuộc vào các thư viện động khác, để bạn phải kiểm tra lại.

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]

Sau đó:

$ 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

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ư thế.

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

Đ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: /superuser/310199/see-civersely-loaded- Shared -objects-in-linux / 12303089


7

Trên OS X theo mặc định không có ldd, objdumphoặc lsof. Để thay thế, hãy thử otool -L:

$ otool -L `which openssl`
/usr/bin/openssl:
    /usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
    /usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

Trong ví dụ này, sử dụng which opensslđiền vào đường dẫn đủ điều kiện cho môi trường người dùng hiện tại và thực thi nhất định.


6

Trên hệ thống UNIX, giả sử tên nhị phân (thực thi) là thử nghiệm. Sau đó, chúng tôi sử dụng lệnh sau để liệt kê các thư viện được sử dụng trong thử nghiệm là

ldd test

4

Với lddbạn có thể có được các thư viện mà các công cụ sử dụng. Để xếp hạng việc sử dụng các thư viện cho một bộ công cụ, bạn có thể sử dụng một cái gì đó như lệnh sau.

ldd /bin/* /usr/bin/* ... | sed -e '/^[^\t]/ d; s/^\t\(.* => \)\?\([^ ]*\) (.*/\2/g' | sort | uniq -c

(Ở đây sedloại bỏ tất cả các dòng không bắt đầu bằng một tab và chỉ lọc ra các thư viện thực tế. Với sort | uniq -cbạn, mỗi thư viện sẽ có một số đếm cho biết số lần xảy ra.)

Bạn có thể muốn thêm sort -gvào cuối để có được các thư viện theo thứ tự sử dụng.

Lưu ý rằng bạn có thể nhận được hai dòng không phải thư viện với lệnh trên. Một trong những thực thi tĩnh ("không phải là thực thi động") và một không có thư viện. Cái sau là kết quả của linux-gate.so.1nó không phải là một thư viện trong hệ thống tệp của bạn mà là một "được cung cấp" bởi kernel.


2

Một tùy chọn khác có thể chỉ là đọc tệp nằm ở

/proc/<pid>/maps

Ví dụ: id quá trình là 2601 thì lệnh là

cat /proc/2601/maps

Và đầu ra là như thế

7fb37a8f2000-7fb37a8f4000 r-xp 00000000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37a8f4000-7fb37aaf3000 ---p 00002000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37aaf3000-7fb37aaf4000 r--p 00001000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37aaf4000-7fb37aaf5000 rw-p 00002000 08:06 4065647                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/network_networkmanager.so
7fb37aaf5000-7fb37aafe000 r-xp 00000000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37aafe000-7fb37acfd000 ---p 00009000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37acfd000-7fb37acfe000 r--p 00008000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37acfe000-7fb37acff000 rw-p 00009000 08:06 4065646                    /usr/lib/x86_64-linux-gnu/libproxy/0.4.15/modules/config_gnome3.so
7fb37acff000-7fb37ad1d000 r-xp 00000000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37ad1d000-7fb37af1d000 ---p 0001e000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37af1d000-7fb37af1e000 r--p 0001e000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37af1e000-7fb37af1f000 rw-p 0001f000 08:06 3416761                    /usr/lib/x86_64-linux-gnu/libproxy.so.1.0.0
7fb37af1f000-7fb37af21000 r-xp 00000000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
7fb37af21000-7fb37b121000 ---p 00002000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
7fb37b121000-7fb37b122000 r--p 00002000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
7fb37b122000-7fb37b123000 rw-p 00003000 08:06 4065186                    /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so

2

trên các gói in ubfox liên quan đến thực thi

ldd executable_name|awk '{print $3}'|xargs dpkg -S |awk -F  ":"  '{print $1}'

0

Tôi thấy bài đăng này rất hữu ích vì tôi cần điều tra các phụ thuộc từ thư viện do bên thứ 3 cung cấp (đường dẫn thực thi 32 so với 64 bit).

Tôi kết hợp một tập lệnh bash đệ quy Q & D dựa trên đề xuất 'readelf -d' trên bản phân phối RHEL 6.

Nó rất cơ bản và sẽ kiểm tra mọi phụ thuộc mọi lúc ngay cả khi nó có thể đã được kiểm tra trước đó (tức là rất dài dòng). Đầu ra là rất cơ bản quá.

#! /bin/bash

recurse ()
# Param 1 is the nuumber of spaces that the output will be prepended with
# Param 2 full path to library
{
#Use 'readelf -d' to find dependencies
dependencies=$(readelf -d ${2} | grep NEEDED | awk '{ print $5 }' | tr -d '[]')
for d in $dependencies; do
   echo "${1}${d}"
   nm=${d##*/}
   #libstdc++ hack for the '+'-s
   nm1=${nm//"+"/"\+"}
   # /lib /lib64 /usr/lib and /usr/lib are searched
   children=$(locate ${d} | grep -E "(^/(lib|lib64|usr/lib|usr/lib64)/${nm1})")
   rc=$?
   #at least locate... didn't fail
   if [ ${rc} == "0" ] ; then
      #we have at least one dependency
      if [ ${#children[@]} -gt 0 ]; then
         #check the dependeny's dependencies
         for c in $children; do
          recurse "  ${1}" ${c}
         done
      else
         echo "${1}no children found"
      fi
   else
      echo "${1}locate failed for ${d}"
   fi
done
}
# Q&D -- recurse needs 2 params could/should be supplied from cmdline
recurse "" !!full path to library you want to investigate!!

chuyển hướng đầu ra đến một tệp và grep cho 'tìm thấy' hoặc 'không thành công'

Sử dụng và sửa đổi, có nguy cơ của riêng bạn, tất nhiên, như bạn muốn.

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.