ฉันจะแสดงรายการสัญลักษณ์ในไฟล์. so ได้อย่างไร


486

ฉันจะแสดงรายการสัญลักษณ์ที่ส่งออกจากไฟล์. so ได้อย่างไร ถ้าเป็นไปได้ฉันก็อยากจะรู้แหล่งที่มาของมัน (เช่นถ้าพวกมันถูกดึงเข้ามาจากห้องสมุดคง)

ฉันใช้ gcc 4.0.2 ถ้านั่นสร้างความแตกต่าง


แพลตฟอร์มสร้างความแตกต่าง Apple จัดหา GCC 4.0 แต่nmไม่ตอบสนองต่อตัวเลือกบางอย่างเช่น-Dและ-g(IIRC)
jww

สิ่งนี้ไม่พิมพ์บน Mac OS
IgorGanapolsky

3
@jww เพราะที่ BSD nmไม่ nmGNU
OrangeDog

คำตอบ:


576

เครื่องมือมาตรฐานสำหรับรายชื่อสัญลักษณ์คือnmคุณสามารถใช้มันได้เช่นนี้

nm -gD yourLib.so

หากคุณต้องการเห็นสัญลักษณ์ของไลบรารี C ++ ให้เพิ่มตัวเลือก "-C" ซึ่งทำให้สัญลักษณ์แยกย่อย

nm -gDC yourLib.so

หากไฟล์. so ของคุณอยู่ในรูปแบบ elf คุณมีสองตัวเลือกดังนี้:

อย่างใดอย่างหนึ่งobjdump( -Cยังมีประโยชน์สำหรับการถอด C ++):

$ objdump -TC libz.so

libz.so:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000002010 l    d  .init  0000000000000000              .init
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 free
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __errno_location
0000000000000000  w   D  *UND*  0000000000000000              _ITM_deregisterTMCloneTable

หรือใช้readelf:

$ readelf -Ws libz.so
Symbol table '.dynsym' contains 112 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000002010     0 SECTION LOCAL  DEFAULT   10
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND free@GLIBC_2.2.5 (14)
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __errno_location@GLIBC_2.2.5 (14)
     4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable

35
แม้ว่าจะไม่ได้ทำงานกับไฟล์. so เสมอไปดังนั้นคุณอาจต้องใช้วิธีการแก้ปัญหา "readelf" ที่กล่าวถึงในคำตอบอื่น
Brooks Moses

9
โปรดทราบว่าเวอร์ชัน OS X ของ nm ไม่มีตัวเลือก '-C' สำหรับสัญลักษณ์การถอดตำแหน่ง c ++ filt สามารถใช้แทนได้ สคริปต์ตัวอย่างที่นี่: v8.googlecode.com/svn/branches/bleeding_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | c ++ filt -p -i
fredbaba

5
โปรดทราบว่าreadelf -Wsจะแสดงสัญลักษณ์ทั้งหมดและnm -gแสดงเฉพาะสัญลักษณ์ที่มองเห็นได้จากภายนอก สิ่งนี้อาจสร้างความสับสนหากคุณตรวจสอบไฟล์สัญลักษณ์หลายไฟล์และเริ่มการแลกเปลี่ยนคำสั่ง
Andrew B

3
ฉันจะเพิ่มobjectdump -TCไปยังรายการ ในทางตรงกันข้ามreadelf -Wsมันไม่แสดงชื่อ mangled
Yan Foto

2
@BrooksMoses สำหรับ.soไฟล์คุณอาจต้องเพิ่ม--dynamicในnmบรรทัดคำสั่ง
user7610

84

หาก.soไฟล์ของคุณอยู่ในรูปแบบเอลฟ์คุณสามารถใช้โปรแกรม readelf เพื่อดึงข้อมูลสัญลักษณ์จากไบนารี คำสั่งนี้จะให้ตารางสัญลักษณ์แก่คุณ:

readelf -Ws /usr/lib/libexample.so

คุณควรแตก.soไฟล์ที่กำหนดไว้ในไฟล์นี้ไม่ใช่ในไลบรารีที่ถูกอ้างอิง คอลัมน์ที่เจ็ดควรมีตัวเลขในกรณีนี้ คุณสามารถแยกมันโดยใช้ regex ง่าย ๆ :

readelf -Ws /usr/lib/libstdc++.so.6 | grep '^\([[:space:]]\+[^[:space:]]\+\)\{6\}[[:space:]]\+[[:digit:]]\+'

หรือตามที่เสนอโดยCaspin :

readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}';

19
readelf -Ws /usr/lib/libstdc++.so.6 | awk '{พิมพ์ $ 8}'; regexes ยอดเยี่ยม แต่บางครั้ง awk เล็ก ๆ น้อย ๆ ไปไกล
deft_code


42

สำหรับไลบรารีที่แบ่งใช้ libNAME ดังนั้นสวิตช์ -D จึงจำเป็นต้องดูสัญลักษณ์ใน Linux ของฉัน

