diff options
author | David Lamparter <equinox@diac24.net> | 2021-02-02 19:38:38 +0100 |
---|---|---|
committer | David Lamparter <equinox@diac24.net> | 2021-02-03 00:55:07 +0100 |
commit | 08a73c422de98eb12a5f3a86112e7a4829eb3fd6 (patch) | |
tree | 4e70d2ce2c2c5ecaae37799acf1b1fafcc7beed9 /lib/xref.c | |
parent | lib/xref: restore lost extern "C" beginning (diff) | |
download | frr-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.c | 106 |
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); } |