LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 49681 - ObjC relocation against symbol in discarded section error on Windows using gnustep-2.0 runtime
Summary: ObjC relocation against symbol in discarded section error on Windows using gn...
Status: NEW
Alias: None
Product: clang
Classification: Unclassified
Component: -New Bugs (show other bugs)
Version: 11.0
Hardware: PC Windows NT
: P normal
Assignee: David Chisnall
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-03-22 09:33 PDT by Frederik Seiffert
Modified: 2021-03-22 21:43 PDT (History)
5 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Frederik Seiffert 2021-03-22 09:33:06 PDT
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.
Comment 1 David Chisnall 2021-03-22 10:18:53 PDT
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
```
Comment 2 Frederik Seiffert 2021-03-22 10:28:19 PDT
(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.
Comment 3 Frederik Seiffert 2021-03-22 21:43:48 PDT
(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.