This is the mail archive of the mailing list for the binutils project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: protected __start_section and __stop_section symbols

The suggestion in the stackoverflow thread to use a new pair of
regular symbols, each initialized to the values of the linker-provided
symbols, is, in my opinion, the best way to do what you want to do.

extern T __start_XXX[];
extern T __stop_XXX[];
T* start_XXX = __start_XXX;
T* stop_XXX = __stop_XXX;

Your shared library can provide the "default" values, with default
visibility on the regular symbols. The initialization forces the
linker to provide those symbols no matter what, and if they're
protected, the regular symbols will always refer to the local section
in the shared library.

If your main program also defines the same set of symbols, its copy of
start_XXX and stop_XXX will override the shared library's copy, and
will refer to the section in the main program.

I've always thought it was just asking for trouble when trying to
refer to linker-provided symbols across load modules, and this
discussion supports that point of view.


On Mon, Feb 5, 2018 at 6:03 PM, H.J. Lu <> wrote:
> On Mon, Feb 5, 2018 at 4:56 PM, Cimbali <> wrote:
>> Hi HJ Michael and Alan, and thanks for your replies.
>> On 05/02/18 22:28, H.J. Lu wrote:
>>> __start_XXX and __stop_XXX symbols are defined for section XXX within
>>> the executable or share objects.  You can create a shared object which
>>> contains section XXX to provide the default __start_XXX and __stop_XXX
>>> if they aren't defined in the executable.
>> Yes that's the behaviour I want, however it does *not* work anymore. The
>> shared object symbols do not act as "default", in the sense that the values
>> from the shared object are always used. Even when they are defined in the
>> executable.
>> Just to check that we mean the same thing, here's a simple test case:
>> ==> bar.c <==
>> #include <stdio.h>
>> typedef void (*fptr)();
>> void pre_init() { printf("OK -- run me from library constructor\n"); }
>> fptr section_fptrlist __attribute__((section("fptrlist"))) = (fptr)pre_init;
>> int main() { return 0; }
>> ==> foo.c <==
>> #include <stdio.h>
>> typedef void (*fptr)();
>> void dummy() { printf("NO -- I should be overriden by prog_function\n"); }
>> fptr section_fptrlist __attribute__((section("fptrlist"))) = (fptr)dummy;
>> extern fptr __start_fptrlist, __stop_fptrlist;
>> void __attribute__((constructor)) setup()
>> {
>>     // setup library: try to call pre_init()
>>     for (fptr *f = &__start_fptrlist; f != &__stop_fptrlist; f++)
>>         (*f)();
>> }
>> $ gcc -g -O0    -fPIC -shared foo.c -o
>> $ gcc -g -O0    bar.c -L. -lfoo -o linked
>> $ LD_LIBRARY_PATH=. ./linked
>> NO -- I should be overriden by prog_function
>> Until commit cbd0eecf2, running this code resulted in "OK -- run me from
>> library constructor".
> This is not what I meant.  The shared object, which provide sthe default
> __start_XXX and __stop_XXX, shouldn't care which __start_XXX and
> __stop_XXX are used inside itself.  If you don't have one, you can add one.
> Or you can use weak symbols to reference __start_XXX and __stop_XXX
> in the executable.
> --
> H.J.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]