DCIT / perl-CryptX

https://metacpan.org/pod/CryptX
Other
35 stars 23 forks source link

Compile "ar" step fails when Perl built with -flto #32

Closed kentfredric closed 7 years ago

kentfredric commented 7 years ago

When perl 5.24.1 is compiled with -flto

Compile stage emits:

ar: ltc/ciphers/aes/aes.o: plugin needed to handle lto object
ar: ltc/ciphers/anubis.o: plugin needed to handle lto object
ar: ltc/ciphers/blowfish.o: plugin needed to handle lto object
ar: ltc/ciphers/camellia.o: plugin needed to handle lto object
ar: ltc/ciphers/cast5.o: plugin needed to handle lto object
...

And tests fail:

PERL_DL_NONLAZY=1 "/usr/bin/perl" "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
Can't load '/var/tmp/portage/dev-perl/CryptX-0.44.0/work/CryptX-0.044/blib/arch/auto/CryptX/CryptX.so' for module CryptX: /var/tmp/portage/dev-perl/CryptX-0.44.0/work/CryptX-0.044/blib/arch/auto/CryptX/CryptX.so: undefined symbol: saferp_desc at /usr/lib64/perl5/5.24.1/x86_64-linux/DynaLoader.pm line 193.
 at t/001_compile.t line 11.
Compilation failed in require at t/001_compile.t line 11.
BEGIN failed--compilation aborted at t/001_compile.t line 11.
Could not load all modules at t/001_compile.t line 9.
END failed--call queue aborted at t/001_compile.t line 11.
# Looks like your test exited with 22 before it could output anything.
t/001_compile.t ..................... Dubious, test returned 22 (wstat 5632, 0x1600)

This may be related to compiling perl with GCC6, which itself needed this patch to work: https://raw.githubusercontent.com/gentoo-perl/perl-patchset/perl-5.24/patches/gentoo/gcc6-lto-configure.diff

However, switching back to GCC5 to compile CryptX does not resolve the problem.

Its not clear at this stage to me where the problem lies, but it may be partly --as-needed also to blame.

But I'd hazard to guess that the missing symbol being saferp_desc indicates a link-ordering or symbol visibility bug.

