Static linking of gperf cpu profiler.

805 views
Skip to first unread message

divy...@gmail.com

unread,
Oct 2, 2017, 7:49:14 PM10/2/17
to gperftools
Hello,

trying to use gperf cpu profiler to link static to a c++ program. have followed the instuction to link library  with the below command.

seeing this linker error, 

any help to know if gperf can be used with static linking.



g++ -std=c++11  -DWITHGPERFTOOLS  -g fork.cpp -o fork -L /usr/lib/ libtcmalloc_and_profiler.a




libtcmalloc_and_profiler.a(stacktrace.o): In function `GetStackTrace_libunwind(void**, int, int)':

../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:112: undefined reference to `_Ux86_64_getcontext'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:116: undefined reference to `_ULx86_64_init_local'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:120: undefined reference to `_ULx86_64_step'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:131: undefined reference to `_ULx86_64_get_reg'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:138: undefined reference to `_ULx86_64_step'
libtcmalloc_and_profiler.a(stacktrace.o): In function `GetStackFrames_libunwind(void**, int*, int, int)':
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:112: undefined reference to `_Ux86_64_getcontext'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:116: undefined reference to `_ULx86_64_init_local'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:120: undefined reference to `_ULx86_64_step'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:124: undefined reference to `_ULx86_64_get_reg'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:131: undefined reference to `_ULx86_64_get_reg'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:138: undefined reference to `_ULx86_64_step'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:143: undefined reference to `_ULx86_64_get_reg'
libtcmalloc_and_profiler.a(stacktrace.o): In function `GetStackTraceWithContext_libunwind(void**, int, int, void const*)':
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:112: undefined reference to `_Ux86_64_getcontext'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:116: undefined reference to `_ULx86_64_init_local'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:120: undefined reference to `_ULx86_64_step'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:131: undefined reference to `_ULx86_64_get_reg'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:138: undefined reference to `_ULx86_64_step'
libtcmalloc_and_profiler.a(stacktrace.o): In function `GetStackFramesWithContext_libunwind(void**, int*, int, int, void const*)':
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:112: undefined reference to `_Ux86_64_getcontext'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:116: undefined reference to `_ULx86_64_init_local'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:120: undefined reference to `_ULx86_64_step'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:124: undefined reference to `_ULx86_64_get_reg'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:131: undefined reference to `_ULx86_64_get_reg'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:138: undefined reference to `_ULx86_64_step'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/stacktrace_libunwind-inl.h:143: undefined reference to `_ULx86_64_get_reg'
libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-linuxthreads.o): In function `ListerThread':
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/base/linuxthreads.cc:272: undefined reference to `sem_wait'
libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-linuxthreads.o): In function `TCMalloc_ListAllProcessThreads':
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/base/linuxthreads.cc:625: undefined reference to `sem_init'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/base/linuxthreads.cc:643: undefined reference to `sem_post'
../cdl_perf/gperf/gperf_static/gperftools-2.6.1/src/base/linuxthreads.cc:669: undefined reference to `sem_destroy'

Yubin Ruan

unread,
Oct 3, 2017, 11:56:30 AM10/3/17
to divy...@gmail.com, gperftools
Errors about sem_* can be solved by linking with the "-pthread"
option. See sem_wait(3).

Yubin

Divya K

unread,
Oct 3, 2017, 1:00:34 PM10/3/17
to gperftools
Thanks Yubin.

could make some progress with the below command, but there seems to be a conflict with libunwind.a and libgcc_eh.a 

g++ -static -o fork fork.cpp -Wl,--eh-frame-hdr  -L../cdl_perf/gperf/gperf_static/build/ -L..//cdl_perf/gperf/libunwind/libunwind-1.1/build libprofiler.a libunwind.a -llzma -DWITHGPERFTOOLS -lpthread



/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_eh.a(unwind-dw2.o): In function `_Unwind_GetIP':
(.text+0x23e0): multiple definition of `_Unwind_GetIP'
libunwind.a(GetIP.o):/build/libunwind-VOtC4T/libunwind-1.1/src/unwind/GetIP.c:30: first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_eh.a(unwind-dw2.o): In function `_Unwind_Resume':
(.text+0x27f0): multiple definition of `_Unwind_Resume'
libunwind.a(Resume.o):/build/libunwind-VOtC4T/libunwind-1.1/src/unwind/Resume.c:30: first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_eh.a(unwind-dw2.o): In function `_Unwind_Backtrace':
(.text+0x29b0): multiple definition of `_Unwind_Backtrace'
libunwind.a(Backtrace.o):/build/libunwind-VOtC4T/libunwind-1.1/src/unwind/Backtrace.c:30: first defined here
collect2: error: ld returned 1 exit status

Yubin Ruan

unread,
Oct 4, 2017, 10:47:17 PM10/4/17
to Divya K, gperftools
2017-10-04 1:00 GMT+08:00 Divya K <divy...@gmail.com>:
> Thanks Yubin.
>
> could make some progress with the below command, but there seems to be a
> conflict with libunwind.a and libgcc_eh.a
>
> g++ -static -o fork fork.cpp -Wl,--eh-frame-hdr
> -L../cdl_perf/gperf/gperf_static/build/
> -L..//cdl_perf/gperf/libunwind/libunwind-1.1/build libprofiler.a libunwind.a
> -llzma -DWITHGPERFTOOLS -lpthread

Actually `-pthread', not `-lpthread', although they are similar, but
note that `-pthread' involves both compiler and linker, while
'-lpthread' involves only linker. For the differences, see:

https://groups.google.com/forum/#!topic/comp.programming.threads/NCEpG0EOCCY

Sorry for the late reply. I guess you have solved that issue? I would
be good if you can provide a simple demo(program) to illustrate your
problem better.

Yubin

Divya K

unread,
Oct 5, 2017, 6:56:52 PM10/5/17
to gperftools
Trying to link a fork based program statically with gperf libraries. Below is the code snippet.

include <stdio.h>
#include <unistd.h>

#ifdef WITHGPERFTOOLS
#include <gperftools/profiler.h>
#endif

void called_by_parent()
{
  unsigned long num = 200000;
  while ( num != 0)
  {
   printf(" parent::num is %lx \n", num);
   num = num -1;
  }
}

void called_by_child()
{
  unsigned long num = 200000;
  while ( num != 0)
  {
   printf(" child::num is %lx \n", num);
   num = num -1;
  }
}

int main(int argc, char **argv)
{
    printf("--beginning of program\n");

    int counter = 0;
    pid_t pid = fork();

    if (pid == 0)
    {
#ifdef WITHGPERFTOOLS
      ProfilerRegisterThread();
      ProfilerStart("child_profile.log");
#endif
        // child process
        int i = 0;
        for (; i < 5; ++i)
        {
            printf("child process: counter=%d\n", ++counter);
        }
        called_by_child();
#ifdef WITHGPERFTOOLS
    ProfilerStop();
#endif
    }
    else if (pid > 0)
    {
#ifdef WITHGPERFTOOLS
    ProfilerStart("parent_profile.log");
#endif

      // parent process
        int j = 0;
        for (; j < 5; ++j)
        {
            printf("parent process: counter=%d\n", ++counter);
        }
        called_by_parent();
#ifdef WITHGPERFTOOLS
    ProfilerStop();
#endif
    }
    else
    {
        // fork failed
        printf("fork() failed!\n");
        return 1;
    }

    printf("--end of program--\n");

    return 0;
}



On Monday, October 2, 2017 at 6:49:14 PM UTC-5, Divya K wrote:

Yubin Ruan

unread,
Oct 5, 2017, 9:30:07 PM10/5/17
to Divya K, gperftools
Hmm... I try to compile and link your snippet with
`libtcmalloc_and_profiler.a' and there is no problem. It turns out
that you are doing it wrong when linking your program. You are doing:

