[Bug libgcc/60939] AIX: exceptions not caught when calling function via pointer

bernard.ladenthin at gmail dot com gcc-bugzilla@gcc.gnu.org
Sun Sep 6 19:47:45 GMT 2026


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

--- Comment #17 from Bernard Ladenthin <bernard.ladenthin at gmail dot com> ---
The mechanism is documented by IBM, so it need not be argued from behaviour.
Three facts from two manuals, and one line of GCC.

1. The linker discards by default.

AIX 5L Version 5.3 Commands Reference, Volume 3, SC23-4890-04, ld command,
"Garbage Collection":

  By default, the ld command performs garbage collection, deleting control
  sections (CSECTs) that are not referenced when generating the output file.

  A CSECT is an indivisible unit of coding or data. A CSECT references another
  CSECT if it contains a relocation entry (RLD) referring to a symbol contained
  in the other CSECT. A referenced CSECT causes all CSECTs it references to be
  referenced as well. In addition, a CSECT is referenced if it contains
  exported symbols, symbols specified with the -u flag, or the symbol
  designated as the entry point with the -e flag.

That is why no unusual link flags are needed to hit this, and why -bnogc, -r,
-bkeepfile and -bgcbypass all make it go away -- which is the workaround people
kept finding by accident.

2. .ref exists to prevent exactly that, and IBM's own example is our case.

AIX 5L Version 5.3 Assembler Language Reference, SC23-4923-02, page 494,
".ref Pseudo-op":

  Creates a R_REF type entry in the relocation table for one or more symbols.

  The .ref pseudo-op supports the creation of multiple RLD entries in the same
  location. This pseudo-op is used in the output of some compilers to ensure
  the linkage editor does not discard routines that are used but not referenced
  explicitly in the text or data sections.

  For example, in C++, constructors and destructors are used to construct and
  destroy class objects. Constructors and destructors are sometimes called only
  from the run-time environment without any explicit reference in the text
  section.

The worked example IBM gives for why .ref exists is a C++ constructor reachable
only from the runtime. That is the reproducer in this ticket.

3. The .ref lives inside the function body's csect.

ASM_OUTPUT_DWARF_TABLE_REF emits it from each function to its frame table. When
nothing references that function body during collect2's first link -- because
collect2 has not written the constructor table yet -- the body is discarded and
the .ref goes with it. The frame table then has nothing pointing at it and is
collected too. collect2 scans the resulting output, finds one frame table where
there were two, and registers only the survivor.

That is the defect. The patch stops depending on the frame table surviving the
first link, by scanning the command-line objects for frame tables before it.

Visible in the process image, breaking on __register_frame_info_table_bases in
the reproducer and dumping the table it is handed:

  without the patch:  0x10001040 <_GLOBAL__F_pFoo>  0x0
  with the patch:     0x100010b0 <_GLOBAL__F__Z3foov>
                      0x10001060 <_GLOBAL__F_pFoo>  0x0

One entry against two, and the one that reappears is the frame table for foo(),
the function holding the handler that was never found.

The patch was resent as v2 on 2026-09-06 with this documentation and the
measurements behind it, threaded under the original posting on gcc-patches.
The code is unchanged from the first version; only the commit message grew.


More information about the Gcc-bugs mailing list