weidai11 / cryptopp

free C++ class library of cryptographic schemes
https://cryptopp.com
Other
4.8k stars 1.49k forks source link

Building Crypto++ 7.0.0 fails on POWER4 ( PowerMac G5, Gentoo Linux 2.4.1, gcc 7.3.0) #656

Closed ernsteiswuerfel closed 5 years ago

ernsteiswuerfel commented 6 years ago

I started the build with make -j3, which goes on for a while but errors out at:

g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -c ppc-simd.cpp In file included from ppc-simd.h:23:0, from ppc-simd.cpp:28: /usr/lib/gcc/powerpc64-unknown-linux-gnu/7.3.0/include/altivec.h:34:2: Fehler: #error Use the "-maltivec" flag to enable PowerPC AltiVec support

error Use the "-maltivec" flag to enable PowerPC AltiVec support

^~~~~ In file included from ppc-simd.cpp:28:0: ppc-simd.h:33:9: Fehler: »vector« bezeichnet keinen Typ; meinten Sie »nextup«? typedef vector unsigned char uint8x16_p; ^~~~ nextup ppc-simd.h:34:9: Fehler: »vector« bezeichnet keinen Typ; meinten Sie »nextup«? typedef vector unsigned short uint16x8_p; ^~~~ nextup [...]

See build.log for details.

Machine is a PowerMac G5 11,2 running Gentoo Linux 2.4.1 (ppc64), gcc 7.3.0, glibc 2.25, binutils 2.29.

Here is the build log: build.log.

noloader commented 6 years ago

Thanks @ernsteiswuerfel .

I test on a G5, but it still runs OS X and not Linux. It looks like we are misdetecting something. Here is the area that is blowing up: GNUmakefile : 400.

Let me think about this. For the time being please use CRYPTOPP_DISABLE_ASM. Open config.h and uncomment the line that comments-out the define. It should be around config.h : 60.

Disabling ASM has little effect on a Power4. Power4 lacks the Power8 goodies, so it would kind of fall into that state on its own.

noloader commented 6 years ago

@ernsteiswuerfel,

We reworked a lot of the code around PowerPC recently. The changes include better makefile support, better Autotools support (CMake still does not know PowerPC), and improved source code support. Improved source code support includes Altivec, POWER7 and POWER8 algorithms.

By the way, can you provide remote access to your box? In return I can provide SSH access to a PowerMac running OS X 10.5 and a Solaris 11.3 x86 machine with Sun Studio installed. My SSH keys are at authorized_keys.

Would you mind testing it again?

ernsteiswuerfel commented 6 years ago

Thanks for working on this issue! Just built from git-master, but it errors out similarly (see build.log).

Theoretically I could provide you SSH access to this box if I would know how to do this (got no fixed IP from the outside, reconfiguration of pfSense probably needed). It's not always on either. build.log

noloader commented 6 years ago

Thanks @ernsteiswuerfel,

Yeah, I'm not sure what to make of this (translated to English):

# make -j2
c++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -c cryptlib.cpp
c++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -c cpu.cpp
...

c++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -c cham-simd.cpp
In file included from adv-simd.h: 74: 0,
                 from cham-simd.cpp: 13:
ppc-simd.h: 575: 8: Error: "uint32x4_p" does not designate a type; did you mean uint32_t?
 inline uint32x4_p VectorLoad (const byte src [16])
        ^ ~~~~~~~~~

Absence of -DCRYPTOPP_DISABLE_ALTIVEC, -DCRYPTOPP_DISABLE_POWER7 (and friends) is probably correct. The makefile detected the compiler supports -mcpu=power4 -maltivec, -mcpu=power7 -maltivec, etc. So I am guessing that is correct.

However, the compile line is completely missing the arch flags required for the *-simd.cpp files. The makefile should be adding them and I can't explain why they are not being added:

c++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -c cham-simd.cpp

This is what it is supposed to look like. This is GCC112 from the compile farm. GCC112 is POWER8:

$ make -j 20 | grep simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power7 -maltivec -c aria-simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power7 -maltivec -c blake2-simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power7 -maltivec -c cham-simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -c crc-simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power8 -maltivec -c gcm-simd.cp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power7 -maltivec -c lea-simd.cp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -c neon-simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power4 -maltivec -c ppc-simd.cp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power8 -maltivec -c rijndael-simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power8 -maltivec -c sha-simd.cp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power8 -maltivec -c shacal2-simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power7 -maltivec -c simeck-simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power8 -maltivec -c simon128-simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power7 -maltivec -c simon64-simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power8 -maltivec -c sm4-simd.cp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power8 -maltivec -c speck128-simd.cpp
g++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power7 -maltivec -c speck64-simd.cpp
...

