From 08a73c422de98eb12a5f3a86112e7a4829eb3fd6 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 2 Feb 2021 19:38:38 +0100 Subject: 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 --- lib/xref.c | 106 +++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 57 insertions(+), 49 deletions(-) (limited to 'lib/xref.c') diff --git a/lib/xref.c b/lib/xref.c index eb5e8ed2c2..40efe51363 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); } -- cgit v1.2.3