Bug 104895 - lto1: issue with space in library filename
Summary: lto1: issue with space in library filename
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: lto (show other bugs)
Version: 12.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: link-failure, lto
Depends on:
Blocks:
 
Reported: 2022-03-12 15:09 UTC by Christoph Müllner
Modified: 2023-06-07 18:45 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-03-14 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Christoph Müllner 2022-03-12 15:09:00 UTC
When building Souffle, I ran into an LTO issue with a library that contains a space in its filename (see https://github.com/souffle-lang/souffle/issues/2214).

I've isolated the issue as follows (Fedora 35: gcc (GCC) 11.2.1 20220127 (Red Hat 11.2.1-9)):

Makefile:
CC=gcc
CFLAGS=-fPIC
CFLAGS:=$(CFLAGS) -flto=auto
RM=rm -f
all: ltomain

"lib do it".so: doit.o
	$(CC) $(CFLAGS) $(LDFLAGS) -shared -Wl,-soname,"lib'do it'.so" -o "lib'do it'.so" doit.o

ltomain: main.o "lib do it".so
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ main.o -L. -l"'do it'"
clean:
	$(RM) *.o *.so ltomain

doit.c:
#include <stdio.h>
void doit(void)
{
  printf("Hello world!\n");
}
void doit();

main.c:
int main()
{
  doit();
}

This gives the following error:
$ make clean all
rm -f *.o *.so ltomain
gcc -fPIC -flto=auto   -c -o main.o main.c
gcc -fPIC -flto=auto   -c -o doit.o doit.c
gcc -fPIC -flto=auto  -shared -Wl,-soname,"lib'do it'.so" -o "lib'do it'.so" doit.o
lto1: error: open it.so. failed: No such file or directory
make[1]: *** [/tmp/ccetIqO9.mk:2: /tmp/ccIqDtkB.ltrans0.ltrans.o] Error 1
lto-wrapper: fatal error: make returned 2 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
make: *** [Makefile:9: "lib] Error 1

Replacing '-flto=auto' by '-flto' works:
$ make clean all
rm -f *.o *.so ltomain
gcc -fPIC -flto   -c -o main.o main.c
gcc -fPIC -flto   -c -o doit.o doit.c
gcc -fPIC -flto  -shared -Wl,-soname,"lib'do it'.so" -o "lib'do it'.so" doit.o
gcc -fPIC -flto  -shared -Wl,-soname,"lib'do it'.so" -o "lib'do it'.so" doit.o
gcc -fPIC -flto  -shared -Wl,-soname,"lib'do it'.so" -o "lib'do it'.so" doit.o
gcc -fPIC -flto  -o ltomain main.o -L. -l"'do it'"

$ LD_LIBRARY_PATH=. ./ltomain
Hello world!
Comment 1 Christoph Müllner 2022-03-12 17:55:17 UTC
Compiling with '-v' shows the following differences:

BAD:
gcc -v -fPIC -flto=auto  -shared -Wl,-soname,"lib'do it'.so" -o "lib'do it'.so" doit.o
[...]
COLLECT_GCC_OPTIONS='-v' '-fPIC' '-flto=auto' '-shared' '-o' 'lib'\''do it'\''.so' '-mtune=generic' '-march=x86-64' '-dumpdir' 'lib'\''do it'\''.so.'
[...]
COLLECT_GCC_OPTIONS='-c' '-fno-openmp' '-fno-openacc' '-fcf-protection=none' '-v' '-fPIC' '-shared' '-mtune=generic' '-march=x86-64'   '-fltrans-output-list=/tmp/ccfiSKsT.ltrans.out' '-fwpa=16' '-fresolution=/tmp/ccOyShqf.res' '-flinker-output=dyn'
[...]
COLLECT_GCC_OPTIONS='-c' '-fno-openmp' '-fno-openacc' '-fcf-protection=none' '-v' '-fPIC' '-shared' '-mtune=generic' '-march=x86-64'   '-fltrans-output-list=/tmp/ccfiSKsT.ltrans.out' '-fwpa=16' '-fresolution=/tmp/ccOyShqf.res' '-flinker-output=dyn' '-dumpdir' './lib'\''do it'\''.so.wpa.'
make -f /tmp/ccNUrSeQ.mk -j16 all
[...]
COLLECT_GCC_OPTIONS='-c' '-fno-openmp' '-fno-openacc' '-fcf-protection=none' '-v' '-fPIC' '-shared' '-mtune=generic' '-march=x86-64'   '-fltrans' '-o' '/tmp/ccfiSKsT.ltrans0.ltrans.o' '-dumpdir' './libdo-'
 /usr/libexec/gcc/x86_64-redhat-linux/11/lto1 -quiet -dumpdir ./libdo- -dumpbase ccfiSKsT.ltrans0.ltrans. -dumpbase-ext . -mtune=generic -march=x86-64 -version -fno-openmp -fno-openacc -fcf-protection=none -fPIC -fltrans it.so. it.so.ltrans0.ltrans /tmp/ccfiSKsT.ltrans0.o -o /tmp/ccCtIFo1.s
[...]

GOOD:
gcc -v -fPIC -flto  -shared -Wl,-soname,"lib'do it'.so" -o "lib'do it'.so" doit.o
[...]
COLLECT_GCC_OPTIONS='-v' '-fPIC' '-flto' '-shared' '-o' 'lib'\''do it'\''.so' '-mtune=generic' '-march=x86-64' '-dumpdir' 'lib'\''do it'\''.so.'
[...]
COLLECT_GCC_OPTIONS='-c' '-fno-openmp' '-fno-openacc' '-fcf-protection=none' '-v' '-fPIC' '-shared' '-mtune=generic' '-march=x86-64'   '-fltrans-output-list=/tmp/ccMA9joX.ltrans.out' '-fwpa' '-fresolution=/tmp/cceTYxPV.res' '-flinker-output=dyn'
[...]
COLLECT_GCC_OPTIONS='-c' '-fno-openmp' '-fno-openacc' '-fcf-protection=none' '-v' '-fPIC' '-shared' '-mtune=generic' '-march=x86-64'   '-fltrans-output-list=/tmp/ccMA9joX.ltrans.out' '-fwpa' '-fresolution=/tmp/cceTYxPV.res' '-flinker-output=dyn' '-dumpdir' './lib'\''do it'\''.so.wpa.'
[...]
COLLECT_GCC_OPTIONS='-c' '-fno-openmp' '-fno-openacc' '-fcf-protection=none' '-v' '-fPIC' '-shared' '-mtune=generic' '-march=x86-64'   '-fltrans' '-o' '/tmp/ccMA9joX.ltrans0.ltrans.o'
 /usr/libexec/gcc/x86_64-redhat-linux/11/lto1 -quiet -dumpbase ./lib'do it'.so.ltrans0.ltrans -mtune=generic -march=x86-64 -version -fno-openmp -fno-openacc -fcf-protection=none -fPIC -fltrans @/tmp/ccpufIq0 -o /tmp/ccyVUMgZ.s

The first three differences look ok:
In the good case we have '-fwpa', and in the base case '-fwpa=16', which looks sane.

In the last diff we can see a wrong behaviour:

In the good case we have:
* '-dumpbase ./lib'do it'.so.ltrans0.ltrans', and
* '-fltrans it.so. it.so.ltrans0.ltrans /tmp/ccfiSKsT.ltrans0.o'

In the bad case we have:
* '-dumpdir ./libdo- -dumpbase ccfiSKsT.ltrans0.ltrans. -dumpbase-ext .'
* '-fltrans @/tmp/ccpufIq0 -o /tmp/ccyVUMgZ.s'
Comment 2 Christoph Müllner 2022-03-12 20:51:45 UTC
Further analysis shows that '-flto=1' works as well and '-flto=16' fails as well.

This brings us right to the spot:

Bad:
[...]
make -f /tmp/ccyzs8VX.mk -j16 all
Using built-in specs.
[...]

Good:
[...]
gcc @/tmp/cclqDb0Y
Using built-in specs.
[...]

Let's look deeper:
$ mkdir tmpdir
$ export TEMP=$(pwd)/tmpdir/
$ gcc -v -fPIC -flto=16  -shared -Wl,-soname,"lib'do it'.so" -o "lib'do it'.so" doit.o -save-temps
$ cat tmpdir/ccM8aNK8.mk 
./lib'do it'.so.ltrans0.ltrans.o:
	@gcc  '-xlto' '-c' '-fno-openmp' '-fno-openacc' '-fcf-protection=none' '-mtune=generic' '-march=x86-64' '-fPIC' '-v' '-fPIC' '-shared' '-save-temps' '-mtune=generic' '-march=x86-64' '-dumpdir' 'lib'do it'.so.' '-dumpbase' './lib'do it'.so.ltrans0.ltrans' '-fltrans' '-o' './lib'do it'.so.ltrans0.ltrans.o' './lib'do it'.so.ltrans0.o'
.PHONY: all
all: \
	./lib'do it'.so.ltrans0.ltrans.o

The invocation of GCC will be:
gcc  '-xlto' '-c' '-fno-openmp' '-fno-openacc' '-fcf-protection=none' '-mtune=generic' '-march=x86-64' '-fPIC' '-v' '-fPIC' '-save-temps' '-shared' '-mtune=generic' '-march=x86-64' '-dumpdir' 'libdon't do it.so.' '-dumpbase' './libdon't do it.so.ltrans0.ltrans' '-fltrans' '-o' './libdon't do it.so.ltrans0.ltrans.o' './libdon't do it.so.ltrans0.o'

And here we see the issue!
The options are each quoted with '-characters. But the filename itself contains these characters as well, which will terminate the string. The space between the '-characters will therefore be interpreted as a separator.

One thing to mention is that GNU Make has limitations how to handle spaces: http://savannah.gnu.org/bugs/?712
Comment 3 Andrew Pinski 2022-03-13 07:43:33 UTC
White spaces and even special characters will always be a problem with anything that interacts with make or the shell.
I am not saying this is not a fixable issue, just fixing this might even require huge changes to way POSIX make works.
Comment 4 Richard Biener 2022-03-14 08:39:49 UTC
Confirmed (you analyzed it well).  A fix would be welcome but not sure if it's easy enough to do - it's just arguments to a rule, not inputs / outputs so I think it should be possible to apply appropriate quoting somehow.