And here is what it looks like on my PowerMac using a MacPorts compiler:

$ CXX=/opt/local/bin/g++-mp-5 make -j 4 | grep simd.cpp
/opt/local/bin/g++-mp-5 -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power7 -maltivec -c aria-simd.cpp
/opt/local/bin/g++-mp-5 -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power7 -maltivec -c blake2-simd.cpp
/opt/local/bin/g++-mp-5 -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power7 -maltivec -c cham-simd.cpp
/opt/local/bin/g++-mp-5 -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -c crc-simd.cpp
...

And here is what it looks like on the PowerMac with the original GCC 4.1 compiler provided by Apple:

$ make
g++ -DNDEBUG -g2 -O3 -DCRYPTOPP_DISABLE_POWER7 -DCRYPTOPP_DISABLE_POWER8 -fPIC -pthread -pipe -c cryptlib.cpp
g++ -DNDEBUG -g2 -O3 -DCRYPTOPP_DISABLE_POWER7 -DCRYPTOPP_DISABLE_POWER8 -fPIC -pthread -pipe -c cpu.cpp
g++ -DNDEBUG -g2 -O3 -DCRYPTOPP_DISABLE_POWER7 -DCRYPTOPP_DISABLE_POWER8 -fPIC -pthread -pipe -c integer.cpp
g++ -DNDEBUG -g2 -O3 -DCRYPTOPP_DISABLE_POWER7 -DCRYPTOPP_DISABLE_POWER8 -fPIC -pthread -pipe -c 3way.cpp
...

Can you post the output of the following? This is what the makefile does to detect features:

$ cp adhoc.cpp.proto adhoc.cpp
$ c++ -dM -E adhoc.cpp | grep -i -E 'pwr|power|arch'
#define _ARCH_PPCGR 1
#define _ARCH_PPCSQ 1
#define _ARCH_PPC 1
#define _ARCH_PWR4 1
#define _ARCH_PWR5 1
#define _ARCH_PWR6 1
#define _ARCH_PWR7 1
#define _ARCH_PWR8 1
#define __powerpc64__ 1
#define __powerpc__ 1
#define _ARCH_PWR5X 1
#define __POWER8_VECTOR__ 1
#define _ARCH_PPC64 1
noloader commented 6 years ago

Theoretically I could provide you SSH access to this box if I would know how to do this (got no fixed IP from the outside, reconfiguration of pfSense probably needed)

Yeah, it is a pain in the ass. I have to do at my house to give others access to the PowerMac and Solaris. You have to enable port forwarding on the router and firewall, and setup an account for me on your Mac. I would hit your box with jwalton@<some ip> -p <some port>. As your IP changes you would have to email it to me. I get an email from folks on occasion asking what my new IP address is as it changes.

ernsteiswuerfel commented 6 years ago

The makefile detected the compiler supports -mcpu=power4 -maltivec, -mcpu=power7 -maltivec, etc. So I am guessing that is correct.

The compiler itself is working very well, since I am running Gentoo on this G5, so everything is built from source. ;-) "-mcpu=power4 -maltivec" would be fine for the G5, as the 970 (G5) is a POWER4-class-CPU. Of course it won't run power5/6/7/8/9 or VSX-SIMD code, but I guess you know that.

$ cp adhoc.cpp.proto adhoc.cpp
$ c++ -dM -E adhoc.cpp | grep -i -E 'pwr|power|arch'
#define CRYPTOPP_POWER8_SHA_AVAILABLE 1
#define _ARCH_PPCGR 1
#define _ARCH_PPCSQ 1
#define _ARCH_PPC 1
#define _BITS_PTHREADTYPES_ARCH_H 1
#define _ARCH_PWR4 1
#define __powerpc64__ 1
#define CRYPTOPP_POWER8_AES_AVAILABLE 1
#define CRYPTOPP_POWER8_AVAILABLE 1
#define __powerpc__ 1
#define CRYPTOPP_POWER8_VMULL_AVAILABLE 1
#define _ASM_POWERPC_ERRNO_H 
#define CRYPTOPP_POWER7_AVAILABLE 1
#define _ARCH_PPC64 1

