[PATCH] elf: Hide DT_INIT and DT_FINI functions

H.J. Lu hjl.tools@gmail.com
Sat Sep 12 02:07:11 GMT 2026


On Sat, Sep 12, 2026 at 9:50 AM Matt Rice <ratmice@gmail.com> wrote:
>
> On Fri, Sep 11, 2026 at 5:16 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Sat, Sep 12, 2026 at 7:59 AM Matt Rice <ratmice@gmail.com> wrote:
> > >
> > >
> > >
> > > On Fri, Sep 11, 2026, 4:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >>
> > >> On Sat, Sep 12, 2026 at 7:34 AM Matt Rice <ratmice@gmail.com> wrote:
> > >> >
> > >> > On Fri, Sep 11, 2026 at 3:55 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >> > >
> > >> > > On Fri, Sep 11, 2026 at 8:10 PM Jan Beulich <jbeulich@suse.com> wrote:
> > >> > > >
> > >> > > > On 11.09.2026 14:04, H.J. Lu wrote:
> > >> > > > > On Fri, Sep 11, 2026 at 7:53 PM Jan Beulich <jbeulich@suse.com> wrote:
> > >> > > > >>
> > >> > > > >> On 11.09.2026 13:45, H.J. Lu wrote:
> > >> > > > >>> On Fri, Sep 11, 2026 at 5:45 PM Jan Beulich <jbeulich@suse.com> wrote:
> > >> > > > >>>>
> > >> > > > >>>> On 11.09.2026 10:32, H.J. Lu wrote:
> > >> > > > >>>>> On Fri, Sep 11, 2026 at 4:10 PM Jan Beulich <jbeulich@suse.com> wrote:
> > >> > > > >>>>>>
> > >> > > > >>>>>> On 11.09.2026 09:56, H.J. Lu wrote:
> > >> > > > >>>>>>> On Fri, Sep 11, 2026 at 2:31 PM Jan Beulich <jbeulich@suse.com> wrote:
> > >> > > > >>>>>>>>
> > >> > > > >>>>>>>> On 11.09.2026 08:23, H.J. Lu wrote:
> > >> > > > >>>>>>>>> On Fri, Sep 11, 2026 at 2:16 PM Jan Beulich <jbeulich@suse.com> wrote:
> > >> > > > >>>>>>>>>>
> > >> > > > >>>>>>>>>> On 11.09.2026 00:29, H.J. Lu wrote:
> > >> > > > >>>>>>>>>>> Hide special functions used by linker to define DT_INIT and DT_FINI in
> > >> > > > >>>>>>>>>>> executable and shared library so that they won't be in dynamic symbol
> > >> > > > >>>>>>>>>>> table.
> > >> > > > >>>>>>>>>>
> > >> > > > >>>>>>>>>> I still don't quite understand: In reply to my comment on the original,
> > >> > > > >>>>>>>>>> combined patch you said the symbols are hidden. Hidden symbols shouldn't
> > >> > > > >>>>>>>>>
> > >> > > > >>>>>>>>> I said they are hidden in glibc.
> > >> > > > >>>>>>>>
> > >> > > > >>>>>>>> Specifically you said "from crti.o in glibc". crti.o is part of what is
> > >> > > > >>>>>>>> being linked, so the two symbols being marked hidden there should prevent
> > >> > > > >>>>>>>> them from making it into the dynamic symbol table. There must hence be a
> > >> > > > >>>>>>>> missing piece.
> > >> > > > >>>>>>>
> > >> > > > >>>>>>> See:
> > >> > > > >>>>>>>
> > >> > > > >>>>>>> https://sourceware.org/bugzilla/show_bug.cgi?id=34623
> > >> > > > >>>>>>
> > >> > > > >>>>>> Adds to the confusion. There you supplied crt.s which doesn't mark the two
> > >> > > > >>>>>> symbols hidden. Whereas in said earlier reply you had
> > >> > > > >>>>>>
> > >> > > > >>>>>>      5: 0000000000000000     0 FUNC    GLOBAL HIDDEN     5 _init
> > >> > > > >>>>>>      6: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
> > >> > > > >>>>>>      7: 0000000000000000     0 FUNC    GLOBAL HIDDEN     7 _fini
> > >> > > > >>>>>>
> > >> > > > >>>>>> How does that fit together? Is what you committed (imo prematurely, despite
> > >> > > > >>>>>> Alan having given his okay) merely working around a source bug then? I think
> > >> > > > >>>>>> this wants reverting, and if it indeed turns out to be needed, it should be
> > >> > > > >>>>>> put back in with a description properly explaining under what conditions
> > >> > > > >>>>>> this adjustment (not mandated by the spec) is necessary. After all you
> > >> > > > >>>>>> override somebody's decision to deliberately have either of the symbols in
> > >> > > > >>>>>> the dynamic symbol table (for whatever good or bad reason).
> > >> > > > >>>>>
> > >> > > > >>>>> It can be a source code issue:
> > >> > > > >>>>>
> > >> > > > >>>>> https://sourceware.org/bugzilla/show_bug.cgi?id=23145
> > >> > > > >>>>> https://sourceware.org/bugzilla/show_bug.cgi?id=34585
> > >> > > > >>>>>
> > >> > > > >>>>> But when linker uses a function for DT_INIT,  that function shouldn't
> > >> > > > >>>>> be global, regardless of whether it is marked hidden.
> > >> > > > >>>>
> > >> > > > >>>> Says (repeating myself, sorry) which part of the spec? As said - people may
> > >> > > > >>>> want to play (good or bad) games, and we shouldn't keep them from doing so.
> > >> > > > >>>
> > >> > > > >>> Assign info->init_function:
> > >> > > > >>>
> > >> > > > >>>  /* The function to call when the executable or shared object is
> > >> > > > >>>      loaded.  */
> > >> > > > >>>   const char *init_function;
> > >> > > > >>>
> > >> > > > >>>   /* The function to call when the executable or shared object is
> > >> > > > >>>      unloaded.  */
> > >> > > > >>>   const char *fini_function;
> > >> > > > >>>
> > >> > > > >>> to DT_INIT is how GNU ld implements DT_INIT.   init_function is
> > >> > > > >>> local to an executable or shared object by definition.
> > >> > > > >>>
> > >> > > > >>> Please study how the C run-time library and ld work together yourself.
> > >> > > > >>
> > >> > > > >> You already admitted that adding .hidden to the source addresses the issue.
> > >> > > > >> You also admitted that nothing in the ELF spec supports the change. I fear
> > >> > > > >> I don't see at all what you want to tell me with this newest reply. Again:
> > >> > > > >> Please revert. If then you still think the change itself is a good one,
> > >> > > > >> re-submit with a much better justification.
> > >> > > > >
> > >> > > > > ELF spec doesn't deal with implementation details.   Mapping _init/_fini to
> > >> > > > > DT_INIT and DT_FINI is a linker implementation detail.
> > >> > > >
> > >> > > > Maybe, yet that still has no effect on the respective symbols' properties.
> > >> > > >
> > >> > > > > On what basis do you think you are right and others are wrong?
> > >> > > >
> > >> > > > On the basis that the ELF spec is sufficient here to describe rules on symbol
> > >> > > > visibility.
> > >> > > >
> > >> > >
> > >> > > _init and _fini are the part of contract between the run-time and linker to
> > >> > > implement DT_INIT and DT_FINI.  They are out of scope of ELF spec.
> > >> > > They are local to the executable or shared object.   They shouldn't
> > >> > > be visible outside of the executable or shared object as shown:
> > >> > >
> > >> > > https://sourceware.org/bugzilla/show_bug.cgi?id=23145
> > >> > >
> > >> >
> > >> > What prevents this from being handled in glibc, by marking these
> > >> > symbols with hidden visibility
> > >> > rather than by handling these symbol names specially?
> > >>
> > >> They are handled specially by linker.  We just missed it in linker
> > >> in the first place.  Otherwise, we won't see
> > >>
> > >> https://sourceware.org/bugzilla/show_bug.cgi?id=23145
> > >>
> > >> at all.
> > >
> > >
> > > That kind of sidesteps my question, let me ask it slightly differently. Could this be changed in glibc by adding the visibility qualifiers there instead of adding more special cases told?
> > >
> > > If not why not?
> >
> > Were you implying that _init and _fini weren't special to linker?
>
> I wasn't implying anything, I was trying to understand why the fix for
> this problem
> must be made in the linker itself, and the strength of that argument.
>
> Whether this is a case of a) for some reason (which I don't
> understand) setting the symbol
> visibility as hidden in glibc is a non-starter and so it must be fixed in ld.
>
> or b) this could be fixed in glibc by setting the symbol visibility, but
> we can fix this in ld so it applies retroactively to an unpatched glibc,
> and further that the bug is so egregious that we should add a special
> case to ld.

