-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Description
#101222 recently landed which enables private symbols to be merged, which includes CFString constants. On a Clang containing that patch, if you build the following C code:
$ cat merge.c
void *__CFConstantStringClassReference;
int main(int argc, char *argv[]) {
return argc ? (long)__builtin___CFStringMakeConstantString("foo")
: (long)__builtin___CFStringMakeConstantString("bar");
}
$ clang -target arm64-apple-macos11 -O3 -S -o merge.s merge.c
It generates the assembly in https://gist.github.com/smeenai/9fe473bcb5c4cb4a2b97eb147b23f671 (I changed a .set directive changed to = to avoid #104623 and match the object file generated by Clang directly). If you compile and link this assembly:
$ llvm-mc --triple=arm64-apple-macos11 --filetype=obj -o merge.o merge.s
$ ld64.lld -arch arm64 -platform_version macos 11 11 -dead_strip -o merge merge.o
you'll discover that the second cfstring constant has been incorrectly dead-stripped:
$ llvm-objdump -h merge.o | grep cfstring
3 __cfstring 00000040 0000000000000020 DATA
$ llvm-objdump -h merge | grep cfstring
3 __cfstring 00000020 0000000100004000 DATA
Note the size of 0x20 instead of 0x40 in the output binary. The code in the binary still references the second string though:
$ llvm-objdump -d merge
0000000100000470 <_main>:
100000470: 1001dc88 adr x8, 0x100004000 <__MergedGlobals>
100000474: d503201f nop
100000478: 11008109 add w9, w8, #0x20
10000047c: 7100001f cmp w0, #0x0
100000480: 1a880120 csel w0, w9, w8, eq
100000484: d65f03c0 ret
Which causes crashes at runtime in an actual program.
This might be a general problem with dead-stripping sections with alt_entry symbols and not something specific to CFStrings, but I haven't experimented further yet.