จะแสดงไลบรารี่ที่ใช้ร่วมกันทั้งหมดที่ใช้งานโดยเอ็กซีคิ้วท์ใน Linux ได้อย่างไร?


225

ฉันต้องการทราบว่าไลบรารี่ใดที่ถูกใช้งานบนระบบของฉัน โดยเฉพาะอย่างยิ่งฉันต้องการจัดอันดับห้องสมุดที่มีการใช้งานมากที่สุดพร้อมกับไบนารีที่ใช้พวกเขา ฉันจะทำสิ่งนี้ได้อย่างไร


คุณอาจจะไม่สามารถที่จะได้รับเป็นจำนวนที่แน่นอนถ้า executables dlopenใช้
jxh

คำตอบ:


271
  1. ใช้lddเพื่อแสดงรายการไลบรารีที่แบ่งใช้สำหรับแต่ละไฟล์ที่เรียกทำงานได้
  2. ล้างข้อมูลเอาต์พุต
  3. เรียงลำดับคำนวณนับเรียงตามจำนวน

หากต้องการค้นหาคำตอบสำหรับไฟล์ปฏิบัติการทั้งหมดในไดเรกทอรี "/ 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

เปลี่ยน "/ bin" ด้านบนเป็น "/" เพื่อค้นหาไดเรกทอรีทั้งหมด

เอาต์พุต (สำหรับไดเร็กทอรี / bin) จะมีลักษณะดังนี้:

  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

แก้ไข - นำ "grep -P" ออกแล้ว


2
นี่เป็นคำตอบที่ยอดเยี่ยม (ฉันโหวตแล้ว) แต่คุณสามารถอธิบายคำสั่ง "grep -P '\ t. * so'" ได้ไหม? จากคำบอกเล่าของมนุษย์การตีความนี้เป็นรูปแบบที่เป็น perexp regp แต่ grep รุ่นของฉันไม่รองรับ (คนระบุว่านี่เป็นปัญหาทั่วไป) regexp คืออะไรเฉพาะ perl?
บ๊อบบี้แจ็ค

2
ฉันคิดว่าคุณอาจจำเป็นต้องใช้ldd -v
MountainX

58
โปรดทราบว่าที่lddจริงแล้วเรียกใช้ไฟล์ปฏิบัติการด้วยตัวแปรสภาพแวดล้อมพิเศษและตัวเชื่อมโยงแบบไดนามิกของ Linux จะรับรู้สถานะนี้และเพียงแสดงผลไลบรารีแทนที่จะเรียกใช้ไฟล์ปฏิบัติการ ดูที่มาเพื่อldd; ในระบบของฉันมันเป็นสคริปต์ทุบตี หากปฏิบัติการเชื่อมโยงแบบคงที่และใช้ syscalls และระบุตัวโหลดที่แตกต่างกันมันสามารถทำสิ่งชั่วร้ายโดยพลการ ดังนั้นอย่าใช้lddกับไฟล์ที่คุณไม่เชื่อถือ
Barry Kelly

'ldd' ไม่ทำงานสำหรับฉันในไบนารีที่คอมไพล์ข้าม คำถามคือเกี่ยวกับการค้นหาไลบรารีที่ใช้โดยโปรแกรมในระบบปัจจุบัน (ซึ่งจะเป็นโปรแกรมเนทีฟตามวลี) นี่เป็นคำตอบที่ดีสำหรับสิ่งนั้น อย่างไรก็ตามฉันคิดว่าฉันจะพูดถึงว่าคุณต้องใช้อย่างอื่นถ้ามองหา libs ที่ใช้ร่วมกันสำหรับโปรแกรมสำหรับระบบที่แตกต่างกัน ('readelf' ที่กล่าวถึงในคำตอบอื่นทำงานให้ฉัน)
Tim Bird

68

ฉันไม่มี ldd บน toolchain ของฉันดังนั้นฉันจึงใช้ objdump:

$ (CROSS_COMPILE) objdump -p

ตัวอย่างเช่น

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
นี่ควรจะปลอดภัยด้วยlddซึ่งแตกต่างจากที่ไม่ควรใช้กับไฟล์ที่ไม่น่าเชื่อถือ
PSkocik