Yeah, it is a pain in the ass. I have to do at my house to give others access to the PowerMac and Solaris. You have to enable port forwarding on the router and firewall, and setup an account for me on your Mac.

I will try this in a week or so. I am off for GamesCon first. ;-)

noloader commented 6 years ago

OK, so this is a tad bit unusual. I've never seen this particular combination of results:

$ cp adhoc.cpp.proto adhoc.cpp
$ c++ -dM -E adhoc.cpp | grep -i -E 'pwr|power|arch'
#define CRYPTOPP_POWER8_SHA_AVAILABLE 1
#define _ARCH_PPCGR 1
#define _ARCH_PPCSQ 1
#define _ARCH_PPC 1
#define _BITS_PTHREADTYPES_ARCH_H 1
#define _ARCH_PWR4 1
#define __powerpc64__ 1
#define CRYPTOPP_POWER8_AES_AVAILABLE 1
#define CRYPTOPP_POWER8_AVAILABLE 1
#define __powerpc__ 1
#define CRYPTOPP_POWER8_VMULL_AVAILABLE 1
#define _ASM_POWERPC_ERRNO_H 
#define CRYPTOPP_POWER7_AVAILABLE 1
#define _ARCH_PPC64 1

Notice CRYPTOPP_POWER7_AVAILABLE and CRYPTOPP_POWER8_AVAILABLE are defined, but CRYPTOPP_ALTIVE_AVAILABLE is not. Here is the test used for Altivec/Power4 from GNUmakefile:450 or so:

# GCC and some compatibles
HAVE_ALTIVEC = $(shell $(CXX) $(CXXFLAGS) -DADHOC_MAIN -mcpu=power4 -maltivec -dM -E adhoc.cpp 2>&1 | $(GREP) -i -c '__ALTIVEC__')
ifneq ($(HAVE_ALTIVEC),0)
  ALTIVEC_FLAG = -mcpu=power4 -maltivec
endif

It looks like we are dropping the ball on finding __ALTIVEC__.

If we detected Altivec correctly then we may hit another error later. Namely, update compiler claims to do Power7 and Power8, but the library support is missing on the old machines. Or at least that's what I have found on PowerMac with OS X 10.5.

At this point I think you should use this patch for your machine until I can get to the bottom of the Altivec misdetection:

$ git diff
diff --git a/config.h b/config.h
index 2d4f970f..2704fe05 100644
--- a/config.h
+++ b/config.h
@@ -6,6 +6,10 @@
 #ifndef CRYPTOPP_CONFIG_H
 #define CRYPTOPP_CONFIG_H

+#define CRYPTOPP_ALTIVEC_AVAILABLE 1^M
+#define CRYPTOPP_DISABLE_POWER7 1^M
+#define CRYPTOPP_DISABLE_POWER8 1^M
+^M
 // ***************** Important Settings ********************

 // define this if running on a big-endian CPU

Of course it won't run power5/6/7/8/9 or VSX-SIMD code, but I guess you know that.

Yeah, the POWER7 and POWER8 routines are for distros like Debian and Fedora. The routines are guarded at runtime so there should not be an unexpected SIGILL.

In your case you don't need them. Worse, they create an unwanted point of failure that you may encounter.

noloader commented 5 years ago

@ernsteiswuerfel,

We reworked the makefile to use feature-based detection by compiling a test program rather than using toolchain version numbers and preprocessor macros. Also see PR 737, Move to feature-based availability testing in Makefile.

I suspect the change probably cleared this issue for you. Can you retest with Master, please?

ernsteiswuerfel commented 5 years ago

Thanks for the update! But can't tell if this fixes the bug. Now git-master runs into another problem:

blake2b_simd.cpp:745:8: Fehler: »uint64x2_p« bezeichnet keinen Typ; meinten Sie »uint64_t«?
 inline uint64x2_p VecLoad64(const void* p)
        ^~~~~~~~~~
        uint64_t
blake2b_simd.cpp:754:8: Fehler: »uint64x2_p« bezeichnet keinen Typ; meinten Sie »uint64_t«?
 inline uint64x2_p VecLoad64LE(const void* p)
[...]

See build.log

Machine is a PowerMac G5 7,3 running Gentoo Linux 2.6 (ppc64), gcc 7.3.0, glibc 2.27, binutils 2.30.

noloader commented 5 years ago

@ernsteiswuerfel,

Oh man... It just occurred to me. Your system is not using English. But it is failing in a way I would not expect.

Based on this:

