How to compile a cpp and then link it to a shared library
Asked Answered
H

1

0

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 question: -finstrument-functions doesn't work with dynamically loaded g++ shared objects (.so)

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);
}

Trace.cpp is compiled by doing:

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

Note that I don't need: MyLib.cpp and MyLibStub.cpp.

Instead compiled Trace.cpp doing:

g++ -g -finstrument-functions -Wall -Wl,-soname,libMyLib.so.0 -shared -fPIC -rdynamic Trace.cpp -o libMyLib.so.0.0 

What I've tried:

The shared object where I want to have Trace.cpp is obtained by:

opp_makemake -f --deep --no-deep-includes --make-so -I . -o veins -O out -I../../inet/src/util/headerserializers/sctp/headers -L../../inet/src -linet 

I added -L and -l:

opp_makemake -f --deep --no-deep-includes --make-so -I . -o veins -L /home/user/Desktop/test/ -lMyLib -O out -I../../inet/src/util/headerserializers/sctp/headers -L../../inet/src -linet 

and got:

/usr/bin/ld: cannot find -lMyLib

I also tried:

opp_makemake -f --deep --no-deep-includes --make-so -I . -o veins /home/user/Desktop/test/libMyLib.so.0.0 -O out -I../../inet/src/util/headerserializers/sctp/headers -L../../inet/src -linet 

which compiled successfully but the application crashed:

Error during startup: Cannot load library '../../src//libveins.so': libMyLib.so.0: cannot open shared object file: No such file or directory.


Question:

  1. How to compile Trace.cpp correctly?
  2. How to link it with the rest of the shared library?

As you might notice I am not very experienced with compiling, linking and similar. So, any extra explanation is very welcome!

Halakah answered 28/4, 2016 at 9:45 Comment(2)
The answer to the question you asked in comments elsewhere is given in the questions you linked: "You have to get your own __cyg_profile_func_enter somewhere before the one from libc.so.6. One way to do that is to link it into your main executable. Or link it into a shared library that is directly linked to your executable (i.e. not dlopen()d one).". Other than that this question seems to be a generic "how do I link it?" which is covered by documentation on your chosen build tools.Senegal
hmm, ok.. that's what I am trying to figure out now. the tricky part is that the tool I am using generates makefiles using a scripts which in the end "merges" 3 simulation tools together... the final make is something like this: pastebin.com/EiXGiHbK ... so the real question is how do I put my implementation before the one from libc.so.6? :/Halakah
F
1

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...

Flavoring answered 30/4, 2016 at 20:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.