nm -D libNAME.so

และสำหรับห้องสมุดแบบคงที่ซึ่งรายงานโดยผู้อื่น

nm -g libNAME.a

35

ผมเก็บไว้สงสัยว่าทำไม-fvisibility = ซ่อนและการมองเห็น #pragma GCCไม่ได้ดูเหมือนจะมีอิทธิพลใด ๆ ที่เป็นสัญลักษณ์ทุกคนมักจะมองเห็นได้ด้วยนาโนเมตร - จนกว่าผมพบว่าโพสต์นี้ที่ชี้ให้ฉันไปreadelfและobjdumpซึ่งทำให้ผมรู้ว่ามี ดูเหมือนจะเป็นตารางสัญลักษณ์สองอัน :

  • รายการที่คุณสามารถแสดงด้วยnm
  • รายการที่คุณสามารถแสดงด้วยreadelfและobjdump

ฉันคิดว่าในอดีตมีสัญลักษณ์การแก้จุดบกพร่องที่สามารถถอดได้ด้วยแถบหรือสวิตช์ -s ที่คุณสามารถมอบให้กับ linker หรือคำสั่งติดตั้ง และแม้ว่า nm จะไม่แสดงรายการอะไรอีกต่อไปสัญลักษณ์ส่งออกของคุณยังคงถูกส่งออกเพราะอยู่ใน "ตารางสัญลักษณ์ไดนามิก" ของเอลฟ์ซึ่งเป็นสัญลักษณ์หลัง


3
ขอบคุณ! สิ่งนี้อธิบายว่าทำไมบางครั้ง "nm" ไม่แสดงสัญลักษณ์ใด ๆ สำหรับไฟล์. so
Brooks Moses

10
nm -D - ให้คุณแสดงตารางสัญลักษณ์แบบไดนามิก
pt123

19

สำหรับ.soไฟล์C ++ nmคำสั่งultimate คือnm --demangle --dynamic --defined-only --extern-only <my.so>

# nm --demangle --dynamic --defined-only --extern-only /usr/lib64/libqpid-proton-cpp.so | grep work | grep add
0000000000049500 T proton::work_queue::add(proton::internal::v03::work)
0000000000049580 T proton::work_queue::add(proton::void_function0&)
000000000002e7b0 W proton::work_queue::impl::add_void(proton::internal::v03::work)
000000000002b1f0 T proton::container::impl::add_work_queue()
000000000002dc50 T proton::container::impl::container_work_queue::add(proton::internal::v03::work)
000000000002db60 T proton::container::impl::connection_work_queue::add(proton::internal::v03::work)

แหล่งที่มา: https://stackoverflow.com/a/43257338


11

ลองเพิ่ม -l ในแฟล็ก nm เพื่อรับแหล่งที่มาของแต่ละสัญลักษณ์ หากไลบรารีถูกคอมไพล์ด้วยข้อมูลการดีบัก (gcc -g) สิ่งนี้ควรเป็นไฟล์ต้นฉบับและหมายเลขบรรทัด ในขณะที่ Konrad กล่าวว่าจุดนี้อาจไม่รู้จักไฟล์วัตถุ / ไลบรารีแบบคงที่


11

สำหรับ Android .soไฟล์ที่ toolchain NDK มาพร้อมกับเครื่องมือที่จำเป็นที่ระบุไว้ในคำตอบอื่น ๆ : readelf, และobjdumpnm


9

คุณสามารถใช้nm -gเครื่องมือจาก binutils toolchain อย่างไรก็ตามแหล่งข้อมูลเหล่านั้นอาจไม่พร้อมใช้งานเสมอ และฉันก็ไม่แน่ใจด้วยซ้ำว่าข้อมูลนี้สามารถเรียกคืนได้เสมอ อาจobjcopyเปิดเผยข้อมูลเพิ่มเติม

/ แก้ไข: nmชื่อของเครื่องมือเป็นหลักสูตร การตั้งค่าสถานะ-gใช้เพื่อแสดงสัญลักษณ์ที่ส่งออกเท่านั้น


6

nm -g แสดงรายการตัวแปร extern ซึ่งไม่จำเป็นต้องมีสัญลักษณ์เอ็กซ์พอร์ต ตัวแปรขอบเขตไฟล์ที่ไม่คงที่ (ใน C) เป็นตัวแปร extern ทั้งหมด

nm -D จะแสดงรายการสัญลักษณ์ในตารางแบบไดนามิกซึ่งคุณสามารถค้นหาที่อยู่ได้โดย dlsym

นาโนเมตร - รุ่น

GNU nm 2.17.50.0.6-12.el5 20061020


1

หากคุณต้องการทราบว่ามีสัญลักษณ์อยู่หรือไม่คุณสามารถใช้

objdump -h /path/to/object

หรือเพื่อแสดงรายการข้อมูลการดีบัก

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