นอกจากนี้ยังobbjdump -pแสดงข้อมูลเพิ่มเติมเช่นRPATHซึ่งอาจเป็นประโยชน์เมื่อตรวจสอบปัญหาการเชื่อมโยงแบบไดนามิกกับปฏิบัติการของคุณ
sitaktif

+1 สำหรับวิธีการที่ปลอดภัยและเชื่อถือได้จริง ๆ (ฉันมีระบบที่musl-gccสร้างไบนารีอย่างสม่ำเสมอเช่นการเรียกlddเลขฐานสองเพียงแค่เรียกใช้งานไบนารีดังนั้นทุกวันนี้ฉันเตือนตัวเองถึงวิธีที่ไม่ปลอดภัยldd)
mtraceur

54

บน Linux ฉันใช้:

lsof -P -T -p Application_PID

สิ่งนี้จะทำงานได้ดีกว่าlddเมื่อไฟล์ปฏิบัติการใช้ตัวโหลดที่ไม่ใช่ค่าดีฟอลต์


ใช้สิ่งนี้เพื่อดูว่าmariadb ใช้ tc-malloc จริงหรือไม่ซึ่งโหลดโดย LD_PRELOAD ใช้งานได้ดี
cmc

2
ฉันกำลังมองหาบางอย่างที่จะแสดง '.so' สำหรับ pid ที่ระบุ นี่คือสิ่งที่ฉันต้องการ ขอบคุณ!
Leo Ufimtsev

48

เพื่อเรียนรู้ว่าไลบรารีใช้ไบนารีอะไรให้ใช้ ldd

ldd path/to/the/tool

คุณจะต้องเขียนเชลล์สคริปต์เล็กน้อยเพื่อไปยังรายละเอียดทั่วทั้งระบบของคุณ


19

ตรวจสอบการอ้างอิงไลบรารีที่แบ่งใช้ของโปรแกรมที่เรียกทำงานได้

หากต้องการทราบว่าไลบรารีใดที่สามารถปฏิบัติการได้ขึ้นอยู่กับไลบรารีคุณสามารถใช้คำสั่ง ldd คำสั่งนี้เรียกใช้ dynamic linker เพื่อค้นหาการขึ้นต่อกันของไลบรารีของ executable

> $ ldd / path / to / program

โปรดทราบว่าไม่แนะนำให้เรียกใช้ ldd ด้วยโปรแกรมปฏิบัติการของ บริษัท อื่นที่ไม่น่าเชื่อถือเนื่องจาก ldd บางรุ่นอาจเรียกใช้งานโดยตรงเพื่อระบุการขึ้นต่อกันของไลบรารีซึ่งอาจมีความเสี่ยงด้านความปลอดภัย

วิธีที่ปลอดภัยกว่าในการแสดงการพึ่งพาไลบรารีของไบนารีแอปพลิเคชันที่ไม่รู้จักคือการใช้คำสั่งต่อไปนี้

$ objdump -p / path / to / program | grep ต้องการ

สำหรับข้อมูลเพิ่มเติม


14

readelf -d เรียกซ้ำ

redelf -dสร้างเอาต์พุตที่คล้ายกันobjdump -pซึ่งถูกกล่าวถึงที่: https://stackoverflow.com/a/15520982/895245

แต่ระวังว่าไลบรารีแบบไดนามิกสามารถขึ้นอยู่กับไลบรารีแบบไดนามิกอื่น ๆ เพื่อที่คุณจะต้องเรียกคืน

ตัวอย่าง:

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

ตัวอย่าง ouptut:

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

แล้ว:

$ 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

เลือกหนึ่งรายการแล้วทำซ้ำ:

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

ตัวอย่างผลลัพธ์:

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]

และอื่น ๆ

/proc/<pid>/maps สำหรับกระบวนการทำงาน

สิ่งนี้มีประโยชน์ในการค้นหาไลบรารีทั้งหมดที่ใช้งานอยู่ในขณะนี้โดยเรียกใช้โปรแกรมปฏิบัติการ เช่น:

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

