https://bugs.kde.org/show_bug.cgi?id=526075

            Bug ID: 526075
           Summary: Tool link fails against a libgcc built without
                    optimisation: undefined reference to _Unwind_Resume /
                    __gcc_personality_v0
    Classification: Developer tools
           Product: valgrind
      Version First 3.26.0
       Reported In:
          Platform: unspecified
                OS: Linux
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: general
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

Created attachment 196443
  --> https://bugs.kde.org/attachment.cgi?id=196443&action=edit
This is a patch that fixes the above mentioned issue

SUMMARY

Linking the tools fails when the toolchain's libgcc.a has been built without
optimisation:

  ld: libgcc.a(_divdi3.o): in function `__divdi3':
  libgcc2.c:1226: undefined reference to `_Unwind_Resume'
  ld:
libgcc.a(_divdi3.o):(.data.rel.local.DW.ref.__gcc_personality_v0[DW.ref.__gcc_personality_v0]+0x0):
      undefined reference to `__gcc_personality_v0'
  ld: libgcc.a(_moddi3.o): in function `__moddi3':
  libgcc2.c:1249: undefined reference to `_Unwind_Resume'
  ld: libgcc.a(_umoddi3.o): in function `__udivmoddi4':
  libgcc2.c:1204: undefined reference to `_Unwind_Resume'
  collect2: error: ld returned 1 exit status
  make[4]: *** [Makefile:1180: memcheck-x86-linux] Error 1

Seen on x86/Linux (32 bit) with gcc 15.3.0 and binutils 2.45, in Buildroot's
autobuilders. It is not Buildroot specific: any toolchain whose libgcc was
compiled at -O0 triggers it.

STEPS TO REPRODUCE

1. Build a cross toolchain whose libgcc is compiled without optimisation. With
Buildroot this is what BR2_OPTIMIZE_0=y does, because the target CFLAGS end up
after libgcc's own -O2 on the libgcc2.c command line:

  gcc/Makefile.in:507
    GCC_CFLAGS = $(CFLAGS_FOR_TARGET) $(INTERNAL_CFLAGS) ...   [->
libgcc.mvars]
  libgcc/Makefile.in:249
    LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) ...

so the last -O on the command line is the -O0 from CFLAGS_FOR_TARGET.

2. Confirm libgcc's divmod objects carry the unwinder references:

  $ i686-linux-gnu-ar x $(i686-linux-gnu-gcc -print-file-name=libgcc.a)
_divdi3.o
  $ i686-linux-gnu-nm -u _divdi3.o
           U __gcc_personality_v0
           U _Unwind_Resume

3. Configure and build valgrind for that target:

  ./configure --host=i686-buildroot-linux-gnu CFLAGS="-O0 -g0
-fno-stack-protector"
  make

  OBSERVED RESULT — the link of every tool fails as shown above.
  EXPECTED RESULT — the tools link.

ANALYSIS

  libgcc's 64 bit division helpers are deliberately compiled with exceptions
enabled (libgcc/Makefile.in:548):

  LIB2_DIVMOD_EXCEPTION_FLAGS := -fexceptions -fnon-call-exceptions

At -O0 GCC keeps the exception landing pads in those objects, so _divdi3.o,
_moddi3.o and _umoddi3.o reference _Unwind_Resume() and __gcc_personality_v0(),
which live in libgcc_eh.a. At -O1 and above the landing pads are optimised away
and the references disappear. Recompiling the very same object with only the
trailing -O changed shows this clearly (same command line libgcc uses, gcc
15.3.0, i686):

  effective -O0 :  U __gcc_personality_v0    U _Unwind_Resume
  ... -O1       :  (none)
  ... -O2       :  (none)

Tools are linked with

 -static -nodefaultlibs -nostartfiles -u _start ... -lgcc $(LIBGCC_SUP)

so libgcc_eh.a is not on the link line, and the references cannot be resolved.
The division helpers themselves are genuinely needed: on x86 the tools pull in
__divdi3, __moddi3, __udivdi3 and __umoddi3 from -lgcc at every  optimisation
level, so this cannot be avoided by building valgrind differently.

Adding -lgcc_eh is not a workable fix, since it drags in unwind-dw2.o and
unwind-dw2-fde-dip.o, which need abort(), strlen() and dl_iterate_phdr() — none
of which are available under -nodefaultlibs.

PROPOSED FIX

The attached patch adds dummy definitions of _Unwind_Resume() and
__gcc_personality_v0() to coregrind/m_libgcc_sup.c, which is exactly the place
for "supplemental functions for libgcc". They can never be reached, since the
core is  plain C and never raises an exception.

Because they end up in libgcc-sup-<platform>.a, which is linked after -lgcc,
archive members are only pulled in on demand: a toolchain that does provide the
real symbols in libgcc.a keeps using those and the dummies are never 
extracted.

Verified on x86/Linux: with an object reproducing an -O0 built _divdi3.o added
to the tool link, the link fails with exactly the two errors above without
libgcc-sup-x86-linux.a and succeeds with it. A full build of 3.26.0 for i686
with the patch applied is clean.

Happy to rework it if you would rather gate the definitions on a configure
check, or have them call VG_(core_panic)() instead of __builtin_trap() — I used
the builtin to keep m_libgcc_sup.o free of references back into libcoregrind.a,
since it is linked last.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to