g++ -std=c++11 -DWITHGPERFTOOLS -g fork.cpp -o fork -L /usr/lib/
libtcmalloc_and_profiler.a

however you should do this instead:

g++ -std=c++11 -DWITHGPERFTOOLS -g fork.cpp -o fork
/path/to/libtcmalloc_and_profiler.a -pthread

"-pthread" is for those "sem_*" functions.

Yubin

Yubin Ruan

unread,
Oct 5, 2017, 9:32:28 PM10/5/17
to Divya K, gperftools
2017-10-06 9:30 GMT+08:00 Yubin Ruan <ablack...@gmail.com>:
> Hmm... I try to compile and link your snippet with
> `libtcmalloc_and_profiler.a' and there is no problem. It turns out
> that you are doing it wrong when linking your program. You are doing:
>
> g++ -std=c++11 -DWITHGPERFTOOLS -g fork.cpp -o fork -L /usr/lib/
> libtcmalloc_and_profiler.a
>
> however you should do this instead:
>
> g++ -std=c++11 -DWITHGPERFTOOLS -g fork.cpp -o fork
> /path/to/libtcmalloc_and_profiler.a -pthread

I am sorry that these lines got wrapped. it should be

Divya K

unread,
Oct 6, 2017, 12:10:39 PM10/6/17
to gperftools
Thanks Yubin.

Sorry i missed the "-static" option in command line .

without the static compiler  option this below command works as you specified.

 g++  -std=c++11  -DWITHGPERFTOOLS  -g fork.cpp -o fork  /usr/lib/libtcmalloc_and_profiler.a /usr/lib/x86_64-linux-gnu/libunwind.a  /usr/lib/x86_64-linux-gnu/liblzma.a -pthread

But here the binary fork is created with partial static and gcc libs are linked dynamically.

ldd fork
        linux-vdso.so.1 =>  (0x00007ffdbc8ae000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fb48b18e000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb48ae85000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb48ac67000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb48a89d000)
        /lib64/ld-linux-x86-64.so.2 (0x000055c855c72000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fb48a687000)


But when the "-static" option is added, to link all the libs statically the linking fails with multiple definitions of libunwind.a and libtcmalloc_and_profiler.a

The error message is copied below.

/usr/lib/gcc/x86_64-linux-gnu/5/libgcc_eh.a(unwind-dw2.o): In function `_Unwind_Resume':
(.text+0x27f0): multiple definition of `_Unwind_Resume'
/usr/lib/x86_64-linux-gnu/libunwind.a(Resume.o):/build/libunwind-VOtC4T/libunwind-1.1/src/unwind/Resume.c:30: first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(malloc.o): In function `__libc_malloc':
(.text+0x6bf0): multiple definition of `__libc_malloc'
/usr/lib/libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-tcmalloc.o):(google_malloc+0x0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(malloc.o): In function `__libc_malloc':
(.text+0x6bf0): multiple definition of `malloc'
/usr/lib/libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-tcmalloc.o):(google_malloc+0x0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(malloc.o): In function `__libc_free':
(.text+0x6f90): multiple definition of `__libc_free'
/usr/lib/libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-tcmalloc.o):(google_malloc+0x3e10): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(malloc.o): In function `__libc_free':
(.text+0x6f90): multiple definition of `free'
/usr/lib/libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-tcmalloc.o):(google_malloc+0x3e10): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(malloc.o): In function `__libc_realloc':
(.text+0x7150): multiple definition of `__libc_realloc'
/usr/lib/libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-tcmalloc.o):(google_malloc+0x7e0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(malloc.o): In function `__libc_realloc':
(.text+0x7150): multiple definition of `realloc'
/usr/lib/libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-tcmalloc.o):(google_malloc+0x7e0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(malloc.o): In function `__libc_memalign':
(.text+0x7530): multiple definition of `__libc_memalign'
/usr/lib/libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-tcmalloc.o):(google_malloc+0x3140): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(malloc.o): In function `__libc_calloc':
(.text+0x77a0): multiple definition of `__libc_calloc'
/usr/lib/libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-tcmalloc.o):(google_malloc+0x2970): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(malloc.o): In function `__libc_valloc':
(.text+0x8ff0): multiple definition of `__libc_valloc'
/usr/lib/libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-tcmalloc.o):(google_malloc+0x3250): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(malloc.o): In function `__libc_pvalloc':
(.text+0x9280): multiple definition of `__libc_pvalloc'
/usr/lib/libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-tcmalloc.o):(google_malloc+0x32e0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(malloc.o): In function `__posix_memalign':
(.text+0x9fa0): multiple definition of `__posix_memalign'
/usr/lib/libtcmalloc_and_profiler.a(libtcmalloc_and_profiler_la-tcmalloc.o):(google_malloc+0x31c0): first defined here
collect2: error: ld returned 1 exit status

Divya K

unread,
Oct 6, 2017, 12:19:00 PM10/6/17
to gperftools


On Friday, October 6, 2017 at 11:10:39 AM UTC-5, Divya K wrote:
Thanks Yubin.

Sorry i missed the "-static" option in command line .

without the static compiler  option this below command works as you specified.

 g++  -std=c++11  -DWITHGPERFTOOLS  -g fork.cpp -o fork  /usr/lib/libtcmalloc_and_profiler.a /usr/lib/x86_64-linux-gnu/libunwind.a  /usr/lib/x86_64-linux-gnu/liblzma.a -pthread

But here the binary fork is created with partial static and gcc libs are linked dynamically.

ldd fork
        linux-vdso.so.1 =>  (0x00007ffdbc8ae000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fb48b18e000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb48ae85000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb48ac67000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb48a89d000)
        /lib64/ld-linux-x86-64.so.2 (0x000055c855c72000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fb48a687000)


But when the "-static" option is added, to link all the libs statically the linking fails with multiple definitions of libunwind.a and libtcmalloc_and_profiler.a

g++ -static  -std=c++11  -DWITHGPERFTOOLS  -g fork.cpp -o fork  /usr/lib/libtcmalloc_and_profiler.a /usr/lib/x86_64-linux-gnu/libunwind.a  /usr/lib/x86_64-linux-gnu/liblzma.a -pthread

Yubin Ruan

unread,
Oct 6, 2017, 10:51:04 PM10/6/17
to Divya K, gperftools
2017-10-07 0:10 GMT+08:00 Divya K <divy...@gmail.com>:
> Thanks Yubin.
>
> Sorry i missed the "-static" option in command line .
>
> without the static compiler option this below command works as you
> specified.
>
> g++ -std=c++11 -DWITHGPERFTOOLS -g fork.cpp -o fork
> /usr/lib/libtcmalloc_and_profiler.a /usr/lib/x86_64-linux-gnu/libunwind.a
> /usr/lib/x86_64-linux-gnu/liblzma.a -pthread

Congratulation ;-)

> But here the binary fork is created with partial static and gcc libs are
> linked dynamically.
>
> ldd fork
> linux-vdso.so.1 => (0x00007ffdbc8ae000)
> libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
> (0x00007fb48b18e000)
> libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb48ae85000)
> libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0
> (0x00007fb48ac67000)
> libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb48a89d000)
> /lib64/ld-linux-x86-64.so.2 (0x000055c855c72000)
> libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1
> (0x00007fb48a687000)

This is reasonable, since libc.so may contain some other symbols
needed by your program.
Hmm...this is also reasonable, because statically linking two
libraries (libc.a and libunwind.a, etc) which contain the same symbol
will by definition lead to multiple-definition errors. So, I think the
only viable solution is the "partial statically-linking" that you
mention above).

And by the way, I would suggest never try to link libraries such as
`libpthread' statically, because libpthread comes with libc, and
therefore bad things will happen if the libc in your system get
changed (which leads to version mismatch and runtime crash). And also
you'd better not link libc statically...

Yubin
Reply all
Reply to author
Forward
0 new messages