How to compile a cpp and then link it to a shared library

后端 未结 1 1344
别跟我提以往
别跟我提以往 2020-12-22 12:04

I want to have the functions which are defined in another .cpp file become available in another simulation tool.

I found the following code in this ques

相关标签:
1条回答
  • 2020-12-22 12:30

    As @Flexo restates what @EmployedRussian said in the linked question, the main point is to get your implementation of __cyg_profile_func_*** before the one provided by libc.so.6.

    One method to do this, is to use the LD_PRELOAD environment variable. Here you can read what LD_PRELOAD does and how it works.

    To use the LD_PRELOAD trick you will need to compile your implementation of the above-mentioned functions as a shared library.

    You can do this by doing:

    g++ -shared -fPIC myImp.cc -o myImp.so -ldl
    

    Once you get the .so file, navigate to the directory where your executable is located and do:

    LD_PRELOAD=<path/to/myImp.so>- ./<myExecutable>
    

    For shared libraries, dynamic linking is used. Meaning:

    resolving of some undefined symbols (is postponed) until a program is run.

    By using LD_PRELOAD you resolve the symbols of your interest before letting the linked do that.


    Here you have an implementation of myImp.cc, which I took from: https://groups.google.com/forum/#!topic/gnu.gcc.help/a-hvguqe10I

    The current version lacks proper implementation for __cyg_profile_func_exit, and I have not been able to demangle the function names.

    #ifdef __cplusplus
    extern "C"
    {
    
            #include <stdio.h>
            #include <stdlib.h>
            #include <sys/types.h>
            #include <sys/stat.h>
            #include <unistd.h>
        #include <dlfcn.h>
    
    
            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
    static FILE *fp;
    int call_level=0;
    void * last_fn;
    void __cyg_profile_func_enter(void *this_fn, void *call_site)
    {
    
        Dl_info di; 
    
            if (fp == NULL) fp = fopen( "trace.txt", "w" );
            if (fp == NULL) exit(-1);
    
            if ( this_fn!=last_fn) ++call_level;
            for (int i=0;i<=call_level;i++) 
        {
            fprintf(fp,"\t");
        }
            //fprintf(fp,  "entering %p\n", (int *)this_fn);
            fprintf(fp,  "entering %p", (int *)this_fn);
            if (dladdr(this_fn, &di)) {
              fprintf(fp,  " %s (%s)", di.dli_sname ? di.dli_sname : "<unknown>", di.dli_fname);
            }
            fputs("\n", fp);
            (void)call_site;
            last_fn = this_fn;
    }
    
    void __cyg_profile_func_exit(void *this_fn, void *call_site)
    {
            --call_level;
            for (int i=0;i<=call_level;i++) fprintf(fp,"\t");
            fprintf(fp, "exiting %p\n", (int *)this_fn);
            (void)call_site;
    
    }
    

    Another option for function tracing which uses LD_PRELOAD is used by LTTng, in the section Function Tracing, but I have never used it...

    0 讨论(0)
提交回复
热议问题