https://sourceware.org/bugzilla/show_bug.cgi?id=32816

--- Comment #6 from Aliaksey Kandratsenka <alkondratenko at gmail dot com> ---

Here is a placeholder for cpuprofiler.c:

#include <stdio.h>
#include <stdlib.h>

void ProfilerStart(const char* filename);

static __attribute__((constructor))
void startup(void)
{
        const char* v = getenv("CPUPROFILE");
        if (!v) return;
        ProfilerStart(v);
}

void ProfilerStart(const char* filename)
{
        printf("Starting with arg: %s!\n", filename);
}

and trivial "program" (program.c):

#include <stdio.h>

int main(void)
{
        printf("main!\n");
        return 0;
}

$ gcc -O2 -g -o prog program.c

Note how program doesn't really reference anything in libprofiler. So it runs
fine without it. We can also build libprofiler.so and LD_PRELOAD it with
expected result:

me@big:~/src/test/linker-require-defined$ gcc -O2 -g -shared -o
libcpuprofiler.so cpuprofiler.c
me@big:~/src/test/linker-require-defined$ gcc -O2 -g -o prog program.c
me@big:~/src/test/linker-require-defined$ LD_PRELOAD=./libcpuprofiler.so
CPUPROFILE=p ./prog 
Starting with arg: p!
main!

libcpuprofiler could also be linked into static library:

me@big:~/src/test/linker-require-defined$ gcc -O2 -g -c cpuprofiler.c 
me@big:~/src/test/linker-require-defined$ ar q libcpuprofiler.a cpuprofiler.o
ar: creating libcpuprofiler.a

But "linking" with -lcpuprofiler doesn't do anything, because there are no
usages (and my OS defaults to -as-needed for shared libraries).

me@big:~/src/test/linker-require-defined$ gcc -O2 -g -o prog program.c -L.
./libcpuprofiler.a
me@big:~/src/test/linker-require-defined$ CPUPROFILE=p ./prog 
main!
me@big:~/src/test/linker-require-defined$ gcc -O2 -g -o prog program.c -L.
-Wl,-rpath,$PWD ./libcpuprofiler.so 
me@big:~/src/test/linker-require-defined$ CPUPROFILE=p ./prog 
main!


No surprises so far.


But say we want to have libprofiler linked into the program, despite having no
direct references. libprofiler is useful for its constructor which can start
profiling etc. For that there are 2 distinct mechanisms that explicitly depend
on library type. --whole-archive for .a-s and -no-as-needed for .so.

And there is a third option. It is at least nominally isn't requiring a
specific library type. I am talking about -Wl,-uProfilerStart. I.e. telling
linker: hey even though this symbol is not pulled by anything, please link
whatever is needed for it.

Indeed, it works for static library:

me@big:~/src/test/linker-require-defined$ gcc -O2 -g -o prog program.c -L.
-Wl,-uProfilerStart ./libcpuprofiler.a
me@big:~/src/test/linker-require-defined$ CPUPROFILE=p ./prog 
Starting with arg: p!
main!

but not for shared:

me@big:~/src/test/linker-require-defined$ gcc -O2 -g -o prog program.c -L.
-Wl,-rpath,$PWD -Wl,-uProfilerStart ./libcpuprofiler.so 
me@big:~/src/test/linker-require-defined$ CPUPROFILE=p ./prog 
main!

to double check -no-as-needed works (but is .so-specific):

me@big:~/src/test/linker-require-defined$ gcc -O2 -g -o prog program.c -L.
-Wl,-rpath,$PWD -Wl,-no-as-needed ./libcpuprofiler.so 
me@big:~/src/test/linker-require-defined$ CPUPROFILE=p ./prog 
Starting with arg: p!
main!

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to