I guess we have a different understanding of what "special case" means.
To me, DT_INIT and DT_FINI are special cases in linker.   My patch
doesn't add new special cases to linker.  It updates the existing special cases.

> The situation in the first case is a much stronger argument than the second.
>
>
> > But _init and _fini are special to run-time and linker.  They should be made
> > local when used to implement DT_INIT and DT_FINI.   Linker should
> > make them local so that a run-time implementation doesn't have to do it.
> > When linker didn't do it,  run-time had no choice:
> >
>
> The "so that a run-time implementation doesn't have to do it."
> leads me to believe that this is the second case correct?
>
> > commit 67c0579669ba1fc265d770252fab31babf887329
> > Author:     H.J. Lu <hjl.tools@gmail.com>
> > AuthorDate: Fri Jun 8 10:28:38 2018 -0700
> > Commit:     H.J. Lu <hjl.tools@gmail.com>
> > CommitDate: Fri Jun 8 10:28:52 2018 -0700
> >
> >     Mark _init and _fini as hidden [BZ #23145]
> >
> >     _init and _fini are special functions provided by glibc for linker to
> >     define DT_INIT and DT_FINI in executable and shared library.  They
> >     should never be put in dynamic symbol table.  This patch marks them as
> >     hidden to remove them from dynamic symbol table.
> >
> > If linker had made them local in the first place, we wouldn't
> > run into this glibc bug.   Linker change prevents another issue
> > of a different run-time library like the glibc bug.
> >
> > --
> > H.J.



-- 
H.J.


More information about the Binutils mailing list