The following allows libgcc to use newer glibc _dl_find_object even
when at compile-time the facility was not available.
Bootstrapped and tested on x86_64-unknown-linux-gnu with new glibc,
on {aarch64,ppc64le,i586,x84_64} SLE15 GA (with old glibc).
We're about to deploy this for SLE15 which builds libgcc_s1 against
GA with glibc 2.26 but customers on SP6 or SP7 benefiting from
glibc 2.38 and possibly faster exception handling with the
_dl_find_object code path.
I think it makes sense to implement a runtime check on such feature
when possible, so I'm proposing the following for trunk. The actual
dl_find_object layout is unfortunately somewhat of a target specific maze,
I've simplified it to the actually relevant head plus making sure the
overall size is sufficient. The important part is to guard the
argument passing to find_fde_tail properly:
# if DLFO_STRUCT_HAS_EH_DBASE
(_Unwind_Ptr) dlfo.dlfo_eh_dbase,
# else
0,
# endif
OK?
Thanks,
Richard.
libgcc/
* unwind-dw2-fde-dip.c (_Unwind_Find_FDE): When _dl_find_object
is not available declare it weak and perform a runtime check
on its presence.
---
libgcc/unwind-dw2-fde-dip.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
index 5c19838e0a3..74cecfc2c2c 100644
--- a/libgcc/unwind-dw2-fde-dip.c
+++ b/libgcc/unwind-dw2-fde-dip.c
@@ -542,6 +542,40 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
if (ret != NULL)
return ret;
+/* When the glibc we build against does not have dl_find_object tentatively
+ declare the relevant bits of the structure here and use a weak declaration
+ so we can perform a runtime check on its presence. */
+#if !defined(DLFO_STRUCT_HAS_EH_DBASE)
+
+#ifdef __i386__
+# define DLFO_STRUCT_HAS_EH_DBASE 1
+#else
+# define DLFO_STRUCT_HAS_EH_DBASE 0
+#endif
+
+/* The following is dl_find_object as in it's maximum size configuration. */
+struct dl_find_object
+{
+ __extension__ unsigned long long int dlfo_flags;
+ void *dlfo_map_start; /* Beginning of mapping containing address. */
+ void *dlfo_map_end; /* End of mapping. */
+ struct link_map *dlfo_link_map;
+ void *dlfo_eh_frame; /* Exception handling data of the object. */
+# if DLFO_STRUCT_HAS_EH_DBASE
+ void *dlfo_eh_dbase; /* Base address for DW_EH_PE_datarel. */
+# if __WORDSIZE == 32
+ unsigned int __dlfo_eh_dbase_pad;
+# endif
+# endif
+ /* PAD to an upper bound size. */
+ __extension__ unsigned long long int __dflo_reserved[8];
+};
+
+ extern int _dl_find_object (void *,
+ struct dl_find_object *) __attribute__((weak));
+
+ if (_dl_find_object)
+#endif
/* Use DLFO_STRUCT_HAS_EH_DBASE as a proxy for the existence of a glibc-style
_dl_find_object function. */
#if defined(DLFO_STRUCT_HAS_EH_DBASE)
--
2.51.0