gold: Something special about malloc/calloc/realloc/free symbols?

Florian Weimer fweimer@redhat.com
Thu Jan 12 13:22:00 GMT 2017


On 01/10/2017 10:44 PM, Paul Smith wrote:
> Thanks for the reply Florian!
>
> On Tue, 2017-01-10 at 12:40 +0100, Florian Weimer wrote:
>> On 01/08/2017 06:31 AM, Paul Smith wrote:
>>>
>>> Hi all.  I have a weird situation and I don't know what to try
>>> next.
>>
>> You also need to export _IO_stdin_used if it is defined by
>> libc_nonshared.a.  I have not yet found a good way to clean this up
>> on the glibc side.
>
> I'm not familiar with that, but I looked at my libc_nonshared.a (from
> GNU C Library 2.12 on Red Hat Enterprise Linux 6.3) and that symbol is
> not present (according to nm) so I guess it's not an issue for me.

Sorry, I misremembered.  As Andreas pointed out, the symbol is in fact 
defined by the startup code.

> FYI, Here's my link line:
>
> g++ -fPIC -fvisibility=hidden -fno-omit-frame-pointer -std=c++14 \
>   -z noexecstack -Wl,--version-script=my-script -Wl,symbolic-functions \
>   -pthread -static-libgcc -static-libstdc++ -g -shared \
>   -Wl,-soname,libfoo.so -o libfoo.so foo.o ... ../util/libutil.a ... \
>   -latomic -lrt -lnsl -lm -ldl -Wl,-rpath,'$ORIGIN/../lib64'
>
> The elided bits are more .o files and more .a files all for my
> code.  One of the .a files is my memory manager replacement (I'm using
> jemalloc).

g++ will call the linker with additional arguments (just to be clear).

>>> It all works great, except for one thing.  In my shared library I'm also
>>> linking a memory management library (linked as a .a) which replaces all
>>> the standard memory functions: malloc, calloc, realloc, free.  I don't
>>> want these to be published by my .so because I want only my library to
>>> be able to access them, not a program that links my library.
>>
>> This happens automatically to enable symbol interposition.
>
> So, you're saying that ld is hardcoded to always mark those four
> symbols as global, if they're defined, regardless of what the linker
> script may say?

No, ld links against -lc (in the form of the libc.so script) and notices 
that the shared object which is being created intends to interpose 
malloc/free/… because both the object being created and libc.so.6 
(referenced from libc.so) define these symbols.  To enable that, the 
symbols are automatically exported.  There is nothing magic about the 
symbols themselves, it's just how ELF interposition works.

I don't know if there is a way to disable this from the version script 
directly, or if there is some other linker script/ld feature to achieve 
this more directly.

>> The best way to deal with this is to rename the allocator functions in
>> the source code.  If that's not possible, maybe you can use a partial
>> link (ld -r) with --wrap or some other ld functionality which renames
>> the symbols.
>
> Unfortunately renaming the allocator is problematic because it means I
> have to recompile all the third party code and force it to use my
> allocator functions instead of malloc (I have the source, but most of
> these libraries don't have any facility to allow use of a different
> allocator function).
>
> I didn't understand the need for using -r / partial link?

My idea (again, no binutils expert) is to do a partial link first, to 
get rid of the malloc/free/… symbols by renaming them, and then link 
against -lc in the final link only.  This way, no interposition happens, 
and the symbols are not exported.

> As for --wrap... are you saying that if I arrange for my replacement
> allocator to define __wrap_malloc() (etc.) rather than malloc(), then
> link with --wrap=malloc, all "malloc" calls in my code will be remapped
> to __wrap_malloc(), which can be localized?

Yes, that's what I would expect.

Thanks,
Florian




More information about the Binutils mailing list