By using the test `with_system_libunwind', libgcc can use either
in-house implementation or reference external libunwind symbols.
However, this breaks the static libgcc.a library, as in t-linux it
references unwind-compat.c, which turns some _Unwind_* symbols into
references of the corresponding symbols in libunwind, but libunwind does
not exist in some conditions (e.g. bootstrapping a toolchain). The
linker complains about `missing version node for symbol', since it can
not find the symbol it is referring to.

The unwind-compat.c module should only exist, if system libunwind is
being used. Also GCC itself should add -lunwind only if this condition
is met, too.

Implementing better control for whether to embed unwind implementation
into libgcc to fix this issue.

gcc/
        * config.gcc: limit -lunwind usage by testing if the system
        libunwind is being used.

libgcc/
        * config.host (ia64): include unwind-compat only if the system
        libunwind is being used.

        * config/ia64/t-linux-libunwind: include libgcc symver definition
        for libgcc symbols, since it bears the same role as t-linux
        (except libunwind); Include fde-glibc.c since the unwind
        implementation requires _Unwind_FindTableEntry in this file.

        * config/ia64/unwind-ia64.c: protect _Unwind_FindTableEntry inside
        inihbit_libc ifndefs to allow it to build with newlib or
        without proper headers.
---
 gcc/config.gcc                       | 5 ++++-
 libgcc/config.host                   | 4 +++-
 libgcc/config/ia64/t-linux-libunwind | 4 ++++
 libgcc/config/ia64/unwind-ia64.c     | 9 ++++++++-
 4 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index b0fa43b5eba..6b08827c3e0 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2359,7 +2359,10 @@ ia64*-*-freebsd*)
        ;;
 ia64*-*-linux*)
        tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h 
ia64/sysv4.h ia64/linux.h"
-       tmake_file="${tmake_file} ia64/t-ia64 ia64/t-linux t-libunwind"
+       tmake_file="${tmake_file} ia64/t-ia64 ia64/t-linux"
+       if test x$with_system_libunwind = xyes ; then
+               tmake_file="${tmake_file} t-libunwind"
+       fi
        target_cpu_default="MASK_GNU_AS|MASK_GNU_LD"
        ;;
 ia64*-*-hpux*)
diff --git a/libgcc/config.host b/libgcc/config.host
index 82ea1772f51..d7025e9077f 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -957,9 +957,11 @@ ia64*-*-freebsd*)
 ia64*-*-linux*)
        # Don't use crtbeginT.o from *-*-linux* default.
        extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
-       tmake_file="$tmake_file ia64/t-ia64 ia64/t-ia64-elf t-crtfm t-softfp-tf 
ia64/t-softfp t-softfp ia64/t-softfp-compat ia64/t-eh-ia64 t-libunwind 
ia64/t-linux"
+       tmake_file="${tmake_file} ia64/t-ia64 ia64/t-ia64-elf t-crtfm 
t-softfp-tf ia64/t-softfp t-softfp ia64/t-softfp-compat ia64/t-eh-ia64"
        if test x$with_system_libunwind != xyes ; then
                tmake_file="${tmake_file} t-libunwind-elf 
ia64/t-linux-libunwind"
+       else
+               tmake_file="${tmake_file} ia64/t-linux t-libunwind"
        fi
        md_unwind_header=ia64/linux-unwind.h
        ;;
diff --git a/libgcc/config/ia64/t-linux-libunwind 
b/libgcc/config/ia64/t-linux-libunwind
index 8b1736a2d67..daef9e97bdb 100644
--- a/libgcc/config/ia64/t-linux-libunwind
+++ b/libgcc/config/ia64/t-linux-libunwind
@@ -1,3 +1,7 @@
 # Build libunwind for IA-64 GLIBC based system.
 LIBUNWIND = $(srcdir)/config/ia64/fde-glibc.c \
   $(srcdir)/config/ia64/unwind-ia64.c
+
+LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c
+
+SHLIB_MAPFILES += $(srcdir)/config/ia64/libgcc-glibc.ver
diff --git a/libgcc/config/ia64/unwind-ia64.c b/libgcc/config/ia64/unwind-ia64.c
index 75208eae60a..a746358da5c 100644
--- a/libgcc/config/ia64/unwind-ia64.c
+++ b/libgcc/config/ia64/unwind-ia64.c
@@ -1730,6 +1730,7 @@ _Unwind_GetRegionStart (struct _Unwind_Context *context)
 void *
 _Unwind_FindEnclosingFunction (void *pc)
 {
+#ifndef inhibit_libc
   struct unw_table_entry *entp, ent;
   unw_word segment_base, gp;
 
@@ -1738,6 +1739,9 @@ _Unwind_FindEnclosingFunction (void *pc)
     return NULL;
   else
     return (void *)(segment_base + entp->start_offset);
+#else
+  return NULL;
+#endif
 }
 
 /* Get the value of the CFA as saved in CONTEXT.  In GCC/Dwarf2 parlance,
@@ -1780,9 +1784,12 @@ uw_frame_state_for (struct _Unwind_Context *context, 
_Unwind_FrameState *fs)
   for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)
     r->when = UNW_WHEN_NEVER;
   context->lsda = 0;
-
+#ifndef inhibit_libc
   entp = _Unwind_FindTableEntry ((void *) context->rp,
                                &segment_base, &context->gp, &ent);
+#else
+  entp = NULL;
+#endif
   if (entp == NULL)
     {
       /* Couldn't find unwind info for this function.  Try an
-- 
2.51.1

Reply via email to