ARM Embedded (Command Line)

From Crypto++ Wiki
Jump to navigation Jump to search

This page will provide instructions for cross-compiling Crypto++ with Ubuntu's GNU C++ compiler for armel architecture. The tools are available in the g++-arm-linux-gnueabi and gcc-arm-linux-gnueabi packages.

There are four steps to building Crypto++ for embedded targets, and the process will create an embedded ARM version of cryptest.exe, the dynamic library, and the static library. After building the library, you can push cryptest.exe and the test vectors to the device. Once on the device, you can then execute the tests using a remote shell. The example below builds for the Cortex-M3 processor using the arm-linux-gnueabi toolchain.

Note: setenv-embedded.sh was added to the library sources in March 2016. It is available in Git and library ZIP files after 5.6.3. Also see Commit 22d6374ce7151ad0, Added Android and embedded environment and test script. If you are build for Android or iOS, then there are separate pages for the platforms. The pages use the toolchains provided by AOSP and Apple. See Android (Command Line) and iOS (Command Line) for details. Also see ARM (Command Line) and ARM Embedded (Bare Metal) if building with the arm-linux-gnueabi toolchain.

Note: the instructions below used to work with Ubuntu 12 or so. Ubuntu 14 and Ubuntu 16 appears to have toolschain problems. The toolchain cannot link an executable; also see Issue 565, Cross Compile for ARM Failure in the Crypto++ bug tracker. Please open bugs against package gcc-arm-linux-gnueabihf or g++-arm-linux-gnueabihf at Ubuntu Launchpad.

Install the Package

Installing the package is as simple as installing g++-arm-linux-gnueabi and gcc-arm-linux-gnueabi.

sudo apt-get update
sudo apt-get install g++-arm-linux-gnueabi gcc-arm-linux-gnueabi

Set the Environment

Before you begin you must set the cross-compilation environment. Setting the environment will do two things. First, it will ensure the arm-linux-gnueabi toolchain is on-path. Second, it will ensure some environmental variables are set so the makefile picks up specific device flags. For example, the script will set IS_ARM_EMBEDDED, ARM_EMBEDDED_FLAGS and ARM_EMBEDDED_SYSROOT.

Perform the following to run the script. The source command is required to make changes to the current shell.

$ source ./setenv-embedded.sh 
CPP: /usr/bin/arm-linux-gnueabi-cpp
CXX: /usr/bin/arm-linux-gnueabi-g++
AR: /usr/bin/arm-linux-gnueabi-ar
LD: /usr/bin/arm-linux-gnueabi-ld
RANLIB: /usr/bin/arm-linux-gnueabi-ranlib
ARM_EMBEDDED_TOOLCHAIN: /usr/bin
ARM_EMBEDDED_CXX_HEADERS: /usr/arm-linux-gnueabi/include/c++/5.4.0
ARM_EMBEDDED_FLAGS: -I/usr/arm-linux-gnueabi/include/c++/5.4.0 -I/usr/arm-linux-gnueabi/include/c++/5.4.0/arm-linux-gnueabi
ARM_EMBEDDED_SYSROOT: /usr/arm-linux-gnueabi

You can tune the ARM_EMBEDDED_FLAGS by opening setenv-embedded.sh, scrolling down to line 100 or so, and changing the block below.

if [ -z "$ARM_EMBEDDED_FLAGS" ]; then
  export ARM_EMBEDDED_FLAGS="-I$ARM_EMBEDDED_CXX_HEADERS -I$ARM_EMBEDDED_CXX_HEADERS/arm-linux-gnueabi"
fi

Build the Library

Cryptopp-embedded-01.png

Building the library consists of running the following command after setting the environment:

$ make -f GNUmakefile-cross

If you plan on stripping the dead code, then you should issue make -f GNUmakefile-cross lean. The lean target builds libcryptopp.a, libcryptopp.so and cryptest.exe; and it adds -ffunction-sections -fdata-sections for you. When you link your shared object or application, you will still need to add -Wl,--gc-sections to perform the stripping of the dead code from the final executable.

