2012-03-25 10 views
6

के साथ काम नहीं करता है। मैं परीक्षण कर रहा हूं- इन दिनों उबंटू पर g ++ साझा ऑब्जेक्ट (.so) फ़ाइलों के साथ फ़िनस्ट्रुमेंट-फ़ंक्शन। मुझे एक अजीब व्यवहार मिला कि -फिनस्ट्रुमेंट-फ़ंक्शंस केवल तभी काम करता है जब लाइब्रेरी स्थिर रूप से जुड़ी हो। यदि मैं लाइब्रेरी से dlopen/dlsym आदि से लिंक करता हूं, तो कोड की कार्यक्षमता अभी भी काम करती है, लेकिन यह __cyg_profile * फ़ंक्शंस को कॉल नहीं करेगी।-finstrument-functions गतिशील रूप से लोड किए गए g ++ साझा ऑब्जेक्ट्स (.so)

MyLib.h

#ifndef __MYLIB_H__ 
#define __MYLIB_H__ 
class MyLib 
{ 
public: 
    void sayHello(); 
}; 
#endif 

MyLib.cpp

#include "MyLib.h" 
#include <iostream> 
using namespace std; 

void MyLib::sayHello() 
{ 
    cout<<"Hello"<<endl; 
} 

MyLibStub.cpp (.so सी इंटरफेस)

:

यहाँ कुछ कोड जल्दी से समस्या पुन: पेश करने हैं

#include "MyLib.h" 

extern "C" void LoadMyLib() 
{ 
    MyLib().sayHello(); 
} 

Trace.cpp

#include <stdio.h> 
#ifdef __cplusplus 
extern "C" 
{ 
    void __cyg_profile_func_enter(void *this_fn, void *call_site) 
     __attribute__((no_instrument_function)); 
    void __cyg_profile_func_exit(void *this_fn, void *call_site) 
     __attribute__((no_instrument_function)); 
} 
#endif 

void __cyg_profile_func_enter(void* this_fn, void* call_site) 
{ 
    printf("entering %p\n", (int*)this_fn); 
} 

void __cyg_profile_func_exit(void* this_fn, void* call_site) 
{ 
    printf("exiting %p\n", (int*)this_fn); 
} 

MainStatic.cpp

#include <iostream> 
using namespace std; 

extern "C" void LoadMyLib(); 

int main() 
{ 
    LoadMyLib(); 
    return 0; 
} 

MainDynamic.cpp

#include <iostream> 
#include <dlfcn.h> 

const char* pszLibName = "libMyLib.so.0.0"; 
const char* pszFuncName = "LoadMyLib"; 

int main() 
{ 
    void* pLibHandle = dlopen(pszLibName, RTLD_NOW); 
    if(!pLibHandle) { 
     return 1; 
    } 
    void (*pFuncLoad)() = 0; 
    //Resolve the function in MyLibStub.cpp 
    pFuncLoad = (void (*)())dlsym(pLibHandle, pszFuncName); 
    if(!pFuncLoad) { 
     return 1; 
    } 
    pFuncLoad(); 
    dlclose(pLibHandle); 
    return 0; 
} 

और निम्न कमांड (उबंटू 11.10 से कम) के साथ संकलन:

g++ -g -finstrument-functions -Wall -Wl,-soname,libMyLib.so.0 -shared -fPIC -rdynamic MyLib.cpp MyLibStub.cpp Trace.cpp -o libMyLib.so.0.0 
ln -s libMyLib.so.0.0 libMyLib.so.0 
ln -s libMyLib.so.0.0 libMyLib.so 
g++ MainStatic.cpp -g -Wall -lMyLib -L./ -o MainStatic 
g++ MainDynamic.cpp -g -Wall -ldl -o MainDynamic 

जब ./MainStatic

साथ कहा जाता है यह की तरह कुछ देता है:

entering 0xb777693f 
entering 0xb777689b 
exiting 0xb777689b 
exiting 0xb777693f 
entering 0xb7776998 
entering 0xb777680c 
Hello 
exiting 0xb777680c 
exiting 0xb7776998 

तथापि, जब ./MainDynamic

साथ कहा जाता है कि यह केवल देता है एक "हैलो"।

Hello 

किसी को भी यहाँ पता है क्यों स्थिर और गतिशील रूप से जुड़ा हुआ पुस्तकालयों के बीच इस तरह का अंतर है? क्या गतिशील रूप से लोड होने पर भी इसे काम करने का कोई समाधान है? अग्रिम में धन्यवाद।

+0

क्या आपके पास इसके लिए कोई सुझाव है: http://stackoverflow.com/questions/36910918/how-to-compile-a-cpp-and-then-link-it-to-a-shared-library – cross

उत्तर

4

यह व्यवहार अपेक्षित है।

इसे समझने के लिए, आपको सबसे पहले यह जानने की आवश्यकता है कि डायनामिक लोडर एक लिंक्ड सूची का उपयोग करके प्रतीकों की खोज करता है, ताकि विभिन्न ELF छवियों को लोड किया जा सके। उस सूची के प्रमुख पर मुख्य निष्पादन योग्य होता है, इसके बाद सभी पुस्तकालय सीधे इसके साथ जुड़े होते हैं। जब आप dlopen() कुछ लाइब्रेरी करते हैं, तो यह सूची के पूंछ में संलग्न हो जाता है।

तो जब लाइब्रेरी में कोड आपने अभी लोड किया है __cyg_profile_func_enter, लोडर उस फ़ंक्शन की पहली परिभाषा के लिए सूची की खोज करता है। Libc.so द्वारा प्रदान की गई पहली परिभाषा डिफ़ॉल्ट है।6, जो सूची के अंत के पास है, लेकिन अपने dlopen() एड पुस्तकालय से पहले है।

आप चलाकर इस सब का निरीक्षण कर सकते हैं:

LD_DEBUG=symbols,bindings ./MainDynamic 

और उत्पादन में __cyg_profile_func_enter की तलाश में।

तो, क्या आप अपने उपकरण को देखने के लिए मुझे क्या करना होगा? आप libc.so.6 से अपने एक स्वयं __cyg_profile_func_enter कहीं से पहले प्राप्त करने के लिए है। एक तरीका यह है कि ऐसा करने के लिए अपने मुख्य निष्पादन में लिंक करने के लिए है। या यह एक साझा पुस्तकालय है कि सीधे (अर्थात नहींdlopen() घ एक) अपने निष्पादन से जुड़ा हुआ में जोड़ देते हैं।

एक बार जब आप ऐसा करते हैं, अपने कार्यान्वयन सूची में पहले से एक हो जाएगा, और यह libc.so.6 में एक का दिल जीत जाएगा, और आप उत्पादन उत्पन्न देखेंगे।

+0

इस के लिए किसी भी समाधान: http://stackoverflow.com/questions/36910918/how-to-compile-a-cpp-and-then-link-it-to-a-shared-library और इस: http: // stackoverflow .com/प्रश्न/36896140/कालानुक्रमिक का पता लगाने के-समारोह-कॉल-इन-सी का उपयोग कर-etrace – cross

संबंधित मुद्दे