*bitpos = bp;
}
+static void xref_add_one(const struct xref *xref)
+{
+ SHA256_CTX sha;
+ struct xrefdata *xrefdata;
+
+ const char *filename, *p, *q;
+ uint8_t hash[32], *h = hash;
+ uint32_t be_val;
+ int bitpos;
+
+ if (!xref || !xref->xrefdata)
+ return;
+
+ xrefdata = xref->xrefdata;
+ xrefdata->xref = xref;
+
+ if (!xrefdata->hashstr)
+ return;
+
+ /* as far as the unique ID is concerned, only use the last
+ * directory name + filename, e.g. "bgpd/bgp_route.c". This
+ * gives a little leeway in moving things and avoids IDs being
+ * screwed up by out of tree builds or absolute pathnames.
+ */
+ filename = xref->file;
+ p = strrchr(filename, '/');
+ if (p) {
+ q = memrchr(filename, '/', p - filename);
+ if (q)
+ filename = q + 1;
+ else
+ filename = p + 1;
+ }
+
+ SHA256_Init(&sha);
+ SHA256_Update(&sha, filename, strlen(filename));
+ SHA256_Update(&sha, xrefdata->hashstr,
+ strlen(xrefdata->hashstr));
+ be_val = htonl(xrefdata->hashu32[0]);
+ SHA256_Update(&sha, &be_val, sizeof(be_val));
+ be_val = htonl(xrefdata->hashu32[1]);
+ SHA256_Update(&sha, &be_val, sizeof(be_val));
+ SHA256_Final(hash, &sha);
+
+ bitpos = -1;
+ base32(&h, &bitpos, &xrefdata->uid[0], 5);
+ xrefdata->uid[5] = '-';
+ base32(&h, &bitpos, &xrefdata->uid[6], 5);
+}
+
+void xref_gcc_workaround(const struct xref *xref)
+{
+ xref_add_one(xref);
+}
+
void xref_block_add(struct xref_block *block)
{
const struct xref * const *xrefp;
- SHA256_CTX sha;
*xref_block_last = block;
xref_block_last = &block->next;
- for (xrefp = block->start; xrefp < block->stop; xrefp++) {
- const struct xref *xref = *xrefp;
- struct xrefdata *xrefdata;
-
- const char *filename, *p, *q;
- uint8_t hash[32], *h = hash;
- uint32_t be_val;
- int bitpos;
-
- if (!xref || !xref->xrefdata)
- continue;
-
- xrefdata = xref->xrefdata;
- xrefdata->xref = xref;
-
- if (!xrefdata->hashstr)
- continue;
-
- /* as far as the unique ID is concerned, only use the last
- * directory name + filename, e.g. "bgpd/bgp_route.c". This
- * gives a little leeway in moving things and avoids IDs being
- * screwed up by out of tree builds or absolute pathnames.
- */
- filename = xref->file;
- p = strrchr(filename, '/');
- if (p) {
- q = memrchr(filename, '/', p - filename);
- if (q)
- filename = q + 1;
- else
- filename = p + 1;
- }
-
- SHA256_Init(&sha);
- SHA256_Update(&sha, filename, strlen(filename));
- SHA256_Update(&sha, xrefdata->hashstr,
- strlen(xrefdata->hashstr));
- be_val = htonl(xrefdata->hashu32[0]);
- SHA256_Update(&sha, &be_val, sizeof(be_val));
- be_val = htonl(xrefdata->hashu32[1]);
- SHA256_Update(&sha, &be_val, sizeof(be_val));
- SHA256_Final(hash, &sha);
-
- bitpos = -1;
- base32(&h, &bitpos, &xrefdata->uid[0], 5);
- xrefdata->uid[5] = '-';
- base32(&h, &bitpos, &xrefdata->uid[6], 5);
- }
+ for (xrefp = block->start; xrefp < block->stop; xrefp++)
+ xref_add_one(*xrefp);
}
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
#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_) \
{ \