$ make -f GNUmakefile-cross static static dynamic cryptest.exe
/usr/bin/arm-linux-gnueabi-g++ -DNDEBUG -g2 -Os -pipe -fPIC -DCRYPTOPP_DISABLE_ASM
-mthumb -mcpu=cortex-m3 -I/usr/arm-linux-gnueabi/include/c++/4.7.3 -I/usr/arm-linux-gnueabi/
include/c++/4.7.3/arm-linux-gnueabi --sysroot=/usr/arm-linux-gnueabi -c 3way.cpp
/usr/bin/arm-linux-gnueabi-g++ -DNDEBUG -g2 -Os -pipe -fPIC -DCRYPTOPP_DISABLE_ASM
-mthumb -mcpu=cortex-m3 -I/usr/arm-linux-gnueabi/include/c++/4.7.3 -I/usr/arm-linux-gnueabi/
include/c++/4.7.3/arm-linux-gnueabi --sysroot=/usr/arm-linux-gnueabi -c adler32.cpp
/usr/bin/arm-linux-gnueabi-g++ -DNDEBUG -g2 -Os -pipe -fPIC -DCRYPTOPP_DISABLE_ASM
-mthumb -mcpu=cortex-m3 -I/usr/arm-linux-gnueabi/include/c++/4.7.3 -I/usr/arm-linux-gnueabi/
include/c++/4.7.3/arm-linux-gnueabi --sysroot=/usr/arm-linux-gnueabi -c algebra.cpp
...

/usr/bin/arm-linux-gnueabi-g++ -DNDEBUG -g2 -Os -pipe -fPIC -DCRYPTOPP_DISABLE_ASM
-mthumb -mcpu=cortex-m3 -I/usr/arm-linux-gnueabi/include/c++/4.7.3 -I/usr/arm-linux-gnueabi/include/
c++/4.7.3/arm-linux-gnueabi --sysroot=/usr/arm-linux-gnueabi -shared -o libcryptopp.so 3way.o
... vmac.o wait.o wake.o whrlpool.o winpipes.o xtr.o xtrcrypt.o zdeflate.o zinflate.o zlib.o  
...

/usr/bin/arm-linux-gnueabi-g++ -o cryptest.exe -DNDEBUG -g2 -Os -pipe -fPIC
-DCRYPTOPP_DISABLE_ASM -mthumb -mcpu=cortex-m3 -I/usr/arm-linux-gnueabi/include/c++/4.7.3
-I/usr/arm-linux-gnueabi/include/c++/4.7.3/arm-linux-gnueabi --sysroot=/usr/arm-linux-gnueabi
bench.o bench2.o test.o validat1.o validat2.o validat3.o adhoc.o datatest.o regtest.o
fipsalgt.o dlltest.o ./libcryptopp.a

After building the library, check it for architecture:

$ find . -name cryptest.exe
./cryptest.exe
$ /usr/bin/arm-linux-gnueabi-readelf -h ./cryptest.exe | grep -i 'class\|machine' 
  Class:                             ELF32
  Machine:                           ARM

$ find . -name libcryptopp.so
./libcryptopp.so
$ /usr/bin/arm-linux-gnueabi-readelf -h ./libcryptopp.so | grep -i 'class\|machine' 
  Class:                             ELF32
  Machine:                           ARM

Execute the Program

To be determined.

Architecture Options

The following table provides some options to use for ARM_EMBEDDED_FLAGS in setenv-embedded.sh. The table below was shamelessly ripped from Terry Guo's GNU Tools for ARM Embedded Processors README:

