Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

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

Open Quuxplusone opened 3 years ago

Quuxplusone commented 3 years ago
Bugzilla Link PR49681
Status NEW
Importance P normal
Reported by Frederik Seiffert (frederik@algoriddim.com)
Reported on 2021-03-22 09:33:06 -0700
Last modified on 2021-03-22 21:43:48 -0700
Version 11.0
Hardware PC Windows NT
CC frederik@algoriddim.com, htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org, neeilans@live.com, richard-llvm@metafoo.co.uk
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
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.
Quuxplusone commented 3 years ago

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
Quuxplusone commented 3 years ago

(In reply to David Chisnall from comment #1)

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.

Quuxplusone commented 3 years ago

(In reply to Frederik Seiffert from comment #2)

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.