In attempting to add support for -G/–keep-global-symbol, I played around with GNU objcopy to see how it handles various situations, especially in interacting with --globalize-symbol. I’d like to see if anyone has objections to the behavior proposed in https://reviews.llvm.org/D50589. Long, gory details below:
These two “global” flags are named similarly, but can have very different effects:
- –globalize-symbol makes a symbol global.
- According to man pages: “Give symbol symbolname global scoping so that it is visible outside of the file in which it is defined.”
- –keep-global-symbol will make all symbols local except for any symbols specified via --keep-global-symbol.
- According to man pages: “Keep only symbol symbolname global. Make all other symbols local to the file, so that they are not visible externally.”
(Note: “–keep-global-symbol LocalSymbol” does not promote it to being a global symbol)
However, the actual thing GNU sources for objcopy.c does (simplified to just relevant bits) is this:
for (auto sym : symbols) {
auto flags = sym->flags;
auto name = sym->name;
// If flag is global/weak, and --keep-global-symbol includes it,
// make it local
if ((flags & (GLOBAL | WEAK)) &&
(keep_globals.size() != 0 && !list_contains(keep_globals, name))) {
sym->flags &= ~(GLOBAL | WEAK);
sym->flags |= LOCAL;
}
// If flag is local and --globalize-symbol is set, make it global
// Note: checks flags, not sym->flags
if ((flags & LOCAL) && list_contains(globalize, name)) {
sym->flags &= ~LOCAL;
sym->flags |= GLOBAL;
}
}
This seems strange for a few reasons:
-
Weak symbols are not globalized. The help for --globalize-symbol never mention it doesn’t handle weak symbols, so this seems like a bug in GNU objcopy.
-
If one were to do “–globalize-symbol SomeGlobal --keep-global-symbol SomeOtherGlobal”, you might expect that both SomeGlobal and SomeOtherGlobal are global in the output file… but it isn’t. (Admittedly, this is a weird command line usage). Because --keep-global-symbol is set and doesn’t include SomeGlobal, SomeGlobal will be demoted to a local symbol. And because the check to see if we should apply the --globalize-symbol flag checks “flags” (the original flag set), and not “sym->flags”, it decides not to do anything, so SomeGlobal remains a local symbol.
The proposed behavior in https://reviews.llvm.org/D50589 is to break from GNU here, so that --globalize-symbol will always make a symbol global, including when it’s a weak symbol, and including when it isn’t included in --keep-global-symbol.
(Actually, --globalize-symbol is already implemented and promotes weak symbols to global, this message is more of a “hey, we’re already different from GNU, is that OK?” for that part)
Thanks – Jordan