أحتاج إلى ربط برنامج C على كائن مشترك بدون رؤوس قسم
-
22-09-2019 - |
سؤال
لقد كتبت واجهة إلى مولد الرمز الذي يتيح لي إنتاج كائنات مشتركة. على الرغم من أنني لا أرغب في تنفيذ الدعم لجدول رأس القسم لأن هذا هو المكان الذي يبقى فيه تعقيد غالبية تنسيق ملف ELF.
يستخدم GNU LD رؤوس القسم للربط مع الكائنات المشتركة. هذا يعني أنه عندما أحاول وضع رابط GCC مع كائني المشترك بدون رؤوس قسم ، فسوف يفشل لأن LD لا يجد الرموز حتى لو كانت موجودة في المكتبة.
هل توجد بعض الخدعة التي يمكنني استخدامها لخداع المترجم لجعل الارتباط ينجح حتى لو لم يجد رموزًا معينة؟
إليك بعض التوضيح حول المشكلة:
cheery@ruttunen:~/Documents/g386$ gcc dev/shared_test.c -L. -lshared -m32
/tmp/cc6qBViY.o: In function `main':
shared_test.c:(.text+0xa): undefined reference to `example_function'
collect2: ld returned 1 exit status
cheery@ruttunen:~/Documents/g386$ cat dev/shared_test.c
// gcc shared_test.c -L. -lshared -m32
// LD_LIBRARY_PATH=. ./a.out
#include <stdio.h>
extern int example_function();
int main(){
printf("hello %d\n", example_function());
}
cheery@ruttunen:~/Documents/g386$ readelf -D -s libshared.so
Symbol table for image:
Num Buc: Value Size Type Bind Vis Ndx Name
2 0: 00800164 0 FUNC GLOBAL DEFAULT ABS example_function
1 0: 008000ac 0 OBJECT GLOBAL DEFAULT ABS _DYNAMIC
المحلول 2
أفضل نهج هنا هو إضافة جداول القسم المطلوبة بواسطة GCC. إذا كان لديك آلية ارتباط ديناميكية عاملة في مولدك ، فهذا يتطلب كل المعلومات نفسها مثل ما ستقدمه في جداول الأقسام.
من أجل الكسل ، كتبت ملف تجميع مشترك واستخدمه في الشريط للحصول على نقطة مرجعية. ´Readelf -يظهر المقاطعان قسمين لكنك لا تحتاج إلى كل شيء. عملت من خلال هذا وقمت بتنفيذ الأقسام بالترتيب حتى بدأت العمل بشكل صحيح. هذا ما اضطررت لإضافته:
cheery@ruttunen:~/Documents/g386$ readelf --sections dynamic_hello.app
There are 5 section headers, starting at offset 0x1b9:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .shstrndx STRTAB 00000000 000281 000024 00 0 0 1
[ 2] .dynamic DYNAMIC 00000000 0000b0 000050 08 WA 3 0 4
[ 3] .dynstr STRTAB 00000000 000158 000020 00 A 0 0 1
[ 4] .dynsym DYNSYM 00000000 000100 000040 10 A 3 0 4
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
لا يضر إذا وضعت أقسامًا أكثر من هذه ، ولكن هذا يكفي للحصول على ربط ديناميكي.
نصائح أخرى
لدى GCC (أي ، LD خلف GCC) خيار سطر الأوامر لتجاهل العوامل الخارجية التي لم يتم حلها. سوف تقمع رسالة الخطأ التي تحصل عليها من GCC. لست متأكدًا من أن هذا سيجعلك سعيدًا.