c++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -c blake2b_simd.cpp
blake2b_simd.cpp:745:8: Fehler: »uint64x2_p« bezeichnet keinen Typ; meinten Sie »uint64_t«?
 inline uint64x2_p VecLoad64(const void* p)
        ^~~~~~~~~~
        uint64_t
blake2b_simd.cpp:754:8: Fehler: »uint64x2_p« bezeichnet keinen Typ; meinten Sie »uint64_t«?
 inline uint64x2_p VecLoad64LE(const void* p)
        ^~~~~~~~~~
        uint64_t

We are mis-detecting availability (again). blake2b_simd.cpp should have -mcpu=power{n} -maltivec. In your case, it is an old G5 so the flags should be -DCRYPTOPP_DISABLE_POWER7 -mcpu=power8 -maltivec. It may look odd, but CRYPTOPP_DISABLE_POWER7 will exclude the code so the extra options don't matter.

Can you run the following from the command line and post the output. They are basic C++ flags (like -g2 -O3) with arch flags (like -mcpu=power4):

PowerMac:cryptopp$ c++ -DNDEBUG -g2 -O3 -fPIC -pthread -mcpu=power4 -maltivec TestPrograms/test_ppc_altivec.cxx
PowerMac:cryptopp$ c++ -DNDEBUG -g2 -O3 -fPIC -pthread -mcpu=power5 -maltivec TestPrograms/test_ppc_altivec.cxx
PowerMac:cryptopp$ c++ -DNDEBUG -g2 -O3 -fPIC -pthread -mcpu=power6 -maltivec TestPrograms/test_ppc_altivec.cxx
TestPrograms/test_ppc_altivec.cxx:1: error: bad value (power6) for -mcpu= switch
PowerMac:cryptopp$ c++ -DNDEBUG -g2 -O3 -fPIC -pthread -mcpu=power7 -maltivec TestPrograms/test_ppc_altivec.cxx
TestPrograms/test_ppc_altivec.cxx:1: error: bad value (power7) for -mcpu= switch

Ultimately, the bad value is detected in the makefile and that's where -DCRYPTOPP_DISABLE_POWER7 comes from. Also see the variable BAD_RESULT around GNUmakefile : 200:

BAD_RESULT="fatal|error|unknown|unrecognized|illegal|ignored|incorrect|not found|not exist|
cannot find|not supported|not compatible|no such instruction|invalid mnemonic"

Earlier I said "... it is failing in a way I would not expect". That's because we are not detecting German language failures. But for this case, it should mean we miss the failure and add the flags anyway (which is not happening).

ernsteiswuerfel commented 5 years ago

Can you run the following from the command line and post the output. They are basic C++ flags (like -g2 -O3) with arch flags (like -mcpu=power4):

T800 ~/build/cryptopp # c++ -DNDEBUG -g2 -O3 -fPIC -pthread -mcpu=power4 -maltivec TestPrograms/test_ppc_altivec.cxx

T800 ~/build/cryptopp # c++ -DNDEBUG -g2 -O3 -fPIC -pthread -mcpu=power5 -maltivec TestPrograms/test_ppc_altivec.cxx

T800 ~/build/cryptopp # c++ -DNDEBUG -g2 -O3 -fPIC -pthread -mcpu=power6 -maltivec TestPrograms/test_ppc_altivec.cxx

T800 ~/build/cryptopp # c++ -DNDEBUG -g2 -O3 -fPIC -pthread -mcpu=power7 -maltivec TestPrograms/test_ppc_altivec.cxx

They show no output at all.

The logic of the script would be correct to go for -mcpu=power4 -maltive for a G5. How would it rate a G4? I use my PowerBook G4 regularly as it's still my main laptop. ;)

noloader commented 5 years ago

They show no output at all.

This should mean your toolchain (CC, CXX, AS and LD) supports all of the arch flags. I would expect this for a modern toolchain.

I'm guessing we are mis-detecting PPC platform, so you never enter the PPC block where the arch flags are added. That is done in GNUmakefile : 50.

# Line 50 or so
IS_PPC32 := $(shell echo "$(HOSTX)" | $(GREP) -v "64" | $(GREP) -i -c -E 'ppc|power')
IS_PPC64 := $(shell echo "$(HOSTX)" | $(GREP) -i -c -E 'ppc64|power64')

Can you add the following around line 60 or so after IS_PPC32 and IS_PPC64 are set and post the results?

