https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81033

--- Comment #37 from Iain Sandoe <iains at gcc dot gnu.org> ---
Created attachment 44446
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44446&action=edit
Proposed fix for trunk

Subject: [PATCH] Fix P81033 for FDEs in partitioned code.

Darwin has the ability to split code into "atoms" in the static linker.
These can then be re-ordered to optimise the code layout (this is a more
fine-grained equivalent of function-sections).

This facility requires cooperation of the compiler, assembler and linker.
As the assembly stage it's signalled by marking objects as
"subsections_vis_symbols" the (expected) default.

The rules for splitting code into atoms (if applied strictly) are like
this:

_linker_visible_labelA: << starts Atom A

(section start if there's no linker visible label before the first local
 one)

 ...

LocalLabelA:  <<== belongs to Atom A
 ...

LocalLableB: <<== belongs to Atom A

 ...

LocalLabelC: <<== belongs to Atom A
**Even if it has the same address as _linker_visible_labelB**

_linker_visible_labelB: << starts Atom B

LocalLabelD: <<== belongs to Atom B

=====

There are two assemblers in common use for Darwin; one based on an old
GAS version (so-called cctools) and one based on the LLVM toolchain.

Newer vendor toolchains are based by default on the LLVM toolchain, and
older ones on the cctools.

The cctools assembler is strict about the atom definitions, the LLVM-
based one is apparently more relaxed.

====

The particular issue that affects the FDE generation in partitioned code
is this:

(section start, or linker-visible symbol makes no difference)
LcoldStartN:

.... (generally 0-length)

_functionN_cold.0: << needed to identify the start of a new atom,
                   << and also to assist in debug on many platforms.

.....

then we have  in the eh_frame section:

  ...
  .quad LcoldStartN - .
  .long LColdEndN - LcoldStartN

Which is intended to point to the start of the code (comes after
_functionN_cold.0)

But with the cctools assembler, that's not what "LcoldStartN" means, and thus
it ends up (usually) pointing to the section start - or worse, to some
random place in a previous function).

With the LLVM-based toolchain, the assembler appears to allow for the
case that LcoldStartN == _functionN_cold.0. BUT (a) it's not guaranteed that
this _is_ the case since alignment of _functionN_cold.0 might put nops
between LcoldStartN and _functionN_cold.0.  (b) It is probably intended to
support aliasing and is not intended to change the atom ABI.

** I suppose it’s exploiting a slight ambiguity as to how to approach a
zero-sized atom.  However, according to the strict def.
the local label should be made to exist in a distinct atom - even if that has
zero size (and can be laid out wherever we like).

So ..

---------

For FDEs, the solution is to place LcoldStartN: _after_ _functionN_cold.0

JFTR, one cannot do things like

        .quad _functionN_cold.0 - .
        .long LColdEndN - _functionN_cold.0

(i.e. replace the local symbol for the cold section in the FDE by the
 actual linker-visible one) .. since that produces the case that the
second expression cannot be resolved at assembly time and it fails.

=====

So this is the simplest patch to ensure that the cold sub-section local
symbol appears after the linker-visible one.

It moves the output of the symbol from assemble_function_start to the
point at which the switch occurs.

====

NOTE that this problem has already been resolved for the first function
subsection, since the function start label 
_myfunction: 
is followed by
LFBN:  <<< this is referenced in the first FDE for the function.

=====

Since final.c now emits a linker-visible symbol on the switch the one
added to emit from the target hook (on text section switch) is both
redundant and confuses the linker by having two co-incident symbols.

So the patch removes the implementation of the target hook for text sect
switch.
---
 gcc/config/darwin.c | 15 ---------------
 gcc/config/darwin.h |  4 ----
 gcc/final.c         |  5 +++++
 gcc/varasm.c        |  4 ----
 4 files changed, 5 insertions(+), 23 deletions(-)

Reply via email to