Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ObjC relocation against symbol in discarded section error on Windows using gnustep-2.0 runtime #49025

Open
triplef opened this issue Mar 22, 2021 · 4 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla clang Clang issues not falling into any other category objective-c

Comments

@triplef
Copy link
Member

triplef commented Mar 22, 2021

Bugzilla Link 49681
Version 11.0
OS Windows NT
CC @triplef,@zygoloid

Extended Description

Linking a file that references functions from the gnustep-2.0 runtime, but does not reference any Objective-C code, results in the following linker errors when using LLD:

lld-link: error: relocation against symbol in discarded section: __start_.objcrt$SEL
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __stop.objcrt$SEL
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __start_.objcrt$CLS
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __stop.objcrt$CLS
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __start_.objcrt$CLR
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __stop.objcrt$CLR
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __start_.objcrt$CAT
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __stop.objcrt$CAT
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __start_.objcrt$PCL
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __stop.objcrt$PCL
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __start_.objcrt$PCR
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __stop.objcrt$PCR
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __start_.objcrt$CAL
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __stop.objcrt$CAL
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __start_.objcrt$STR
>>> referenced by test-ffaa49.o:(.objc_init)

lld-link: error: relocation against symbol in discarded section: __stop.objcrt$STR
>>> referenced by test-ffaa49.o:(.objc_init)
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Using link.exe only results in the following warnings:

libcmt.lib(exe_main.obj) : warning LNK4078: multiple '.CRT' sections found with different attributes (40400040)
libcmt.lib(initializers.obj) : warning LNK4254: section '.CRT' (C0000040) merged into '.rdata' (40000040) with different attributes

This can be reproduced e.g. as follows:

$ cat test.m
#include <objc/runtime.h>

int main(int argc, char *argv[]) {
  objc_getClass("Test");
}

$ clang -fobjc-runtime=gnustep-2.0 -fuse-ld=lld -lobjc test.m

Adding any code that references Objective-C classes in the same file, e.g. [NSObject new], makes the linker errors disappear. Likewise using the gnustep-1.9 runtime does not expose this issue.

This is relevant when using Autoconf to check for the existence of runtime functions, as it will generate files like the above (minus the #include) to do so.

@triplef
Copy link
Member Author

triplef commented Mar 22, 2021

assigned to @davidchisnall

@davidchisnall
Copy link
Contributor

The use of the runtime APIs is actually a red herring. I think this can be reproduced with:

int main(void) { return 0; }

If saved as a .m file. If a compilation unit does not contain any Objective-C constructs, then we still emit the start and end section markers and the call to the load function, but I suspect the linker removes them entirely because nothing is marked as needing to be retained. There was a similar bug in clang 7 with ELF, and I'm surprised the fix there (don't emit the Objective-C metadata if none of it is used) didn't catch this case, but the correct fix on Windows is probably slightly different: I think we need to mark the start and end markers as used so that they're not discarded, though I'm surprised that this works with just one class / selector reference: I guess the fact that one of the sections is live keeps the others around?

Note that this could also probably be worked around in the header file by putting this in runtime.h:

#ifdef __OBJC__
static id __work_around_clang_bug = @"unused";
#endif

@triplef
Copy link
Member Author

triplef commented Mar 22, 2021

The use of the runtime APIs is actually a red herring. I think this can be
reproduced with:

int main(void) { return 0; }

Yes you’re right!

Note that this could also probably be worked around in the header file by
putting this in runtime.h:

#ifdef __OBJC__
static id __work_around_clang_bug = @"unused";
#endif

Unfortunately that doesn’t seem to do the trick, I’m getting the same errors when adding that to my test.m.

@triplef
Copy link
Member Author

triplef commented Mar 23, 2021

Unfortunately that doesn’t seem to do the trick, I’m getting the same errors
when adding that to my test.m.
Putting the following in test.m works as a workaround:

#if defined(__OBJC__) && defined(__clang__) && defined(_MSC_VER)
id __work_around_clang_bug = @"__unused__";
#endif

It has to be declared non-static, and the string needs to be at least 9 characters it seems (probably so it doesn’t end up as tiny string).

I tried putting the static variant in runtime.h but that doesn’t seem to do the trick, and adding it non-static results in duplicate symbols even if guarded by a define.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla clang Clang issues not falling into any other category objective-c
Projects
None yet
Development

No branches or pull requests

3 participants