Làm cách nào để liệt kê các ký hiệu trong tệp .so


486

Làm cách nào để liệt kê các ký hiệu đang được xuất từ ​​tệp .so? Nếu có thể, tôi cũng muốn biết nguồn của họ (ví dụ: nếu chúng được kéo vào từ thư viện tĩnh).

Tôi đang sử dụng gcc 4.0.2, nếu điều đó tạo ra sự khác biệt.


Nền tảng tạo nên sự khác biệt. Apple cung cấp GCC 4.0, nhưng nó nmkhông đáp ứng với một số tùy chọn, như -D-g(IIRC).
jww

Điều này in không có gì trên Mac OS.
IgorGanapolsky

3
@jww vì đó là BSD nm, không phải GNU nm.
OrangeDog

Câu trả lời:


577

Công cụ tiêu chuẩn để liệt kê các biểu tượng là nm, bạn có thể sử dụng nó đơn giản như thế này:

nm -gD yourLib.so

Nếu bạn muốn xem các ký hiệu của thư viện C ++, hãy thêm tùy chọn "-C" để giải mã các ký hiệu (nó dễ đọc hơn rất nhiều).

nm -gDC yourLib.so

Nếu tệp .so của bạn ở định dạng elf, bạn có hai tùy chọn:

Hoặc objdump( -Ccũng hữu ích cho việc gỡ rối 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

Hoặc sử dụng 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
Tuy nhiên, điều này không phải lúc nào cũng hoạt động với các tệp .so và do đó bạn có thể phải sử dụng giải pháp "đọc" được đề cập trong câu trả lời khác.
Brooks Moses

9
Lưu ý rằng các phiên bản OS X của nm bị thiếu tùy chọn '-C' cho các biểu tượng sắp xếp. Bộ lọc c ++ có thể được sử dụng thay thế. Kịch bản ví dụ ở đây: v8.googlecode.com/svn/branches/bleinating_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | c ++
lọc

5
Lưu ý rằng readelf -Wssẽ hiển thị cho bạn tất cả các biểu tượng và nm -gchỉ hiển thị các biểu tượng hiển thị bên ngoài. Điều này có thể gây nhầm lẫn nếu bạn đang kiểm tra nhiều tệp biểu tượng và bắt đầu trao đổi các lệnh của bạn.
Andrew B

3
Tôi cũng sẽ thêm objectdump -TCvào danh sách. Ngược lại readelf -Ws, nó không hiển thị tên xéo.
Yan Foto

2
@BrooksMoses Đối với .socác tệp bạn có thể cần thêm --dynamicvào nmdòng lệnh.
dùng7610

84

Nếu .sotệp của bạn ở định dạng elf, bạn có thể sử dụng chương trình readelf để trích xuất thông tin ký hiệu từ tệp nhị phân. Lệnh này sẽ cung cấp cho bạn bảng biểu tượng:

readelf -Ws /usr/lib/libexample.so

Bạn chỉ nên trích xuất những cái được định nghĩa trong .sotệp này , không phải trong các thư viện được tham chiếu bởi nó. Cột thứ bảy nên chứa một số trong trường hợp này. Bạn có thể giải nén nó bằng cách sử dụng regex đơn giản:

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

hoặc, theo đề xuất của Caspin ,:

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

19
readelf -Ws /usr/lib/libstdc++.so.6 | awk '{in $ 8}'; regexes là tuyệt vời nhưng đôi khi một chút awk đi một chặng đường dài.
deft_code


42

Đối với các thư viện dùng chung libNAME. Ngoài ra, công tắc -D là cần thiết để xem các biểu tượng trong Linux của tôi

nm -D libNAME.so

và cho thư viện tĩnh như báo cáo của người khác

nm -g libNAME.a

35

Tôi liên tục tự hỏi tại sao -fvisibility = ẩntầm nhìn #pragma GCC đã dường như không có bất kỳ ảnh hưởng, như tất cả những biểu tượng luôn có thể nhìn thấy với nm - cho đến khi tôi tìm thấy bài này mà chỉ tôi readelfobjdump , mà làm cho tôi nhận ra rằng có dường như thực sự là hai bảng biểu tượng:

  • Một trong những bạn có thể liệt kê với nm
  • Một trong những bạn có thể liệt kê với readelfobjdump

Tôi nghĩ rằng trước đây có chứa các biểu tượng gỡ lỗi có thể được tước bằng dải hoặc chuyển đổi -s mà bạn có thể cung cấp cho trình liên kết hoặc lệnh cài đặt . Và ngay cả khi nm không liệt kê bất cứ điều gì nữa, các biểu tượng đã xuất của bạn vẫn được xuất vì chúng nằm trong "bảng biểu tượng động" ELF, là biểu tượng sau.


3
Cảm ơn bạn! Điều này giải thích tại sao đôi khi "nm" không hiển thị bất kỳ ký hiệu nào cho các tệp .so.
Brooks Moses

10
nm -D - cho phép bạn liệt kê bảng biểu tượng động
pt123

19

Đối với .socác tệp C ++ , nmlệnh cuối cùng là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)

nguồn: https://stackoverflow.com/a/43257338


11

Hãy thử thêm -l vào các cờ nm để lấy nguồn của mỗi ký hiệu. Nếu thư viện được biên dịch với thông tin gỡ lỗi (gcc -g) thì đây sẽ là tệp nguồn và số dòng. Như Konrad đã nói, tại thời điểm này, tệp đối tượng / thư viện tĩnh có thể chưa được biết.


11

Đối với Android .sofile, chuỗi công cụ NDK đi kèm với các công cụ cần thiết được đề cập trong câu trả lời khác: readelf, objdumpnm.


9

Bạn có thể sử dụng nm -gcông cụ từ chuỗi công cụ binutils. Tuy nhiên, nguồn của họ không phải lúc nào cũng có sẵn. và tôi thực sự thậm chí không chắc chắn rằng thông tin này luôn có thể được lấy. Có lẽobjcopy tiết lộ thêm thông tin.

/ EDIT: Tên của công cụ là tất nhiên nm. Cờ -gđược sử dụng để chỉ hiển thị các biểu tượng xuất khẩu.


6

nm -g liệt kê biến extern, không phải là biểu tượng xuất khẩu cần thiết. Bất kỳ biến phạm vi tệp không tĩnh (trong C) đều là biến ngoài.

nm -D sẽ liệt kê biểu tượng trong bảng động mà bạn có thể tìm thấy địa chỉ của nó bằng dlsym.

bước sóng

GNU nm 2.17.50.0.6-12.el5 20061020


1

Nếu bạn chỉ muốn biết nếu có là biểu tượng trình bày , bạn có thể sử dụng

objdump -h /path/to/object

hoặc để liệt kê thông tin gỡ lỗi

objdump -g /path/to/object
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.