$(info HOSTX: $(HOSTX))
$(info IS_PPC32: $(IS_PPC32))
$(info IS_PPC64: $(IS_PPC64))
noloader commented 5 years ago

@ernsteiswuerfel,

I think I found the problem. It took me several days but I got Clang built for GCC112 on the GCC Compile Farm. I was finally able to exercise the compiler.

A run under Clang showed clang++ -dumpmachine returned powerpc64. We were not checking for that target. Here's the fix for the mis-identification: Commit aae108d2284d.

Clang 7.0 does not appear to implement crypto. I can't get it to accept either __vcipher or __builtin_crypto_vcipher (and friends). It appears to be a major oversight on LLVM's part. It is going to take several hours to find out what works and get the tests aligned correctly.

It looks like LLVM's Clang changed which type of intrinsics it is willing to accept. Sometimes it accept's XLC-style, and sometimes it accepts GCC-style. And it uses the same preprocessor macros when it masquerades as other compilers so we can't really tell which to use at the moment.

ernsteiswuerfel commented 5 years ago

Thansk! I can confirm your commit fixes the build issue. I suppose this bug will also be present on my G4 machines, which woulde be fixed by adding powerpc to the 32 bit ppc detection. Though I have to try yet.

However during the build I see messages like

c++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power8 -maltivec -c blake2b_simd.cpp
c++ -DNDEBUG -g2 -O3 -fPIC -pthread -pipe -mcpu=power7 -maltivec -c blake2s_simd.cpp

Should this not be -mcpu=power4 on my G5?

The test suite seems fine:

Testing Settings...

passed:  Your machine is big endian.
passed:  Aligned data access.
passed:  sizeof(byte) == 1
passed:  sizeof(word16) == 2
passed:  sizeof(word32) == 4
passed:  sizeof(word64) == 8
passed:  sizeof(word128) == 16
passed:  sizeof(hword) == 4, sizeof(word) == 8, sizeof(dword) == 16
passed:  cacheLineSize == 128
passed:  hasAltivec == 1, hasPower7 == 0, hasPower8 == 0, hasPMULL == 0, hasAES == 0, hasSHA256 == 0, hasSHA512 == 0

But Blake2s is the first test that errors out due to unknown instruction:

BLAKE2s validation suite running...

passed   algorithm name
TestScripts/cryptest-cmake.sh: Zeile 60:  3720 Ungültiger Maschinenbefehl   (Speicherabzug geschrieben) ./cryptest.exe v
cryptest.exe v failed
noloader commented 5 years ago

@ernsteiswuerfel,

I suppose this bug will also be present on my G4 machines

Your G4 machine should be OK for the platform detection (IS_PPC32 and IS_PPC64) since we only look for ppc|power.

But Blake2s is the first test that errors out due to unknown instruction ...

I believe this is the language bug in the makefile. This is the [symptom of the] error I expected earlier.

We are working the language bug at Issue 741. It was opened when we saw some of your compiler diagnostics.

I'm going to close this issue since we fixed the problem that kept you out of the PPC blocks. We will continue with the illegal instruction problem over at Issue 741.

noloader commented 5 years ago

Should this not be -mcpu=power4 on my G5?

OK, this is a different issue. I believe this should fix it for BLAKE2s: Commit 59ba3b6aca10.

ChaCha follows the same pattern as BLAKE2s and it will probably fail with an illegal instruction, too. I'll get to that next. I believe ChaCha was cleared at Commit e28b2e0f02df.


The way the makefile works is, it looks at the toolchain and selects the highest ISA it can find. Since your toolchain is is modern it selects POWER7 and POWER8. But that's not helpful for old hardware like yours. Usually the story ends here.

However, in the case of BLAKE2s and ChaCha we get clever and drop from POWER7 to POWER4 if POWER7 is not available. Our cleverness introduced the illegal instruction bug because it had a logic bug.

What you need to do for this case is manually add -DCRYPTOPP_DISABLE_POWER7 (is there a -mno-power7 in Clang?) to CXXFLAGS.

noloader commented 5 years ago

@ernsteiswuerfel,

I'm testing the fix for the language problem from Issue 741 at Commit 1ac7207545f3. The 1ac7207545f3 commit is limited to PowerPC only.

Would you mind giving it a try?

("PowerPC only" is not all that limited. For us, it covers (1) AIX, Linux and OS X operation systems; (2) Apple, Clang, IBM, and GCC compilers; and (3) POWER4, POWER7 and POWER8. It gets a lot of exercise).