+------------------------------------------------------------------+
| ARM Core | Command Line Options                       | multilib |
|----------|--------------------------------------------|----------|
|Cortex-M0+| -mthumb -mcpu=cortex-m0plus                | armv6-m  |
|Cortex-M0 | -mthumb -mcpu=cortex-m0                    |          |
|Cortex-M1 | -mthumb -mcpu=cortex-m1                    |          |
|          |--------------------------------------------|          |
|          | -mthumb -march=armv6-m                     |          |
|----------|--------------------------------------------|----------|
|Cortex-M3 | -mthumb -mcpu=cortex-m3                    | armv7-m  |
|          |--------------------------------------------|          |
|          | -mthumb -march=armv7-m                     |          |
|----------|--------------------------------------------|----------|
|Cortex-M4 | -mthumb -mcpu=cortex-m4                    | armv7e-m |
|(No FP)   |--------------------------------------------|          |
|          | -mthumb -march=armv7e-m                    |          |
|----------|--------------------------------------------|----------|
|Cortex-M4 | -mthumb -mcpu=cortex-m4 -mfloat-abi=softfp | armv7e-m |
|(Soft FP) | -mfpu=fpv4-sp-d16                          | /softfp  |
|          |--------------------------------------------|          |
|          | -mthumb -march=armv7e-m -mfloat-abi=softfp |          |
|          | -mfpu=fpv4-sp-d16                          |          |
|----------|--------------------------------------------|----------|
|Cortex-M4 | -mthumb -mcpu=cortex-m4 -mfloat-abi=hard   | armv7e-m |
|(Hard FP) | -mfpu=fpv4-sp-d16                          | /fpu     |
|          |--------------------------------------------|          |
|          | -mthumb -march=armv7e-m -mfloat-abi=hard   |          |
|          | -mfpu=fpv4-sp-d16                          |          |
|----------|--------------------------------------------|----------|
|Cortex-R4 | [-mthumb] -march=armv7-r                   | armv7-ar |
|Cortex-R5 |                                            | /thumb   |
|Cortex-R7 |                                            | 	   |
|(No FP)   |                                            |          |
|----------|--------------------------------------------|----------|
|Cortex-R4 | [-mthumb] -march=armv7-r -mfloat-abi=softfp| armv7-ar |
|Cortex-R5 | -mfpu=vfpv3-d16                            | /thumb   |
|Cortex-R7 |                                            | /softfp  |
|(Soft FP) |                                            |          |
|----------|--------------------------------------------|----------|
|Cortex-R4 | [-mthumb] -march=armv7-r -mfloat-abi=hard  | armv7-ar |
|Cortex-R5 | -mfpu=vfpv3-d16                            | /thumb   |
|Cortex-R7 |                                            | /fpu     |
|(Hard FP) |                                            |          |
|----------|--------------------------------------------|----------|
|Cortex-A* | [-mthumb] -march=armv7-a                   | armv7-ar |
|(No FP)   |                                            | /thumb   |
|----------|--------------------------------------------|----------|
|Cortex-A* | [-mthumb] -march=armv7-a -mfloat-abi=softfp| armv7-ar |
|(Soft FP) | -mfpu=vfpv3-d16                            | /thumb   |
|          |                                            | /softfp  |
|----------|--------------------------------------------|----------|
|Cortex-A* | [-mthumb] -march=armv7-a -mfloat-abi=hard  | armv7-ar |
|(Hard FP) | -mfpu=vfpv3-d16                            | /thumb   |
|          |                                            | /fpu     |
+------------------------------------------------------------------+

You might encounter issues with Cortex and hard floating point options. If you receive an error similar to:

/usr/lib/gcc-cross/arm-linux-gnueabi/4.7/../../../../arm-linux-gnueabi/bin/ld:
    error: 3way.o uses VFP register arguments, libcryptopp.so does not
/usr/lib/gcc-cross/arm-linux-gnueabi/4.7/../../../../arm-linux-gnueabi/bin/ld:
    failed to merge target specific data of file 3way.o
...

Then see GCC with Cortex-M4 hard float link error "X uses VFP register arguments, Y does not" on the GCC mailing list.

Downloads

setenv-embedded.sh - Download from GitHub

GNUmakefile-cross - Download from GitHub