كيف أقوم بإدراج الرموز في ملف .so
-
09-06-2019 - |
سؤال
كيف أقوم بإدراج الرموز التي يتم تصديرها من ملف .so؟إذا أمكن، أود أيضًا معرفة مصدرهم (على سبيل المثال:إذا تم سحبها من مكتبة ثابتة).
أنا أستخدم gcc 4.0.2، إذا كان ذلك يحدث فرقًا.
المحلول
الأداة القياسية لإدراج الرموز هي nm
, ، يمكنك استخدامه ببساطة مثل هذا:
nm -g yourLib.so
إذا كنت تريد رؤية رموز مكتبة C++، أضف الخيار "-C" الذي يزيل تشابك الرموز (وهو أكثر قابلية للقراءة).
nm -gC 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
نصائح أخرى
إذا كان لديك .so
الملف بتنسيق elf، يمكنك استخدام برنامج readelf لاستخراج معلومات الرمز من الملف الثنائي.سيعطيك هذا الأمر جدول الرموز:
readelf -Ws /usr/lib/libexample.so
يجب عليك فقط استخراج تلك المحددة في هذا .so
الملف، وليس في المكتبات المشار إليها به.يجب أن يحتوي العمود السابع على رقم في هذه الحالة.يمكنك استخراجه باستخدام regex بسيط:
readelf -Ws /usr/lib/libstdc++.so.6 | grep '^\([[:space:]]\+[^[:space:]]\+\)\{6\}[[:space:]]\+[[:digit:]]\+'
أو كما اقترح كاسبين,:
readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}';
objdump -TC /usr/lib/libexample.so
بالنسبة للمكتبات المشتركة libNAME.so، كان مفتاح التبديل -D ضروريًا لرؤية الرموز في نظام Linux الخاص بي
nm -D libNAME.so
وللمكتبة الثابتة كما أفاد آخرون
nm -g libNAME.a
ظللت أتساءل لماذا -fvisibility=خفية و #pragma رؤية دول مجلس التعاون الخليجي لا يبدو أن لها أي تأثير، حيث كانت جميع الرموز مرئية دائمًا نانومتر - حتى وجدت هذا المنشور الذي دلني عليه readelf و com.objdump, مما جعلني أدرك أنه يبدو أن هناك بالفعل اثنين جداول الرموز:
- الشخص الذي يمكنك القائمة معه نانومتر
- الشخص الذي يمكنك القائمة معه readelf و com.objdump
أعتقد أن الأول يحتوي على رموز تصحيح يمكن تجريدها يجرد أو رمز التبديل -s الذي يمكنك منحه للرابط أو ثَبَّتَ يأمر.وحتى إذا لم يعد nm يُدرج أي شيء، فسيستمر تصدير الرموز المصدرة الخاصة بك لأنها موجودة في "جدول الرموز الديناميكي" الخاص بـ ELF، وهو الأخير.
حاول إضافة -l إلى إشارات nm للحصول على مصدر كل رمز.إذا تم تجميع المكتبة بمعلومات تصحيح الأخطاء (gcc -g)، فيجب أن يكون هذا هو الملف المصدر ورقم السطر.كما قال كونراد، ربما يكون ملف الكائن/المكتبة الثابتة غير معروف في هذه المرحلة.
لأجهزة الأندرويد .so
الملفات، تأتي سلسلة أدوات NDK مع الأدوات المطلوبة المذكورة في الإجابات الأخرى: readelf
, objdump
و nm
.
لسي ++ .so
الملفات، في نهاية المطاف nm
الأمر هو 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)
يمكنك استخدام ال nm -g
أداة من سلسلة أدوات binutils.ومع ذلك، فإن مصدرها ليس متاحًا دائمًا بسهولة.ولست متأكدًا في الواقع من إمكانية استرجاع هذه المعلومات دائمًا.ربما objcopy
يكشف المزيد من المعلومات.
/يحرر:اسم الاداة بالطبع nm
.العلم -g
يستخدم لإظهار الرموز المصدرة فقط.
nm -g يسرد المتغير الخارجي، وهو ليس رمزًا مُصدَّرًا ضروريًا.أي متغير نطاق ملف غير ثابت (في C) كلها متغيرات خارجية.
سوف يقوم nm -D بإدراج الرمز في الجدول الديناميكي، والذي يمكنك العثور على عنوانه عن طريق dlsym.
نانومتر - الإصدار
جنو نانومتر 2.17.50.0.6-12.el5 20061020
إذا كنت تريد فقط معرفة ما إذا كانت هناك رموز حاضر يمكنك استخدام
objdump -h /path/to/object
أو لسرد معلومات التصحيح
objdump -g /path/to/object