summaryrefslogtreecommitdiffstats
path: root/lib/xref.c
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.c
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.c')
-rw-r--r--lib/xref.c106
1 files changed, 57 insertions, 49 deletions
diff --git a/lib/xref.c b/lib/xref.c
index eb5e8ed2c..40efe5136 100644
--- a/lib/xref.c
+++ b/lib/xref.c
@@ -63,60 +63,68 @@ static void base32(uint8_t **inpos, int *bitpos,
*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);
}