[Bug c/91664] New: Undefined reference linker errors when static linking archive with gcc target_clones function multi-versioning

2019-09-04 Thread element at elementsofsound dot org
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

2019-09-04 Thread element at elementsofsound dot org
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

2019-09-04 Thread element at elementsofsound dot org
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

2019-09-04 Thread element at elementsofsound dot org
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

2019-09-04 Thread element at elementsofsound dot org
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