blueszhangsh / gperftools

Automatically exported from code.google.com/p/gperftools
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

1.2 has problem linking in both libprofiler.a and libtcmalloc.a statically #129

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
In 1.1, linking both statically worked great but now there's dozens of
duplicate symbols coming from the .o's that the two libraries share. 

How we're linking:
  g++ -o foo foo.a DIR/libprofiler.a DIR/libtcmalloc.a DIR/libunwind.a

Example error messages (just a subset):

-----------------------
/libtcmalloc.a(.text+0x172b0): In function
`ProcMapsIterator::NextExt(unsigned long*, unsigned long*, char**, unsigned
long*, long*, char**, unsigned long*, unsigned long*, unsigned long*,
unsigned long*, unsigned long*)':
src/base/sysinfo.cc:544: multiple definition of
`ProcMapsIterator::NextExt(unsigned long*, unsigned long*, char**, unsigned
long*, long*, char**, unsigned long*, unsigned long*, unsigned long*,
unsigned long*, unsigned long*)'
/libprofiler.a(.text+0x45c0):src/base/sysinfo.cc:544: first defined here
/libtcmalloc.a(.text+0x182a0): In function `AnnotateCondVarWait':
src/base/dynamic_annotations.cc:49: multiple definition of
`AnnotateCondVarWait'
/libprofiler.a(.text+0x55b0):src/base/dynamic_annotations.cc:49: first
defined here
/libtcmalloc.a(.text+0x17210): In function
`ProcMapsIterator::ProcMapsIterator(int, ProcMapsIterator::Buffer*)':
src/base/sysinfo.cc:440: multiple definition of
`ProcMapsIterator::ProcMapsIterator(int, ProcMapsIterator::Buffer*)'
/libprofiler.a(.text+0x4520):src/base/sysinfo.cc:440: first defined here
/libtcmalloc.a(.text+0x18290): In function `AnnotateRWLockReleased':
src/base/dynamic_annotations.cc:46: multiple definition of
`AnnotateRWLockReleased'
/libprofiler.a(.text+0x55a0):src/base/dynamic_annotations.cc:46: first
defined here
/libtcmalloc.a(.text+0x18280): In function `AnnotateRWLockAcquired':
src/base/dynamic_annotations.cc:44: multiple definition of
`AnnotateRWLockAcquired'
/libprofiler.a(.text+0x5590):src/base/dynamic_annotations.cc:44: first
defined here
/libtcmalloc.a(.text+0x164c0): In function
`base::VDSOSupport::SymbolIterator::SymbolIterator(void const*, int)':
src/base/vdso_support.cc:415: multiple definition of
`base::VDSOSupport::SymbolIterator::SymbolIterator(void const*, int)'
/libprofiler.a(.text+0x37d0):src/base/vdso_support.cc:415: first defined here
--------------

Reproducible case:

--
main.cc
--
#include "profiler.h"
#include "heap-profiler.h"

int main() {
  ProfilerFlush();
  HeapProfilerStop();
  GetHeapProfile();
}

--
Makefile
--
DIR1=/home/engshare/fbcode/external/gperftools/google-perftools-1.2-libunwind-0.
99/
DIR2=/home/engshare/fbcode/external/gperftools/google-perftools-1.1-libunwind-0.
99/
UNW_DIR=/home/engshare/fbcode/external/libunwind/libunwind-0.99/

.PHONY: clean
clean:
    rm -f main1 main2

main1: main.cc
    g++ -o main1 -I$(DIR1) main.cc \
    $(DIR1)/libprofiler.a \
    $(DIR1)/libtcmalloc.a \
    $(UNW_DIR)/libunwind.a

main2: main.cc
    g++ -o main2 -I$(DIR2) main.cc \
    $(DIR2)/libprofiler.a \
    $(DIR2)/libtcmalloc.a \
    $(UNW_DIR)/libunwind.a

----------
$ make main2  # works
$ make main1  # errors

Original issue reported on code.google.com by mrab...@gmail.com on 12 May 2009 at 3:47

GoogleCodeExporter commented 9 years ago
} In 1.1, linking both statically worked great

Well, it "worked" in that it didn't give any errors, but if I understand right, 
the
profiler didn't actually get linked in.  (See
http://groups.google.com/group/google-perftools/browse_thread/thread/1ff9b500430
90d9d/21e43120107d6494?lnk=gst&q=static#21e43120107d6494)
 This is probably why you didn't get any multiple-defined-symbols errors.

I'll ask the linker experts around here if there's any way to resolve this.

Original comment by csilv...@gmail.com on 12 May 2009 at 4:09

GoogleCodeExporter commented 9 years ago
What was the reason for switching to 'ld -r' instead of just 'ar' to put the 
.o's
together in 1.2?  Is there a way to add a ./configure option, perhaps, to link
differently?

Original comment by mrab...@gmail.com on 12 May 2009 at 11:44

GoogleCodeExporter commented 9 years ago
The reason to move from ar to 'ld -r' is for the reason I had mentioned 
earlier: with
ar, the resulting .a files would ignore HEAP_CHECK and HEAPPROFILE and 
CPUPROFILE. 
With 'ld -r', it respects those.  So I think the 'ld -r' solution is a strict
improvement.  That said, if you don't need it for you needs, feel free to edit 
the
Makefile to go back to 'ar'.  In fact, all you should need to do is to comment 
out
the actions for libtcmalloc.o and libprofiler.o, so they're no-ops.

I believe there is a way to keep 'ld -r' but resolve the problem you're having 
with
linking in both .a's -- though this is more a matter of faith than anything, 
since I
haven't found it yet. :-)  But I still expect to have that for the next release.

Original comment by csilv...@gmail.com on 13 May 2009 at 1:17

GoogleCodeExporter commented 9 years ago
OK, I have the following proposed fix:

In the Makefile, look for the lines like this:
   cp -f "$@" .libs/libprofiler.a
   cp -f "$@" .libs/libtcmalloc.a

replace those lines with this:
   objcopy --weaken "$@" .libs/libprofiler.a
   objcopy --weaken "$@" .libs/libtcmalloc.a

You'll have to do a 'make clean' and 'make' to rebuild after that (actually, 
doing
'rm lib*.o && make' should work fine).

Let me know how that works for you.  I plan on using this solution (with a lot 
of
configure-time checking to go along with it!) for the next release.

Original comment by csilv...@gmail.com on 13 May 2009 at 3:38

GoogleCodeExporter commented 9 years ago
I ended up fixing this a different way: I now (as of perftools 1.3) have a 
library:
libtcmalloc_and_profiler.a, that you can use to link both in statically.  The 
stuff
with objcopy just turned out to be too fragile and difficult to use properly.

Original comment by csilv...@gmail.com on 10 Jun 2009 at 2:01