summaryrefslogtreecommitdiffstats
path: root/lib/xref.h
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@diac24.net>2021-02-02 19:38:38 +0100
committerDavid Lamparter <equinox@diac24.net>2021-02-03 00:55:07 +0100
commit08a73c422de98eb12a5f3a86112e7a4829eb3fd6 (patch)
tree4e70d2ce2c2c5ecaae37799acf1b1fafcc7beed9 /lib/xref.h
parentlib/xref: restore lost extern "C" beginning (diff)
downloadfrr-08a73c422de98eb12a5f3a86112e7a4829eb3fd6.tar.xz
frr-08a73c422de98eb12a5f3a86112e7a4829eb3fd6.zip
lib/xref: work around GCC bug 41091
gcc fucks up global variables with section attributes when they're used in templated C++ code. The template instantiation "magic" kinda breaks down (it's implemented through COMDAT in the linker, which clashes with the section attribute.) The workaround provides full runtime functionality, but the xref extraction tool (xrelfo.py) won't work on C++ code compiled by GCC. FWIW, clang gets this right. Signed-off-by: David Lamparter <equinox@diac24.net>
Diffstat (limited to 'lib/xref.h')
-rw-r--r--lib/xref.h24
1 files changed, 24 insertions, 0 deletions
diff --git a/lib/xref.h b/lib/xref.h
index e464da413..426ffad70 100644
--- a/lib/xref.h
+++ b/lib/xref.h
@@ -119,6 +119,7 @@ struct xref_block {
extern struct xref_block *xref_blocks;
extern void xref_block_add(struct xref_block *block);
+extern void xref_gcc_workaround(const struct xref *xref);
#ifndef HAVE_SECTION_SYMS
/* we have a build system patch to use GNU ld on Solaris; if that doesn't
@@ -218,12 +219,35 @@ extern const struct xref * const __stop_xref_array[1] DSO_LOCAL;
#endif /* HAVE_SECTION_SYMS */
/* emit the array entry / pointer to xref */
+#if defined(__clang__) || !defined(__cplusplus)
#define XREF_LINK(dst) \
static const struct xref * const NAMECTR(xref_p_) \
__attribute__((used, section("xref_array"))) \
= &(dst) \
/* end */
+#else /* GCC && C++ */
+/* workaround for GCC bug 41091 (dated 2009), added in 2021...
+ *
+ * this breaks extraction of xrefs with xrelfo.py (because the xref_array
+ * entry will be missing), but provides full runtime functionality. To get
+ * the proper list of xrefs from C++ code, build with clang...
+ */
+struct _xref_p {
+ const struct xref * const ptr;
+
+ _xref_p(const struct xref *_ptr) : ptr(_ptr)
+ {
+ xref_gcc_workaround(_ptr);
+ }
+};
+
+#define XREF_LINK(dst) \
+ static const struct _xref_p __attribute__((used)) \
+ NAMECTR(xref_p_)(&(dst)) \
+ /* end */
+#endif
+
/* initializer for a "struct xref" */
#define XREF_INIT(type_, xrefdata_, func_) \
{ \