แสดงการพึ่งพาแบบไดนามิกที่โหลดในปัจจุบันทั้งหมดของ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

วิธีนี้ยังแสดงไลบรารีที่เปิดด้วยdlopenทดสอบด้วยการตั้งค่าขั้นต่ำนี้ซึ่งถูกแฮ็กด้วยกับsleep(1000)Ubuntu 18.04

ดูเพิ่มเติมที่: /superuser/310199/see-currently-loaded-shared-objects-in-linux/1243089


7

บน OS X โดยค่าเริ่มต้นไม่มีldd, หรือobjdump lsofเป็นทางเลือกลอง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)

ในตัวอย่างนี้ใช้การwhich opensslเติมในพา ธ ที่ผ่านการรับรองโดยสมบูรณ์สำหรับสภาพแวดล้อมผู้ใช้ที่สามารถเรียกใช้งานได้และปัจจุบัน


6

บนระบบ UNIX สมมติว่าชื่อ binary (executable) คือการทดสอบ จากนั้นเราจะใช้คำสั่งต่อไปนี้เพื่อแสดงรายการไลบรารีที่ใช้ในการทดสอบคือ

ldd test

4

ด้วยlddคุณสามารถรับไลบรารีที่เครื่องมือใช้ ในการจัดอันดับการใช้งานไลบรารี่สำหรับชุดเครื่องมือคุณสามารถใช้คำสั่งดังต่อไปนี้

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

(ที่นี่จะsedตัดบรรทัดทั้งหมดที่ไม่ได้ขึ้นต้นด้วยแท็บและตัวกรองจะออกเฉพาะไลบรารีจริง ๆ เท่านั้นเมื่อsort | uniq -cคุณได้รับแต่ละไลบรารีด้วยการนับจำนวนจะแสดงจำนวนครั้งที่มันเกิดขึ้น)

คุณอาจต้องการเพิ่มsort -gในตอนท้ายเพื่อรับไลบรารีตามลำดับการใช้งาน

โปรดทราบว่าคุณอาจได้รับสองบรรทัดที่ไม่ใช่ห้องสมุดด้วยคำสั่งดังกล่าว หนึ่งใน executables แบบคงที่ ("ไม่ใช่แบบไดนามิกที่ปฏิบัติการได้") และหนึ่งในนั้นที่ไม่มีไลบรารี หลังคือผลลัพธ์linux-gate.so.1ซึ่งไม่ใช่ไลบรารีในระบบไฟล์ของคุณ แต่มีเคอร์เนล "ระบุ" หนึ่งอัน


2

อีกทางเลือกหนึ่งสามารถอ่านไฟล์ที่อยู่ที่

/proc/<pid>/maps

ตัวอย่างเช่น id กระบวนการคือ 2601 ดังนั้นคำสั่งคือ

cat /proc/2601/maps

และผลลัพธ์ก็เหมือน

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

บน Ubuntu แพ็คเกจการพิมพ์ที่เกี่ยวข้องกับการปฏิบัติการ

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

0

ฉันพบว่าโพสต์นี้มีประโยชน์มากเพราะฉันต้องการตรวจสอบการอ้างอิงจากห้องสมุดบุคคลที่สามที่ให้บริการ (เส้นทางการดำเนินการ 32 vs 64 บิต)

ฉันรวบรวมสคริปต์ B&D แบบเรียกซ้ำอีกครั้งโดยอ้างอิงจากข้อเสนอแนะ 'readelf -d' ใน distro RHEL 6

มันเป็นพื้นฐานมากและจะทดสอบทุกการพึ่งพาทุกครั้งแม้ว่ามันอาจได้รับการทดสอบมาก่อน (เช่น verbose มาก) เอาต์พุตก็ธรรมดามากเช่นกัน

#! /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!!

เปลี่ยนเส้นทางผลลัพธ์ไปยังไฟล์และ grep สำหรับ 'พบ' หรือ 'ล้มเหลว'

ใช้และแก้ไขตามความเสี่ยงของคุณเองตามที่คุณต้องการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.