ऐसा मत करो; अपने कंपाइलर और लिंकर को अनुभागों में भरने दें क्योंकि वे फिट दिखाई देते हैं।
इसके बजाय, अपने कार्यों को उपयुक्त function attributes के साथ चिह्नित करें, ताकि संकलक और लिंकर उन्हें सही अनुभागों में रख सकें।
उदाहरण के लिए
,
static void before_main(void) __attribute__((constructor));
static void after_main(void) __attribute__((destructor));
static void before_main(void)
{
/* This is run before main() */
}
static void after_main(void)
{
/* This is run after main() returns (or exit() is called) */
}
तुम भी एक प्राथमिकता (जैसे कि, __attribute__((constructor (300)))
), 101 और 65535 सहित उनके बीच एक पूर्णांक प्रदान कर सकते हैं, पहले छोटे प्राथमिकता संख्या रन होने कार्यों के साथ।
ध्यान दें कि चित्रण के लिए, मैंने static
कार्यों को चिह्नित किया। यही है, फ़ंक्शन फ़ाइल स्कोप के बाहर दिखाई नहीं देंगे। कार्यों को स्वचालित रूप से कॉल करने के लिए प्रतीकों को निर्यात करने की आवश्यकता नहीं है।
परीक्षण के लिए, मैं बचत की सलाह देते हैं एक अलग फ़ाइल में निम्न, का कहना है कि tructor.c
:
#include <unistd.h>
#include <string.h>
#include <errno.h>
static int outfd = -1;
static void wrout(const char *const string)
{
if (string && *string && outfd != -1) {
const char *p = string;
const char *const q = string + strlen(string);
while (p < q) {
ssize_t n = write(outfd, p, (size_t)(q - p));
if (n > (ssize_t)0)
p += n;
else
if (n != (ssize_t)-1 || errno != EINTR)
break;
}
}
}
void before_main(void) __attribute__((constructor (101)));
void before_main(void)
{
int saved_errno = errno;
/* This is run before main() */
outfd = dup(STDERR_FILENO);
wrout("Before main()\n");
errno = saved_errno;
}
static void after_main(void) __attribute__((destructor (65535)));
static void after_main(void)
{
int saved_errno = errno;
/* This is run after main() returns (or exit() is called) */
wrout("After main()\n");
errno = saved_errno;
}
ताकि आप संकलन और किसी भी कार्यक्रम या लाइब्रेरी का हिस्सा के रूप में यह लिंक कर सकते हैं। इसे साझा लाइब्रेरी के रूप में संकलित करने के लिए, उदाहरण का उपयोग करें
gcc -Wall -Wextra -fPIC -shared tructor.c -Wl,-soname,libtructor.so -o libtructor.so
और आप
LD_PRELOAD=./libtructor.so some-command-or-binary
का उपयोग कर कार्यों errno
अपरिवर्तित रखने के किसी भी गतिशील रूप से जुड़े हुए आदेश या बाइनरी में लगाना कर सकते हैं, हालांकि यह व्यवहार में कोई फर्क नहीं करना चाहिए, और निम्न स्तर को write()
syscall का उपयोग संदेशों को मानक त्रुटि में आउटपुट करें। प्रारंभिक मानक त्रुटि को एक नए वर्णनकर्ता को डुप्लिकेट किया गया है, क्योंकि कई मामलों में, मानक वैश्विक स्वयं को अंतिम वैश्विक विनाशक से पहले बंद कर दिया जाता है - यहां हमारे विनाशक - चला जाता है।
(कुछ पागल बाइनरी, आम तौर पर सुरक्षा के प्रति संवेदनशील हैं, करीब सभी वर्णनकर्ता वे के बारे में पता नहीं है, तो आप नहीं सभी मामलों में After main()
संदेश दिखाई दे सकता।)
यह अजीब है ... अपने पहले प्रश्न के बारे में - मेरे GDB पता चलता है कि init समारोह बिल्कुल नहीं चलता है। – MByD
यह काफी संभव है कि यूनिट सेक्शन मानक लाइब्रेरी से पहले चलता है जो काम करने के लिए पर्याप्त प्रारंभ होता है। यूनिट फ़ंक्शन वास्तव में चल रहा है या नहीं, यह देखने के लिए कि आप ग्लोबल वैरिएबल सेट करने की तरह किसी निर्भरता के साथ कुछ क्यों नहीं करते हैं। –