[Bug c/91664] New: Undefined reference linker errors when static linking archive with gcc target_clones function multi-versioning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91664 Bug ID: 91664 Summary: Undefined reference linker errors when static linking archive with gcc target_clones function multi-versioning Product: gcc Version: 8.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: element at elementsofsound dot org Target Milestone: --- Created attachment 46826 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46826&action=edit Preprocessed file for fmv-test.c Target: x86_64-linux-gnu gcc version 8.3.0 (Ubuntu 8.3.0-6ubuntu1) Creating a static library archive with publicly declared functions with target_clones attribute, causes undefined reference errors to the function clones when linking the archive into the final application. I created a test build on github which illustrates this: https://github.com/elementgreen/fmv-test Also a stackoverflow question: https://stackoverflow.com/questions/57798005/how-to-fix-undefined-reference-linker-errors-when-static-linking-archive-with-gc This test build has 3 different make targets "works", "also_works", and "borken". The first just builds the executable in one go with .c source files and -o for the target executable. The second compiles each .c into .o object files and then links them with gcc -o and the object files. The final make target compiles each .c into .o files, then creates an archive with ar, and then links the .a archive into the final executable with gcc -o. The first 2 targets work, the 3rd does not, with the errors: gcc -c fmv-test.c gcc -c main.c ar cr fmv-test.a fmv-test.o main.o gcc -o fmv-test-borken fmv-test.a /usr/bin/ld: fmv-test.a(main.o): in function `fmv_test': main.c:(.text.fmv_test.resolver[fmv_test.resolver]+0x1f): undefined reference to `fmv_test.avx2.0' /usr/bin/ld: main.c:(.text.fmv_test.resolver[fmv_test.resolver]+0x3b): undefined reference to `fmv_test.avx.1' /usr/bin/ld: main.c:(.text.fmv_test.resolver[fmv_test.resolver]+0x57): undefined reference to `fmv_test.sse4_1.2' /usr/bin/ld: main.c:(.text.fmv_test.resolver[fmv_test.resolver]+0x71): undefined reference to `fmv_test.sse2.3' /usr/bin/ld: main.c:(.text.fmv_test.resolver[fmv_test.resolver]+0x7a): undefined reference to `fmv_test.default.4' collect2: error: ld returned 1 exit status
[Bug c/91664] Undefined reference linker errors when static linking archive with gcc target_clones function multi-versioning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91664 --- Comment #1 from element at elementsofsound dot org --- Created attachment 46827 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46827&action=edit Preprocessed file for main.c
[Bug c/91664] Undefined reference linker errors when static linking archive with gcc target_clones function multi-versioning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91664 --- Comment #4 from element at elementsofsound dot org --- (In reply to Andrew Pinski from comment #2) > Try this: > gcc -c fmv-test.c > gcc -c main.c > ar cr fmv-test.a main.o fmv-test.o > gcc -o fmv-test-borken fmv-test.a > > It might be because the way linker processes archives and most likely not a > bug. I tried changing the order of the .o files in the ar command as shown, but same errors occurred.
[Bug c/91664] Undefined reference linker errors when static linking archive with gcc target_clones function multi-versioning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91664 --- Comment #5 from element at elementsofsound dot org --- (In reply to Andrew Pinski from comment #3) > Maybe it is not clear but target_clones is only supposed to be on the > definition rather just declarations too. I'm not sure if I understood you exactly. The target_clones attribute is defined in the header file for the definition of the function (for use by other .c files). If I add it to the actual function, GCC complains, so I only have it on the definition. I think that is what you meant. One thing I have noticed is that when the .c files are compiled as individual object files, objdump shows that the number at the end of the symbols for the target clones do not match. However, when linking these object files with gcc they somehow are resolved. If instead they are placed in an archive, then they don't resolve. Not sure if this is related. It seems like this has something to do more with the linking than gcc compilation of the C code. So perhaps my lack of knowledge led me to file the bug for the wrong component? See below: objdump -t fmv-test.o | grep fmv_test l F .text 0062 fmv_test.default.9 0239 l F .text 0062 fmv_test.avx2.4 029b l F .text 0062 fmv_test.avx.5 02fd l F .text 0062 fmv_test.sse4_1.6 035f l F .text 0062 fmv_test.sse2.7 ld .text.fmv_test.resolver .text.fmv_test.resolver 03c1 g i .text 0080 internal_func._GLOBAL___fmv_test.ifunc wF .text.fmv_test.resolver0080 fmv_test.resolver g i .text.fmv_test.resolver0080 fmv_test objdump -t main.o | grep fmv_test ld .text.fmv_test.resolver .text.fmv_test.resolver g i .text.fmv_test.resolver0080 fmv_test wF .text.fmv_test.resolver0080 fmv_test.resolver *UND* fmv_test.avx2.0 *UND* fmv_test.avx.1 *UND* fmv_test.sse4_1.2 *UND* fmv_test.sse2.3 *UND* fmv_test.default.4
[Bug c/91664] Undefined reference linker errors when static linking archive with gcc target_clones function multi-versioning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91664 --- Comment #6 from element at elementsofsound dot org --- I removed the internal_func() with the target_clones attribute, which caused the last number digit of the symbols for fmv_test clones to match up between object files, but errors still occur. I ran nm on the resulting archive and got the below output, which may provide a clue. Note that the fmv_test target clone functions have lower case 't' for local Text and don't end up in the archive index. I removed the target_clones attribute and fmv_test ends up being a global Text symbol (also pasted below), which builds fine: nm -s fmv-test.a Archive index: main in main.o fmv_test in main.o fmv_test.resolver in main.o fmv_normal_function in fmv-test.o fmv_test.resolver in fmv-test.o fmv_test in fmv-test.o main.o: U __cpu_indicator_init U __cpu_model i fmv_test U fmv_test.avx.1 U fmv_test.avx2.0 U fmv_test.default.4 W fmv_test.resolver U fmv_test.sse2.3 U fmv_test.sse4_1.2 U _GLOBAL_OFFSET_TABLE_ T main U malloc U memset fmv-test.o: U __cpu_indicator_init U __cpu_model 004d T fmv_normal_function i fmv_test 00a8 t fmv_test.avx.1 005b t fmv_test.avx2.0 t fmv_test.default.4 W fmv_test.resolver 0142 t fmv_test.sse2.3 00f5 t fmv_test.sse4_1.2 U _GLOBAL_OFFSET_TABLE_ This is when fmv_test is defined without target_clones attribute: Archive index: main in main.o fmv_test in fmv-test.o fmv_normal_function in fmv-test.o main.o: U fmv_test U _GLOBAL_OFFSET_TABLE_ T main U malloc U memset fmv-test.o: 004d T fmv_normal_function T fmv_test