ฉันจะแสดงรายการสัญลักษณ์ที่ส่งออกจากไฟล์. so ได้อย่างไร ถ้าเป็นไปได้ฉันก็อยากจะรู้แหล่งที่มาของมัน (เช่นถ้าพวกมันถูกดึงเข้ามาจากห้องสมุดคง)
ฉันใช้ gcc 4.0.2 ถ้านั่นสร้างความแตกต่าง
nm
ไม่ nm
GNU
ฉันจะแสดงรายการสัญลักษณ์ที่ส่งออกจากไฟล์. so ได้อย่างไร ถ้าเป็นไปได้ฉันก็อยากจะรู้แหล่งที่มาของมัน (เช่นถ้าพวกมันถูกดึงเข้ามาจากห้องสมุดคง)
ฉันใช้ gcc 4.0.2 ถ้านั่นสร้างความแตกต่าง
nm
ไม่ nm
GNU
คำตอบ:
เครื่องมือมาตรฐานสำหรับรายชื่อสัญลักษณ์คือ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
readelf -Ws
จะแสดงสัญลักษณ์ทั้งหมดและnm -g
แสดงเฉพาะสัญลักษณ์ที่มองเห็นได้จากภายนอก สิ่งนี้อาจสร้างความสับสนหากคุณตรวจสอบไฟล์สัญลักษณ์หลายไฟล์และเริ่มการแลกเปลี่ยนคำสั่ง
objectdump -TC
ไปยังรายการ ในทางตรงกันข้ามreadelf -Ws
มันไม่แสดงชื่อ mangled
.so
ไฟล์คุณอาจต้องเพิ่ม--dynamic
ในnm
บรรทัดคำสั่ง
หาก.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}';
objdump -TC /usr/lib/libexample.so
สำหรับไลบรารีที่แบ่งใช้ libNAME ดังนั้นสวิตช์ -D จึงจำเป็นต้องดูสัญลักษณ์ใน Linux ของฉัน
nm -D libNAME.so
และสำหรับห้องสมุดแบบคงที่ซึ่งรายงานโดยผู้อื่น
nm -g libNAME.a
ผมเก็บไว้สงสัยว่าทำไม-fvisibility = ซ่อนและการมองเห็น #pragma GCCไม่ได้ดูเหมือนจะมีอิทธิพลใด ๆ ที่เป็นสัญลักษณ์ทุกคนมักจะมองเห็นได้ด้วยนาโนเมตร - จนกว่าผมพบว่าโพสต์นี้ที่ชี้ให้ฉันไปreadelfและobjdumpซึ่งทำให้ผมรู้ว่ามี ดูเหมือนจะเป็นตารางสัญลักษณ์สองอัน :
ฉันคิดว่าในอดีตมีสัญลักษณ์การแก้จุดบกพร่องที่สามารถถอดได้ด้วยแถบหรือสวิตช์ -s ที่คุณสามารถมอบให้กับ linker หรือคำสั่งติดตั้ง และแม้ว่า nm จะไม่แสดงรายการอะไรอีกต่อไปสัญลักษณ์ส่งออกของคุณยังคงถูกส่งออกเพราะอยู่ใน "ตารางสัญลักษณ์ไดนามิก" ของเอลฟ์ซึ่งเป็นสัญลักษณ์หลัง
สำหรับ.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
ลองเพิ่ม -l ในแฟล็ก nm เพื่อรับแหล่งที่มาของแต่ละสัญลักษณ์ หากไลบรารีถูกคอมไพล์ด้วยข้อมูลการดีบัก (gcc -g) สิ่งนี้ควรเป็นไฟล์ต้นฉบับและหมายเลขบรรทัด ในขณะที่ Konrad กล่าวว่าจุดนี้อาจไม่รู้จักไฟล์วัตถุ / ไลบรารีแบบคงที่
สำหรับ Android .so
ไฟล์ที่ toolchain NDK มาพร้อมกับเครื่องมือที่จำเป็นที่ระบุไว้ในคำตอบอื่น ๆ : readelf
, และobjdump
nm
คุณสามารถใช้nm -g
เครื่องมือจาก binutils toolchain อย่างไรก็ตามแหล่งข้อมูลเหล่านั้นอาจไม่พร้อมใช้งานเสมอ และฉันก็ไม่แน่ใจด้วยซ้ำว่าข้อมูลนี้สามารถเรียกคืนได้เสมอ อาจobjcopy
เปิดเผยข้อมูลเพิ่มเติม
/ แก้ไข: nm
ชื่อของเครื่องมือเป็นหลักสูตร การตั้งค่าสถานะ-g
ใช้เพื่อแสดงสัญลักษณ์ที่ส่งออกเท่านั้น
nm -g แสดงรายการตัวแปร extern ซึ่งไม่จำเป็นต้องมีสัญลักษณ์เอ็กซ์พอร์ต ตัวแปรขอบเขตไฟล์ที่ไม่คงที่ (ใน C) เป็นตัวแปร extern ทั้งหมด
nm -D จะแสดงรายการสัญลักษณ์ในตารางแบบไดนามิกซึ่งคุณสามารถค้นหาที่อยู่ได้โดย dlsym
นาโนเมตร - รุ่น
GNU nm 2.17.50.0.6-12.el5 20061020
หากคุณต้องการทราบว่ามีสัญลักษณ์อยู่หรือไม่คุณสามารถใช้
objdump -h /path/to/object
หรือเพื่อแสดงรายการข้อมูลการดีบัก
objdump -g /path/to/object
nm
ไม่ตอบสนองต่อตัวเลือกบางอย่างเช่น-D
และ-g
(IIRC)