I don't have much experience with LTO bugs , and I only test this configuration now because an end-user of ours reported it: https://bugs.gentoo.org/583532 , some reports indicate the issue is using "ar" instead of "gcc-ar", but I'm not sure where that comes from ( http://stackoverflow.com/questions/39236917/using-gccs-link-time-optimization-with-static-linked-libraries )

This may even be a bug for EUMM as I've seen a similar compile error to this in the last week

Summary of my perl5 (revision 5 version 24 subversion 1) configuration:

  Platform:
    osname=linux, osvers=4.8.5-gentoo, archname=x86_64-linux
    uname='linux katipo2 4.8.5-gentoo #43 smp preempt tue nov 1 19:41:26 nzdt 2016 x86_64 intel(r) core(tm) i5-2410m cpu @ 2.30ghz genuineintel gnulinux '
    config_args='-des -Dinstallprefix=/usr -Dinstallusrbinperl=n -Di_ndbm -Di_gdbm -Di_db -DDEBUGGING=none -Dinc_version_list=5.24.0/x86_64-linux 5.24.0  -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64 -Dnoextensions=ODBM_File -Duseshrplib -Darchname=x86_64-linux -Dcc=x86_64-pc-linux-gnu-gcc -Doptimize=-O2 -pipe -mtune=native -march=native -fstack-protector-strong -fno-stack-protector -flto -Dldflags=-Wl,-O1 -Wl,--as-needed -fstack-protector-strong -fno-stack-protector -flto -Dprefix=/usr -Dsiteprefix=/usr/local -Dvendorprefix=/usr -Dscriptdir=/usr/bin -Dprivlib=/usr/lib64/perl5/5.24.1 -Darchlib=/usr/lib64/perl5/5.24.1/x86_64-linux -Dsitelib=/usr/local/lib64/perl5/5.24.1 -Dsitearch=/usr/local/lib64/perl5/5.24.1/x86_64-linux -Dvendorlib=/usr/lib64/perl5/vendor_perl/5.24.1 -Dvendorarch=/usr/lib64/perl5/vendor_perl/5.24.1/x86_64-linux -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dvendorman1dir=/usr/share/man/man1 -Dvendorman3dir=/usr/share/man/man3 -Dman1ext=1 -Dman3ext=3pm -Dlibperl=libperl.so.5.24.1 -Dlocincpth=/usr/include  -Dglibpth=/lib64 /usr/lib64  -Duselargefiles -Dd_semctl_semun -Dcf_by=Gentoo -Dmyhostname=localhost -Dperladmin=root@localhost -Ud_csh -Dsh=/bin/sh -Dtargetsh=/bin/sh -Uusenm -Di_ndbm -Di_gdbm -Di_db -DDEBUGGING=none -Dinc_version_list=5.24.0/x86_64-linux 5.24.0  -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64 -Dnoextensions=ODBM_File'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='x86_64-pc-linux-gnu-gcc', ccflags ='-fstack-protector-strong -fno-stack-protector -DPERL_HASH_FUNC_SDBM -DPERL_DISABLE_PMC -fwrapv -fno-strict-aliasing -pipe -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -pipe -mtune=native -march=native -fstack-protector-strong -fno-stack-protector -flto',
    cppflags='-fstack-protector-strong -fno-stack-protector -DPERL_HASH_FUNC_SDBM -DPERL_DISABLE_PMC -fwrapv -fno-strict-aliasing -pipe'
    ccversion='', gccversion='5.4.0', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678, doublekind=3
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16, longdblkind=3
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='x86_64-pc-linux-gnu-gcc', ldflags ='-Wl,-O1 -Wl,--as-needed -fstack-protector-strong -fno-stack-protector -flto'
    libpth=/usr/local/lib64 /lib64 /usr/lib64 /usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/include-fixed /usr/lib /lib/../lib64 /usr/lib/../lib64 /lib
    libs=-lpthread -lnsl -lndbm -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.24.so, so=so, useshrplib=true, libperl=libperl.so.5.24.1
    gnulibc_version='2.24'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -pipe -mtune=native -march=native -fstack-protector-strong -fno-stack-protector -flto -Wl,-O1 -Wl,--as-needed -fstack-protector-strong -fno-stack-protector -flto'

Characteristics of this binary (from libperl): 
  Compile-time options: HAS_TIMES PERLIO_LAYERS PERL_COPY_ON_WRITE
                        PERL_DISABLE_PMC PERL_DONT_CREATE_GVSV
                        PERL_HASH_FUNC_SDBM PERL_MALLOC_WRAP
                        PERL_PRESERVE_IVUV USE_64_BIT_ALL USE_64_BIT_INT
                        USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE
                        USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_LOCALE_TIME
                        USE_PERLIO USE_PERL_ATOF
  Locally applied patches:
    gentoo/hints_hpux - Fix hpux hints
    gentoo/aix_soname - aix gcc detection and shared library soname support
    gentoo/EUMM-RUNPATH - https://bugs.gentoo.org/105054 cpan/ExtUtils-MakeMaker: drop $PORTAGE_TMPDIR from LD_RUN_PATH
    gentoo/config_over - Remove -rpath and append LDFLAGS to lddlflags
    gentoo/opensolaris_headers - Add headers for opensolaris
    gentoo/patchlevel - List packaged patches for perl-5.24.1-r1(#3) in patchlevel.h
    gentoo/cleanup-paths - Cleanup PATH and shrpenv
    gentoo/enc2xs - Tweak enc2xs to follow symlinks and ignore missing @INC directories.
    gentoo/darwin-cc-ld - https://bugs.gentoo.org/297751 darwin: Use $CC to link
    gentoo/cpan_definstalldirs - Provide a sensible INSTALLDIRS default for modules installed from CPAN.
    gentoo/interix - Fix interix hints
    gentoo/create_libperl_soname - https://bugs.gentoo.org/286840 Set libperl soname
    gentoo/mod_paths - Add /etc/perl to @INC
    gentoo/EUMM_perllocalpod - cpan/ExtUtils-MakeMaker: remove targets that generate perllocal.pod
    gentoo/drop_fstack_protector - https://bugs.gentoo.org/348557 Don't force -fstack-protector on everyone
    gentoo/usr_local - Configure: Don't include sources in /usr/local/ for compiling perl
    gentoo/D-SHA-CFLAGS - https://bugs.gentoo.org/506818 Do not set custom CFLAGS in cpan/Digest-SHA
    gentoo/io_socket_ip_tests - cpan/IO-Socket-IP: Disable network tests
    gentoo/cygwin-libperl - Cygwin: avoid libperl.dll.dll.a
    gentoo/tests - Fixup EUMM perlocal.pod tests and customised SHA1s
    gentoo/basepm-dot-inc - base.pm: Protect against . in @INC
    gentoo/zlib-1.2.9-backported-fixes - [rt#119762] Compress-Raw-Zlib: backport zlib 1.2.9+ fixes from upstream 2.073
    gentoo/gcc6-lto-configure - [RT#128131] fix symbol detection with gcc 6 link-time optimization
    debian/cpan-missing-site-dirs - Fix CPAN::FirstTime defaults with nonexisting site dirs if a parent is writable
    debian/makemaker-pasthru - Pass LD settings through to subdirectories
    fixes/memoize_storable_nstore - [rt.cpan.org #77790] Memoize::Storable: respect 'nstore' option not respected
    fixes/podman-pipe - Better errors for man pages from standard input
    fixes/respect_umask - Respect umask during installation
    fixes/net_smtp_docs - [rt.cpan.org #36038] Document the Net::SMTP 'Port' option
    fixes/document_makemaker_ccflags - [rt.cpan.org #68613] Document that CCFLAGS should include $Config{ccflags}
    fixes/parallel-manisort.patch - Fix parallel building
  Built under linux
  Compiled at Feb 21 2017 15:37:34
  @INC:
    /etc/perl
    /usr/local/lib64/perl5/5.24.1/x86_64-linux
    /usr/local/lib64/perl5/5.24.1
    /usr/lib64/perl5/vendor_perl/5.24.1/x86_64-linux
    /usr/lib64/perl5/vendor_perl/5.24.1
    /usr/local/lib64/perl5
    /usr/lib64/perl5/vendor_perl/5.24.0
    /usr/lib64/perl5/vendor_perl
    /usr/lib64/perl5/5.24.1/x86_64-linux
    /usr/lib64/perl5/5.24.1
    .
Leont commented 7 years ago

MakeMaker has no concept of LTO, and doesn't take it into account when statically linking a library. Setting the ar/full_ar configuration entries to gcc-ar when enabling -flto should help.

karel-m commented 7 years ago

@kentfredric what's the output of perl -MConfig -E 'say $Config{ar}; say $Config{full_ar}' on the box in question?

kentfredric commented 7 years ago
perl -MConfig -E 'say $Config{ar}; say $Config{full_ar}'
ar
/usr/bin/ar

However, I've tried numerous things getting it to work:

  1. Setting AR=x86_64-pc-linux-gnu-ar ( This is the result of a query function to ask for the users full AR )
  2. Trying to pass CFLAGS like -fno-lto as OPTIMIZE= ( doesn't work because Perl's flags come afterwards, usurping them )
  3. Trying to pass explicit CFLAGS/LDFLAGS to make ( doesn't work because you hardcode perls cflags in the makefile )
  4. Setting AR_STATIC_ARGS="cr --plugin liblto_plugin.so" # this of course doesn't work because the plugin path is not fully qualified, but I don't know how to generically do this on whatever compiler / version the end user has.

None of which have gotten my anywhere

karel-m commented 7 years ago

Could you please try the latest master?

kentfredric commented 7 years ago

Excellent. That works :) :+1:

karel-m commented 7 years ago

fix released as CryptX-0.046

Thanks for your time

karel-m commented 7 years ago

@Leont On some other platforms that might need to be llvm-ar (conjecture, not verified)

what about 86cab48 (removing -flto)?

@kentfredric could you please test again the latest master?

kentfredric commented 7 years ago
 git --no-pager log --oneline -1 
86cab48 remove -flto
git clean -fdx
...
etc
...
All tests successful.
Files=101, Tests=23414, 26 wallclock secs ( 3.85 usr  0.46 sys + 23.24 cusr  1.57 csys = 29.12 CPU)
Result: PASS
karel-m commented 7 years ago

Great!

It seems safer to go this way (stripping -flto).

Leont commented 7 years ago

what about 86cab48 (removing -flto)?

That's sounds safe and sane.

The alternative is that people with -flto in their flags should also have their ar set to match. The default can be fixed in perl core, but that's unlikely to happen before 5.28. I'm expecting this sort of issue nt to be unique to this distribution.

karel-m commented 7 years ago

released as CryptX-0.047

rurban commented 6 years ago

FYI I've just fixed this now in cperl: Required changes were on Configure to properly set the arflags (with the full plugin path), and the llvm-ar, plus EUMM to set AR_STATIC_ARGS to be based on arflags, not hardcoded to 'cr'.

perl5 is totally not lto ready, cperl just switched now to -flto by default. So you were right to strip -flto.

todd-richmond commented 1 year ago

you can work around this in modern perls by changing compile flags for perl itself to set config correctly. I'm able to build perl and 800 cpan modules with LTO

Configure -ders -Accflags='-Dar=gcc-ar -Dnm=gcc-nm ...'

rurban commented 1 year ago

I've fixed that in cperl, btw

todd-richmond commented 1 year ago

I've been able to get both perl interpreter and cpan modules to compile with LTO and our own optimization flags. The only one out of 800 I had a problem with is URI::XS because it uses CMake and I can't figure out how to configure ranlib to be gcc-ranlib. Perl Config sets it to ':' unlike nm/ar and setting it to a real value causes mod_perl build to fail

Unfortunately cperl is too many revs back since we try to keep up to the latest, even when we don't necessarily use modern features. We are migrating to signatures and 'use v5.36' implicit warnings/strict though. 5.38 has some perf improvements too

Perf is our biggest concern so are there any commits that makes substantial improvements w/o breaking compatibility? We can patch our builds and have taken a few early fixes (not failing on int wrap and fixing resource copying on clones for example)