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

Bernard Ladenthin <bernard.ladenthin at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bernard.ladenthin at gmail dot 
com

--- Comment #15 from Bernard Ladenthin <bernard.ladenthin at gmail dot com> ---
Still present in 2026, in GCC 12.3.0, 13.3.0 and 15.2.0 -- the newest GCC
IBM ships for AIX.  The a.cc/b.cc attached in 2014 reproduce it unchanged:

  BEGIN
  terminate called after throwing an instance of 'std::runtime_error'
    what():  TILT
  IOT/Abort trap(coredump)   exit=134

Seen on real POWER8 (AIX 7.3 TL01, gcc 12.3.0 and 13.3.0, 32- and 64-bit),
POWER10 (AIX 7.3 TL04, gcc 13.3.0 and 15.2.0), and emulated POWER8 under
QEMU (AIX 7.2 TL04, gcc 13.3.0).

IBM Open XL 17.1.1 (clang 15) is not affected on the same machine, same OS
and same linker -- so this is GCC, not an AIX platform limit.


Cause
-----

collect2 leaves SCAN_DWEH out of the scan before the first link:

  scanfilter this_filter = ld1_filter;
  #if HAVE_AS_REF
    if (!shared_obj)
      this_filter &= ~SCAN_DWEH;
  #endif

Frame tables are collected from the first link's output instead.  That
assumes a table left out here still shows up there, because
ASM_OUTPUT_DWARF_TABLE_REF emits a .ref from each function body to its
table -- which holds only while the function body survives.  A unit whose
sole entry point is a static constructor has nothing referenced during the
first link (collect2 has not written the constructor table yet), so the AIX
linker discards the csect and the frame table with it:

  $ g++ -Wl,-debug -o t a.o b.o main.o | grep 'frame table'
  1 frame table found

although nm shows two _GLOBAL__F_* symbols, both C_EXT, both classified
SYM_DWEH.  The generated glue registers only the survivor:

  extern void *x12 __asm__ ("_GLOBAL__F_main");
  static void *frame_table[] = { &x12, 0 };

Adding the missing entry by hand turns terminate into a caught exception,
which pins the cause to the registration and nothing else.


Workarounds
-----------

None were on record here.  Two work, both measured:

  g++ -Wl,-bkeepfile:a.o ...            (per object contributing a table)
  g++ -Wl,-u,_GLOBAL__F__GLOBAL__I_...  (per frame-table symbol)

Either keeps the csect alive through the first link, so its table is still
there to be found.


Patch
-----

Posted to gcc-patches with a testcase; link at the end.

Constructors are already collected from the objects; frame tables are not.
The comment's concern -- dragging in objects nothing references -- is real
for archive members and not for objects named on the command line, which
are linked either way.  So: keep excluding SCAN_DWEH for libraries, retain
it for objects.

Testsuite, same tree, only collect2 swapped:

                 g++.dg/eh/pr60939.C     full check-g++
  unpatched      4 passes, 4 failures    224411 result lines
  patched        8 passes                224411 result lines

No differing line between the two full runs, and identical tallies in every
category (211110 expected passes, 14 unexpected failures, 28 unexpected
successes, 2090 expected failures, 11169 unsupported).  The test fails in
gnu++98, gnu++14, gnu++17 and gnu++20 alike, so the language standard is
not involved.

Shared-object and static-archive links were compared too: identical
behaviour, the archive case growing by 56 bytes -- the one added table
entry, not a dragged-in member.

The testcase is deliberately not AIX-gated: it is a valid program
everywhere and passes on other targets.

The affected block is byte-identical in releases/gcc-13, 14, 15 and master,
and the patch applies cleanly to 13.3.0 and to master.

Sent to gcc-patches on 2026-09-05, CC'ing the AIX maintainer:

  [PATCH] collect2: scan objects for EH frame tables before the first link
  [PR60939]
 
https://inbox.sourceware.org/gcc-patches/[email protected]/

Reply via email to