This is the mail archive of the mailing list for the glibc 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: gold vs libc

> Have we identified a fix?

I had to re-read the old discussion to come back up to speed on the
details.  See
for the full old thread (Ian's last message is in the April archive and so
doesn't get included in the thread link chain from there).  (Just to make
this revival of the thread a bit more self-contained so people don't have
to find all the old bits I did, I'll note here that is a report of this
same issue.)  In
I said:

    IMHO it would be acceptable to simply disable .eh_frame optimization when
    there are any symbols in input .eh_frame sections that will survive to
    affect the output of anything except the .eh_frame output section's
    contents.  (That tortured wording is to distinguish __EH_FRAME_BEGIN__,
    whose value is used by relocs in other sections like .text, from the
    various .L* symbols used within individual input sections that are only
    used in arithmetic producing values inside the section.)  What's not
    acceptable is breaking the core semantics of linking that would apply if
    nobody had ever thought of .eh_frame optimization.

and also, in response to the cited suggestion from Ian:

    > The current code has a simple algorithm that usually produces the
    > result we want: we simply copy .eh_frame sections until we find one we
    > can optimize.  Perhaps we could change to a different algorithm: put
    > all unoptimized .eh_frame sections first, then all optimized .eh_frame
    > sections.

    In the concrete scenario, that would violate the abstract principles I
    described but would deliver an even better practical result.  The empty
    .eh_frame section (and its __EH_FRAME_BEGIN__ symbol) from crtbeginT.o
    count as "unoptimized", while the .eh_frame content from crt1.o could count
    as "optimized".  So it would place the emptiness and __EH_FRAME_BEGIN__
    first, and everything else (including crt1.o's contributions) after, even
    though crt1.o appears before crtbeginT.o in the link.

    I think either this or disabling the optimization entirely are acceptable
    resolutions to the bug.

I think that when Ian said, "we've identified a fix," he was referring to,
"put all unoptimized .eh_frame sections first, then all optimized .eh_frame

> From my point of view, the proper fix is to reorder the crt files so that
> the __EH_FRAME_BEGIN__ symbol *precedes* any non-empty .eh_frame
> sections. Why is this not possible? Don't we all agree that it's silly to
> have the start symbol follow some actual content?

I think everyone agrees that putting crt1.o before crtbegin.o is
undesireable.  It's certainly possible to change that.  But it's one of
those nasty interactions between our loosely-coordinated components: it's
GCC (or another compiler driver) that both provides crtbegin.o and decides
on the link order; it's glibc (or another C library) that provides crt1.o
and decides whether it should or does contain CFI; it's the linker
(whichever one) that the compiler and libc together rely on to do The Right

AFAIK nothing prevents us from changing GCC.  But it will be years before
we can rely on people using a GCC so changed.  That's no reason to avoid
changing GCC so that (eventually) no other fixes or workarounds will be
required; but it is a key reason why "pass the buck to GCC" is not an
acceptable resolution to the situation today.

The fundamental mindset of my part of this conversation has been that Gold
is billed as a drop-in replacement for BFD ld and this is a situation in
which it does not fit that bill.  It might well be right to call this a
"bug-compatibility" situation and argue that Gold is more Right than BFD ld
is.  But that doesn't deliver a practical solution to the real problem.

> If you want to disable .eh_frame optimization in this case, what are
> the specific conditions under which we should not do it? When
> --eh-frame-hdr is not specified? When we're doing static linking? When
> we see a zero-length section with a symbol that comes after a
> non-zero-length section, but isn't an end bracket? (How should we tell
> the start bracket apart from the end bracket?) When we see a non-zero
> length section in a file named "crt1.o"? None of these strikes me as
> particularly elegant (or future-proof).

Of the things you listed above, off hand the only thing that seems
approximately sensible to me is not to optimize when not using
--eh-frame-hdr.  (The rationale there is that --eh-frame-hdr is an explicit
request for the linker to grok .eh_frame's format completely and produce
"optimal, semantically equivalent" results with the clear expectation that
PT_GNU_EH_FRAME will be the only means of bootstrapping access to the data.
Otherwise, the implicit expectation is that the linker just behave like a
linker and paste together input sections and their symbols in their input
order.)  The other predicates you listed are indeed too picayune and
fragile.  In March I suggested a predicate that I think is the closest to
"exactly right" for the general case of things like bracket symbols; that's
cited at the top of this message.  That might well be overly fragile as
well, and the notion that people really care about optimizing the space use
of .eh_frame at all when they aren't bothering to optimize its runtime
access cost seems dubious.

> If the .eh_frame data in crt1.o really does need to come before
> __EH_FRAME_BEGIN__, another thing you could do is simply make it so
> gold treats it as non-optimizable. Adding a null relocation to the
> first word of the section should do it; inserting a zero-length entry
> anywhere but the end would do it (if that doesn't have adverse affects
> elsewhere).

It doesn't need to and in fact it's undesireable that it do so.  That is
one reason in favor of Ian's suggestion: though it doesn't adhere to any
clear abstract principle I can see, as a pragmatic solution to the actual
case in point, it magically makes something even better in practice than
the status quo ante (ante as in before switching linkers) long before a fix
for the underlying wrongness (in GCC's link order) will be available.
OTOH, it certainly seems like it has more risk of unintended consequences
we aren't now able to predict than does simply disabling optimization.

Incidentally, Ian mentioned Gold having had a special case for the
__EH_FRAME_BEGIN__ symbol.  But 'git log -G__EH_FRAME_BEGIN -- gold' finds
no point in the history where Gold's source code mentioned that symbol.  Do
you know what Ian was referring to?  From

    I freely grant that GCC's crtbegin.o file tries this trick in a number
    of different ways--even worse, crtend.o has trailing symbols.  Because
    of this existing behaviour, gold has various special cases to make it
    continue to work.  One of those special cases is for
    __EH_FRAME_BEGIN__.  As you've seen, the existing special case does
    not work any more.  This is an unfortunate interaction.  I don't think
    it's an obvious bug.

In that vein, there is Rafael's suggestion:

> Since the problem comes from an optimizations that knows what
> .eh_frame is, maybe it could learn that __EH_FRAME_BEGIN__ and
> __EH_FRAME_END__ are special symbols marking the start and end of the
> section?

I think that would be acceptable too.  It would have the same benefits of
"magically fixing" the crt1/crtbegin ordering snafu, but it seems much
simpler and thus it seems that predicting possible downsides would be
easier (I haven't thought of any).

I've said a lot in this thread about abstract principles for how a linker
should behave and how those boil down for Gold in this case, and as to
abstraction and principles I stick by everything I've said so far.  But the
bottom line is that from the glibc perspective, we'll be happy with any
solution that makes Gold deliver results as usable or more usable than BFD
ld's results for the scenario we know about without depending on GCC to
change the link order.


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