Linux

From Crypto++ Wiki
Jump to: navigation, search

The Crypto++ mailing list occasionally receives questions regarding library use on various Linux platforms. This page will attempt to help folks working with Linux.

On Linux, Crypto++ is named libcryptopp. The makefile (discussed below) will create and install libcryptopp.a and libcryptopp.so. libcryptopp.a is a traditional static library, while libcryptopp.so is a shared object. Note: libcryptopp should not be confused with libcrypto (libcrypto is OpenSSL).

Linux shared objects written in C++ can be tricky since exceptions must cross the executable/shared object boundary for proper program execution. Those using a Crypto++ shared object should read Note for Shared Object Callers.

Crypto++ FIPS validation does not apply to Linux modules. This is because a Crypto++ binary was validated on Windows as a compiled DLL, and not in source form.

A separate page is available for using Crypto++ under Apple's Xcode. See iOS for building Crypto++ as a static library.

Finally, many thanks to the folks who helped with this page, including (but definitely not limited to) Zooko Wilcox O'Hearn, Nathan Phillip Brink, Alexey Kurov, Jonathan Wakely, Ian Lance Taylor, and Jens Peter Secher.

Fetch the Library

There are two ways to get Crypto++ on a Linux machine. The first is to download Crypto++ from the website (or SourceForge/SVN). The second is to install Crypto++ from a package provided by a distribution such as Debian, Fedora, Mandrivia, OpenSuse, or Ubuntu (see Linux Distributions Offering Crypto++ below).

When Crypto++ releases a version, a ZIP file is created an placed on the website for download. For example, the Crypto++ 5.6.1 ZIP was placed in the download area in August 2010 after revision 521 (the version change and tag). The 5.6.1 ZIP file is fixed in time and does not include the latest bug fixes - it will always be cumulative up to revision 521. Inevitably, this means the Crypto++ ZIP files will become stale over time.

Crypto++ Website

Fetch the latest version of the library. Below, the download was saved in cryptopp. Issue the following to extract the archive. -a handles the CR/LF conversions.

> cd cryptopp/
> unzip -a cryptopp561.zip

Move on to Build and Install the Library.

SourceForge Repository

Issue the following to fetch the latest Crypto++ code from the SourceForge SVN repository.

$svn checkout https://cryptopp.svn.sourceforge.net/svnroot/cryptopp/trunk/c5 cryptopp

I you only want Crypto++ up to a certain revision, perform the following. Below, a checkout of revision 496 is performed.

$svn checkout -r 496 https://cryptopp.svn.sourceforge.net/svnroot/cryptopp/trunk/c5 cryptopp-496

Distribution Package

Most distributions package the library as cryptopp (libcryptopp.a or libcryptopp.so), while Debian (and derivatives) use libcryptopp and libcrypto++. Other distributions, such as Red Hat and Mint, do not provide a Crypto++ package. If using a distribution's version of the library, be aware that you will most likely receive a shared object (libcryptopp.so) rather than a traditional archive (libcryptopp.a).

To develop with Crypto++ using a distribution's package, you usually need to install three packages: the library's base package, the development package, and the debug symbol package. For example, on Debian, the packages of interest are libcrypto++8, libcrypto++8-dbg, and libcrypto++-dev.

If using a distribution's shared object, please take time to read Note for Shared Object Callers.

apt-get

For apt-get distributions (Debian and derivatives such as Ubuntu), issue the following to locate the package name and install the package. Note that the dev or development version of the Crypto++ library was selected. Note that grep crypto++ might need to be changed to grep cryptopp.

root@bruno:/# apt-cache pkgnames | grep -i crypto++
libcrypto++-utils
libcrypto++8
libcrypto++8-dbg
libcrypto++-dev
libcrypto++-doc

root@bruno:/# apt-get install libcrypto++8 libcrypto++8-dbg libcrypto++-dev
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  libcrypto++-dev libcrypto++8 libcrypto++8-dbg
0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
Need to get 10.7MB of archives.

...

yum

On distributions which use yum (such as Fedora), search for Crypto++ using yum:

# yum search crypto++

============================== Matched: crypto++ ===============================
pycryptopp.x86_64 : Python wrappers for the Crypto++ library
cryptopp.i686 : Public domain C++ class library of cryptographic schemes
cryptopp.x86_64 : Public domain C++ class library of cryptographic schemes
cryptopp-devel.i686 : Header files and development documentation for cryptopp
cryptopp-devel.x86_64 : Header files and development documentation for cryptopp
cryptopp-doc.noarch : Documentation for cryptopp
cryptopp-progs.x86_64 : Programs for manipulating cryptopp routines

Issue the following commands to install the library and header files:

> su -
 password:
# yum install cryptopp cryptopp-devel

The cryptest.exe program is not installed with the library on Fedora. If you want the cryptest program, issue:

# yum install cryptopp cryptopp-progs

Build and Install the Library

Crypto++ comes with a makefile named GNUMakefile. The library does not use autoconf and friends, so there is no ./configure. The library is built and tested against a number of operating systems and platforms. Linux build results can be found at Build Status.

Precompiled headers require more than simply defining USE_PRECOMPILED_HEADERS. If you plan on using it, see Precompiled headers below.

Beginning with revision 496, the makefile includes targets cryptest.exe, libcryptopp.a, libcryptopp.so, and install. Revision 496 is included in the 5.6.1 ZIP archive on the website. Crypto++ 5.6.0 and earlier did not include the libcryptopp.so target.

Some distributions, such as Ubuntu 8.10 and higher, include Fortify instrumentation when optimizations are at level 2 (-O2) and higher. To reduce the code size by removing the additional compile and run-time checks on Ubuntu, specify either -U_FORTIFY_SOURCE or -D_FORTIFY_SOURCE=0. For Crypto++ 5.6.0 and x86 Karmic (9.10) distribution, the size of the library was reduced from 35.7 MB to 13.1 MB when building without -g and with -D_FORTIFY_SOURCE=0.

Makefile

The default makefile is configured to build a static library (archive), release build (-DNDEBUG), and includes options for moderate optimizations (-O2) and debug symbols (-g). If you find the build and options don't suit your taste, gcc and g++ have an abundance of commands and flags (see man gcc). Performance penalties (or lack of penalties) when using -g are discussed in How does the gcc -g option affect performance?.

The Crypto++ makefile uses a CXXFLAG of -march=native, so Crypto++ builds correctly for the platform. However, GCC prior to version 4.6 has bugs related to -march=native. See, for example, LTO performance: -march=native isn't saved in COLLECT_GCC_OPTIONS.

Crypto++ does not specify -mtune. Specifying -mtune can significantly benefit performance on x86 and x64 hardware. See Intel 386 and AMD x86-64 Options and The difference between -mtune and -march.

Precompiled headers require a few modifications beyond defining USE_PRECOMPILED_HEADERS. See Precompiled headers below.

If you want to build a shared object rather than an archive, uncomment the following line in the GNUmakefile. Also see Note for Shared Object Callers below.

# CXXFLAGS += -fPIC

If you are using pthreads, Crypto++ will add -pthread to LDFLAGS for Linux. The library does not add the _REENTRANT flag to CFLAGS. For GNU/Linux, both -pthread and _REENTRANT should be specified. See -pthread option and gcc -pthread should define _REENTRANT?.

If you plan to profile your program under Linux, add the -p or -pg switch to the makefile for use by prof or gprof. See Options for Debugging Your Program or GCC and Profiling.

Make and Install

Issue make to build the static library. To build the static archive, shared object, and test program, enter the following (be sure to add -fPIC to the makefile). There is no need for root at this point.

> make static dynamic test

The library has a lot of functionality (and debug information), and some are alarmed at its compiled size. When the final executable is linked, most of the information will be discarded so the final executable will be considerably smaller.

> ls -al *.a
-rw-r--r-- 1 user user 56069234 2010-09-07 01:14 libcryptopp.a

After the library successfully builds, run cryptest.exe v to validate the library. Now would be a good time to base line Crypto++ against tools such as Valgrind and Purify. See Profiling for details.

> cryptest.exe v

If you plan on building and installing both the static and dynamic libraries, tell make to do so. Otherwise, libcryptopp.a and cryptest.exe will be built under a standard user account, and libcryptopp.so will be built as root during install.

$ make libcryptopp.a libcryptopp.so cryptest.exe
...
$ ls *.so *.a *.exe
cryptest.exe    libcryptopp.a   libcryptopp.so

Finally, install the library. By default, Crypto++ installs to /usr/include and /usr/lib. This must be done using root since files are written to /usr/bin, /usr/include, and /usr/lib. Note that make install does not copy the test vectors into /usr/bin. If your distribution does not support su, try issuing sudo make install.

> su -
Password:
# cd .../cryptopp-5.6.0/
# make install

To change the installation directory, add a value for PREFIX when invoking make:

# gmake install PREFIX=/usr/local
...
mkdir -p /usr/local/include/cryptopp /usr/local/lib /usr/local/bin
cp *.h /usr/local/include/cryptopp
cp *.a /usr/local/lib
cp *.so /usr/local/lib
cp *.exe /usr/local/bin

OpenBSD

OpenBSD is not Linux (but an OpenBSD might find themselves here). If compiling and installing for OpenBSD, please change PREFIX to /usr/local. If you install to /usr, be prepared for a typical output of:

g++ -g3 -ggdb -O0 -pipe -fsigned-char -fmessage-length=0
-Woverloaded-virtual -Wreorder -Wformat=2 -Wformat-security
-Wno-unused -fvisibility=hidden -fstack-protector -I. -I./esapi
-I./deps -I/usr/local/include -fpic -c src/codecs/HTMLEntityCodec.cpp
-o src/codecs/HTMLEntityCodec.o
In file included from /usr//include/cryptopp/misc.h:4,
                from ./esapi/crypto/Crypto++Common.h:24,
                from src/codecs/HTMLEntityCodec.cpp:12:
/usr//include/cryptopp/cryptlib.h:99: error: template with C linkage
/usr//include/cryptopp/cryptlib.h:247: error: template with C linkage
/usr//include/cryptopp/cryptlib.h:254: error: template with C linkage
/usr//include/cryptopp/cryptlib.h:261: error: template with C linkage
/usr//include/cryptopp/cryptlib.h:268: error: template with C linkage
/usr//include/cryptopp/cryptlib.h:293: error: template with C linkage
/usr//include/cryptopp/cryptlib.h:698: error: template with C linkage

Directory Structure

After the installation, a typical directory structure is as follows.

  • /usr/bin
    • cryptest.exe
  • /usr/include
    • Crypto++ header files in cryptopp subdirectory
  • /usr/lib
    • libcryptopp.a or libcryptopp.so

Verify the Installation

Two commands can be used to verify the installation of Crypto++. First is whereis, second is ldconfig.

> whereis cryptest.exe
 cryptest: /usr/bin/cryptest.exe

> whereis libcryptopp.a
libcryptopp: /usr/lib/libcryptopp.a /usr/lib/libcryptopp.so /usr/lib64/libcryptopp.a /usr/lib64/libcryptopp.so
user@bruno:~$ ldconfig -p | grep crypto++
    libcrypto++.so.8 (libc6,x86-64) => /usr/lib/libcrypto++.so.8
    libcrypto++.so (libc6,x86-64) => /usr/lib/libcrypto++.so

Precompiled Headers

Use of precompiled headers is framed out in Crypto++, but the feature requires a few tweaks for Linux. Using precompiled headers on a Core 2 Duo (circa late-2008) reduced compile times by 38% (3 min, 51 sec versus 2 min, 22 sec). On a Core i7 machine (circa mid-2010) the time was reduced by 24% to just under 2 minutes. Note that GCC must be version 3.4 or hight to support the feature.

To use precompiled headers, modify pch.h by adding <string>, <algorithm>, and <memory> to the list of includes. This makes sense since string and auto_ptr are used frequently in Crypto++ and therefore benefit from precompilation.

Add USE_PRECOMPILED_HEADERS to CXXFLAGS. Note: this is a Crypto++ define, and is not required by GCC's implementation of precompiled headers.

CXXFLAGS = -DNDEBUG -g -O2 -DUSE_PRECOMPILED_HEADERS=1

Add a rule for precompile. The file name must have the extension .gch. The command must also use the same CXXFLAGS as the files using precompiled header. Both are GCC requirements.

precompile: pch.h pch.cpp
    $(CXX) $(CXXFLAGS) pch.h -o pch.h.gch

Finally, edit GNUmakefile and add precompile as a dependency for targets all, libcryptopp.a, libcryptopp.so, and cryptest.exe. For example:

all: precompile cryptest.exe

...

cryptest.exe: precompile libcryptopp.a $(TESTOBJS)
	$(CXX) -o $@ $(CXXFLAGS) $(TESTOBJS) -L. -lcryptopp $(LDFLAGS) $(LDLIBS)

To verify that precompiled headers are being used, add the following to pch.h. If one message is displayed, precompiled headers are in play. If 130 or so messages are displayed, Crypto++ is not using precompiled headers. Note: Stallman no longer objects to #pragma since it can be used in a macro.

#pragma message("Including Crypto++ precompiled header file.")

To benchmark the savings issue the following:

make clean && date && make && date

Also see Jason Smethers' comments on using ccache to reduce compilation times at Linux/GCC and Precompiled Headers.

A Crypto++ Program

The sample program below uses Crypto++'s Integer class. It was chosen because Integer overloads operator<<, which makes it convenient to exercise the library and display results with minimal effort.

Source Code

#include <iostream>
using std::cout;
using std::endl;

#include "cryptopp/integer.h"
using CryptoPP::Integer;

int main( int, char** ) {

  Integer i;

  cout << "i: " << i << endl;

  return 0;
}

The integer class has arbitrary precision, so a variable will easily handle large integers and other arithmetic operations such as the following.

int main( int, char** ) {

  Integer j("100000000000000000000000000000000");
  j %= 1999;

  cout << "j: " << j << endl;

  return 0;
}

Compiling and Linking

To compile and link the program issue the following. There are two points to observe when compiling and linking. First, use g++ rather than gcc (see GCC's Compiling C++ Programs). Second the library directive (-l) is the last argument to g++. Note: on some systems (for example, Fedora), the library option might be -lcrypto++.

g++ -g3 -ggdb -O0 -Wall -Wextra -Wno-unused -o test test.cpp -lcryptopp

-Wall and -Wextra turn on most warnings since its always a good idea to let static analysis tools catch mistakes early. (For reasons only known to the free software world, -Wall only turns on some warnings, and not all warnings as the name implies.) -Wno-unused increases the signal to noise ratio because Crypto++ has a lot of unused parameters, which is par for the course for an object oriented program with lots of interfaces.

If -Wall and -Wextra are producing too much noise (even after -Wno-unused), compile with -fdiagnostics-show-option to locate which additional warnings to suppress. See Options to Request or Suppress Warnings.

The -g3 switch adds maximum debug information to the executable test and is not required (note that -g is equivalent to -g2). The -ggdb adds gdb extensions which might prove useful when debugging non-trivial programs under gdb which support extensions. See Options for Debugging Your Program or GCC. If you are adding -ggdb, you might consider adding -fno-omit-frame-pointer so that stack traces from the field are easier to walk.

-O0 disables all optimizations, so even #define's are available to the debugger. Usually, optimizations such as these are taken by the optimizer, and the debugger will display something similar to 'value optimized out'. Note that -O0 is the default optimization level.

-o specifies the output file name. -l specifies the library. When using -l, we only need to specify the base library name. ld will prepend lib and append .a (or .so) when searching for the library (reference the ld man pages around line 6200). Finally, the -l option location is significant (libraries must be specified last).

Running the Program

To run the program, specify the current working directory in case test is a program in /usr/bin.

./test

Output should be as below.

i: 0.

If we were to run the variant 100000000000000000000000000000000 % 1999, we would receive the expected result of 820.

Stripping Debug Symbols

If the program was compiled and linked with debug symbols, strip can be used to remove the symbols. Once stripped, debuggers and stack traces are generally useless.

> ls -l myprogram
... 6866924 2009-04-28 16:12 myprogram
> strip --strip-debug myprogram
> ls -l myprogram
... 1738761 2009-04-28 16:13 myprogram

Reducing Application Size

If you are working in a size constrained environment, you have a few options to reduce an application's size. First, consider compiling with -Os.

Second, add the following to compiler flags (CXXFLAGS): -fdata-sections, -ffunction-sections, and -fvtable-gc. Third, adding the following to the linker flags (LDFLAGS): -static, --gc-sections, -s. See Removing unused functions/dead code for details.

Static linking (-static) is important for dead code removal. If the linker is not honoring requests, try specifying the full archive name on the commanle line. For example:

g++ -o test.exe test.cpp /usr/local/lib/libcryptopp.a

Crypto++ Libraries

In general, try to use the static version of the Crypto++ library (libcryptopp.a or libcryptopp.a) rather than the shared object.

When building from the makefile, the library name will be either libcryptopp.a or libcryptopp.so (depending on the make target). For distributions which provide a Crypto++ library package, there seems to be two predominant shared object names: libcryptopp.{a|so} and libcrypto++.{a|so}. For example, systems running Fedora or OpenSuse will use libcryptopp.so, while Debian and Ubuntu will offer libcrypto++.so.

C++ based shared objects under GNU Linux usually leaves something to to be desired. If you have problems with two separate libraries each loading Crypto++ as s shared object, see:

libcryptopp.a

libcryptopp.a is the static version of the Crypto++ library. The Crypto++ makefile will build and install the static library in response to make install. Since the library is typically on a known path for the linker (see below), there is usually no need for the -L option to ld.

> whereis libcryptopp.a
libcryptopp: /usr/lib/libcryptopp.a

libcryptopp.so

libcryptopp.so is the shared object version of the Crypto++ library (dynamic version in Windows parlance). The makefile added the libcryptopp.so target at commit 496. Revision 496 is included in the 5.6.1 ZIP archive on the website.

Though Crypto++ now supports building a shared object, Crypto++ versions 5.6.0 and prior did not support shared objects and the makefile did not include the target. Zooko Wilcox-O'Hearn, author of the Tahoe File System (a secure, decentralized, fault-tolerant file system), has posted a patch for building Crypto++ as a shared object. See Patch: build libcryptopp.so. In addition, Zooko offers information on using Debian and Fedora's prebuilt libcryptopp.so.

Users of the shared object should familiarize themselves with Note for Shared Object Callers, and package maintainers should read Note for Distribution Packagers below.

Shared Objects and Globals

Note for Shared Object Callers and Note for Distribution Packagers discuss some circumstances required to crash a shared object (C++ shared object, RTLD_GLOBAL, global objects with destructors, and violation of C++'s One Definition Rule). Use of global variables are inevitable, and Crypto++ attempts to use them in a library-safe manner.

Auditing the library for use of global variables began when Crypto++ added official support for shared objects. Unfortunately, it does not appear that gcc offers a switch to audit for use of globals. A feature request for the switch was submitted in October, 2010. See Switch to warn of global variables in a C++ shared object.

In the absence of an official auditing method, Crypto++ tries to use consistent naming, with global variables specified with a g_ prefix. Ian Taylor suggests using objdump and objdump -t -j .data | grep ' g '. nm -D /usr/lib/cryptopp.so | grep g_ can also be used to audit use of global variables in the library. See Audit Use of Global Variables in C++ Shared Object (GCC Warning?).

Note for Shared Object Callers

Callers which dynamically load libcryptopp.so or libcrypto++.so should use the RTLD_GLOBAL flag in dlopen. If the call to dlopen fails, OR in RTLD_LAZY and try again. According to the Open Group Base Specifications of dlopen, a third option of interest exists, but we've never had to use it: RTLD_NOW. If the first two tries fail, RTLD_GLOBAL | RTLD_NOW probably will not hurt.

RTLD_GLOBAL is required so that a module can correctly catch a Crypto++ exception. The reason for the flags is the new C++ ABI and the GCC 3.0 [and above] series of tools use address comparisons, rather than string comparisons, to determine type equality. See dynamic_cast, throw, typeid don't work with shared libraries.

The flags passed to dlopen (RTLD_GLOBAL, RTLD_LAZY, and RTLD_NOW) have been determined through trial and error, and is being passed on in folklore fashion (there's some wiggle room in the Open Group Base Specifications of dlopen). For example, Fedora and OpenSuse appear to accept just RTLD_GLOBAL, while Debian and Ubuntu seem to require RTLD_GLOBAL | RTLD_LAZY.

Since your program might run on systems which use either libcryptopp.so or libcrypto++.so, the following might be a helpful strategy for dynamic loading. In fact, Cryptopp-SO-Test.zip uses similar to ensure the Crypto++ shared object is located regardless of Linux distribution or dlopen behavior.

void* cryptlib = NULL;

cryptlib = dlopen("libcryptopp.so", RTLD_GLOBAL);

if(!cryptlib)
    cryptlib = dlopen("libcryptopp.so", RTLD_GLOBAL | RTLD_LAZY);

if(!cryptlib)
    cryptlib = dlopen("libcrypto++.so", RTLD_GLOBAL);

if(!cryptlib)
    cryptlib = dlopen("libcrypto++.so", RTLD_GLOBAL | RTLD_LAZY);

if(!cryptlib)
    throw runtime_error("Failed to load crypto++ shared object");

...

dlclose(cryptlib);

Finally, Zooko Wilcox O'Hearn reports that Python test cases occasionally fail when using RTLD_GLOBAL. Zooko's work around was to drop the flag. Open questions include 'Does this imply RTLD_LOCAL', and 'Is this behavior limited to Ubuntu'. See [Tahoe LAFS] Changeset 711. So much for planning based on documentation.

Note for Distribution Packagers

The following should probably be in a separate FAQ for packagers and patchers.

Bug Fixes and Releases

If you are a package maintainer and would like to know of bug fixes, releases, and other interesting events which might warrant a package update, please add your email address to the list on the Linux Talk page.

trunk/c5 is Current and Stable

trunk/c5 is stable and includes the latest bug fixes. The SVN command to fetch the lastest version of Crypto++ is:

 $svn checkout https://cryptopp.svn.sourceforge.net/svnroot/cryptopp/trunk/c5 cryptopp

Crypto++ X.Y.Z ZIP is Fixed

When Crypto++ releases a version, a ZIP file is created and placed on the website for download. For example, the Crypto++ 5.6.1 ZIP was placed in the download area in August 2010 after a commit of revision 521. The 5.6.1 ZIP file is fixed in time and does not include the latest bug fixes - it will always be cumulative up to revision 521. Inevitably, all ZIP files will become stale over time.

Library Validation

After building the Crypto++ library, please issue cryptest.exe v to verify the library.

cryptest.exe v

To validate the Crypto++ library, one runs cryptest.exe v. However, cryptest.exe makes assumptions about the location of its test data. After cryptest.exe has been installed in /usr/bin, the the brittle assumptions no longer hold true and the validation no longer works. We've been trying to gather feedback on how to resolve the issue (see, for example, Linux: make install and test vectors).

Crypto++ was fortunate that Jens Peter Secher, maintainer of the Debian package, responded with Debian's solution. However, Wei did not act upon it, which might suggest there was something he did not like - for example, did the Debian fix apply to both user compiles and package-maintainer compiles. Additional comments and suggestions are welcomed.

Please Don't Back-port

Please don't back-port bug fixes and patches. When a patch is back-ported, there are two versions in play: a base package version and a back-ported version number. If all revisions up to (and including the revision of interest) are not taken, then there is a base package version and a collection of revisions.

Unfortunately, we have yet to see a Linux binary or package carry around two independent version numbers or a base version and collection of revisions. By the time a problem is reported on the Crypto++ mailing list, its impossible to tell what Crypto++ code is actually being used. For example, myprog --version nearly always returns the base version, but never returns the patch level or collection of revisions back ported. Since --version only returns a base package version, what switch are folks supposed to use to determine patch levels?

A concrete example of the problem in another package is OpenSSL. Its damn near impossible to tell what version of OpenSSL (0.9.8 {k|l|m|n|o|p|q}) is running on a given Linux distribution because of grafting, back-porting, and the Frankenstein-ian patch work. Confer: Identifying openssl version from lib. Hopefully OpenSSL's 1.0.0 release will offer an opportunity to clean up the versioning mess.

If its determined that a package must be patched, please include all revisions up to the revision of interest. The svn command to fetch based on revisions is:

 $svn checkout -r 496 https://cryptopp.svn.sourceforge.net/svnroot/cryptopp/trunk/c5 cryptopp-496

It would also be very helpful if the SVN revision number were readily available. For example, libcryptopp-5.6.0-svn496.so, libcryptopp-5.6.0-r496.so, or libcryptopp-5.6.0-496.so.

Shared objects

Some distributions require that a library be distributed as a shared object. At revision 496, Wei committed a fix for a possible global object destruction issue. The crash was attributed to a violation of C++'s One Definition Rule (ODR). Since Crypto++ appears to comply with C++ ODR (specifically, section 3.5, Program and Linkage), the report could indicate a bug in the implementation of the shared objects in the original report; or it could indicate a bug in the dynamic linker (provided by glibc); or some obscure combination of interactions.

Architecture of cryptopp-so-test program
A multi-threaded stress test is available for the Crypto++ shared object: Cryptopp-SO-Test.zip. The executable is dependent upon the four [test] shared objects, and the four shared objects are dependent upon libcryptopp.so. The executable is not dependent upon libcryptopp.so.

The tests attempt to reproduce the conditions specified in Errors with multiple loading cryptopp as shared lib on Linux and confirm conformance with ODR. First, the test harness performs a fork to get two distinct processes in memory (strictly speaking, two processes is not required). Each process then creates 64 threads, each of which calls one of four intermediate [test] shared objects, which in turn load a single libcryptopp.so or libcrypto++.so. Each thread will then sleep a random amount of time over the interval [0, 5) seconds to promote interleaving and concurrency; and then exercise catching a Crypto++ exception originating in the shared object, exercise global non-trivial objects (such as the g_nullNameValuePairs to ensure linkage and operation), and exercise selected components such as the AES and AutoSeededRandomPool.

Note: Cryptopp-SO-Test.zip suffers from insecure library loading since it will attempt to load one of the four shared objects (discussed above) from both the LD_PATH and the current working directory. The test code should not be blindly copied/pasted into a production project without a code review.

A typical output of a successful run of cryptopp-so-test is similar to below. A return 0 from main is good, a crash is bad.

user@bruno:home$ ./cryptopp-so-test.exe 
Parent, Main thread, Crypto++ not loaded (expected)
Child, Main thread, Crypto++ not loaded (expected)
Child, Thread 1, dsotest-2.so at 0x1445970, Crypto++ at 0x7fdb26c05000
Parent, Thread 7, dsotest-2.so at 0x1445970, Crypto++ at 0x7fdb26c05000
Parent, Thread 8, dsotest-3.so at 0x14461d0, Crypto++ at 0x7fdb26c05000
Child, Thread 2, dsotest-3.so at 0x14461a0, Crypto++ at 0x7fdb26c05000
Parent, Thread 10, dsotest-1.so at 0x1434590, Crypto++ at 0x7fdb26c05000
Parent, Thread 11, dsotest-2.so at 0x1445970, Crypto++ at 0x7fdb26c05000
Child, Thread 3, dsotest-4.so at 0x14468f0, Crypto++ at 0x7fdb26c05000
Parent, Thread 12, dsotest-3.so at 0x14461d0, Crypto++ at 0x7fdb26c05000
...
Child, Thread 72, successfully completed testing
Parent, Thread 53, successfully completed testing
Parent, Thread 40, successfully completed testing
Child, Thread 55, successfully completed testing
Parent, Thread 88, successfully completed testing
Child, Thread 12, successfully completed testing
Child, Main thread exiting
Parent, Thread 54, successfully completed testing
Parent, Thread 69, successfully completed testing
Parent, Main thread exiting
user@bruno:~home$

Linux Distributions

The following offers helpful information when using packages provided by the distribution.

Distributions Offering Crypto++

Crypto++ does not offer RPMs or DEBs. Each distribution performs its own packaging.

Linux Distributions Offering Crypto++
Distribution Library Name Package Information
Debian libcrypto++ http://packages.debian.org/search?keywords=crypto%2B%2B
CentOS 6 libcryptopp Requires EPEL6 testing repository. See http://fedoraproject.org/wiki/EPEL
Fedora libcryptopp http://koji.fedoraproject.org/koji/packageinfo?packageID=7023
Mandriva libcryptopp http://doc4.mandriva.org/bin/view/d4/search?name=cryptopp&opc=component
OpenSuse libcryptopp http://software.opensuse.org/search?q=cryptopp&baseproject=openSUSE%3AFactory
Red Hat 5 Not included http://ftp.redhat.com/pub/redhat/linux/enterprise/5Client/en/os/SRPMS/
Red Hat 6 libcryptopp Requires EPEL6 testing repository. See http://fedoraproject.org/wiki/EPEL
Scientific Linux libcryptopp Requires EPEL6 testing repository. See http://fedoraproject.org/wiki/EPEL
Ubuntu libcrypto++ http://packages.ubuntu.com/search?keywords=crypto%2B%2B

The list above is not complete, is listed in alphabetical order, and not meant to insult unlisted distributions. The table includes Red Hat because it is popular in the enterprise. The table was compiled using the top 5 or so distributions from Linux Distributions - Facts and Figures at distrowatch.com.

Distribution Package Version

The dpkg command can be used to determine the version of Crypto++ installed on a system using apt-get and friends.

$ apt-cache pkgnames | grep -i crypto++
libcrypto++-utils
libcrypto++8
libcrypto++8-dbg
libcrypto++-dev
libcrypto++-doc

$ dpkg -s libcrypto++8
Package: libcrypto++8
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 4900
Maintainer: Ubuntu Developers
Architecture: amd64
Source: libcrypto++
Version: 5.6.0-5
Depends: libc6 (>= 2.4), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 4.2.1)
Description: General purpose cryptographic library - shared library
 General purpose cryptographic library for C++.

 This package contains the shared libraries and should only be
 installed if other packages depend on it.
Original-Maintainer: Jens Peter Secher <jps@debian.org>
Homepage: http://www.cryptopp.com

GNU Linux versioning usually leaves a lot to be desired. Some distributions use the library name and Crypto++ library version to form a package name and file names (for example, libcryptopp-5.6.0.so). Other distributions use the library name and base system version (for example, libcryptopp-fc13.so) for package and file names. And the situation only gets worst as fixes are back-ported while leaving package names, versions, and file names unchanged.

To show package related information, use apt-cache.

$ apt-cache showpkg libcrypto++8
Package: libcrypto++8
Versions: 
5.6.0-5 (/var/lib/apt/lists/us.archive.ubuntu.com_ubuntu_dists_lucid_universe_binary-amd64_Packages) (/var/lib/dpkg/status)
 Description Language: 
                 File: /var/lib/apt/lists/us.archive.ubuntu.com_ubuntu_dists_lucid_universe_binary-amd64_Packages
                  MD5: 81fdf53fa3eb3f0f338e2c29ca70b7aa

Reverse Depends: 
  kvirc,libcrypto++8
  python-pycryptopp-dbg,libcrypto++8
  python-pycryptopp,libcrypto++8
  libcrypto++8-dbg,libcrypto++8 5.6.0-5
  libcrypto++-utils,libcrypto++8
  libcrypto++-dev,libcrypto++8 5.6.0-5
  kvirc,libcrypto++8
  amule-utils-gui,libcrypto++8
  amule-daemon,libcrypto++8
  amule-adunanza-utils-gui,libcrypto++8
  amule-adunanza-daemon,libcrypto++8
  amule-adunanza,libcrypto++8
  amule,libcrypto++8
Dependencies: 
5.6.0-5 - libc6 (2 2.4) libgcc1 (2 1:4.1.1) libstdc++6 (2 4.2.1) 
Provides: 
5.6.0-5 -

For systems using yum, use info to display Crypto++ package information:

# yum info cryptopp
updates/metalink                                         |  17 kB     00:00     
updates-debuginfo/metalink                               |  14 kB     00:00     
updates-source/metalink                                  |  15 kB     00:00     
Installed Packages
Name        : cryptopp
Arch        : x86_64
Version     : 5.6.1
Release     : 3.fc14
Size        : 5.4 M
Repo        : installed
From repo   : updates
Summary     : Public domain C++ class library of cryptographic schemes
URL         : http://www.cryptopp.com/
License     : Public Domain
Description : Crypto++ Library is a free C++ class library of cryptographic
            : schemes. See http://www.cryptopp.com/ for a list of supported
            : algorithms.
            : 
            : One purpose of Crypto++ is to act as a repository of public domain
            : (not copyrighted) source code. Although the library is copyrighted
            : as a compilation, the individual files in it are in the public
            : domain.

...

Examining the Library

This section covers usage of objdump and nm to examine symbols and code generation. See Ten Commands Every Linux Developer Should Know. If you are working on Mac OS X, use otool -afhv <obj file>.

Examining Code

Examining program using dissy
To examine the generated code, use objview or dissy (a visual front end to objview). Below, objview displays the file header.
user@studio:~$ objdump -f rsa_kgen.exe

rsa_kgen.exe:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0000000000404dd0

To disassemble a function, use the -d switch.

user@studio:~$ objdump -d rsa_kgen.exe 0x4049a8

rsa_kgen.exe:     file format elf64-x86-64

Disassembly of section .init:

00000000004049a8 <_init>:
  4049a8:    48 83 ec 08              sub    $0x8,%rsp
  4049ac:    e8 4b 04 00 00           callq  404dfc <call_gmon_start>
  4049b1:    e8 da 04 00 00           callq  404e90 <frame_dummy>
  4049b6:    e8 25 3d 00 00           callq  4086e0 <__do_global_ctors_aux>
  4049bb:    48 83 c4 08              add    $0x8,%rsp
  4049bf:    c3                       retq

Similar to nm (discussed below), we can also dump decorated symbols.

user@studio:~$ objdump -t rsa_kgen.exe | grep Integer

000000000060c260  w    O .bss	0000000000000038              _ZTVN8CryptoPP7IntegerE
0000000000406e5a  w    F .text	0000000000000048              _ZNK8CryptoPP23TrapdoorFunctionInverse26CalculateRandomizedInverseERNS_21RandomNumberGeneratorERKNS_7IntegerE
0000000000000000       F *UND*	0000000000000000              _ZN8CryptoPP7IntegerC1ERKS0_
0000000000406cba  w    F .text	0000000000000047              _ZNK8CryptoPP16TrapdoorFunction23ApplyRandomizedFunctionERNS_21RandomNumberGeneratorERKNS_7IntegerE
0000000000000000       F *UND*	0000000000000000              _ZN8CryptoPP7IntegermmEv
0000000000000000       F *UND*	0000000000000000              _ZN8CryptoPP7IntegerC1Ev
0000000000406a8c  w    F .text	0000000000000075              _ZN8CryptoPP7IntegerD1Ev

Finally, we can clean up the output a bit with the following command.

user@studio:~$ objdump -t rsa_kgen.exe | grep Integer | cut --bytes=26-30,60-

.bss   _ZTVN8CryptoPP7IntegerE
.text  _ZNK8CryptoPP23TrapdoorFunctionInverse26CalculateRandomizedInverseERNS_21RandomNumberGeneratorERKNS_7IntegerE
*UND*  _ZN8CryptoPP7IntegerC1ERKS0_
.text  _ZNK8CryptoPP16TrapdoorFunction23ApplyRandomizedFunctionERNS_21RandomNumberGeneratorERKNS_7IntegerE
*UND*  _ZN8CryptoPP7IntegermmEv
*UND*  _ZN8CryptoPP7IntegerC1Ev
.text  _ZN8CryptoPP7IntegerD1Ev

Examining Symbols

To dump the contents of the library, use the nm command. Note: if examining symbols from a shared object, you must inldue the -D or --dynamic option:

nm /usr/lib/cryptopp.a
nm --dynamic /usr/lib/cryptopp.so

The command below dumps the library's exported symbols then filters based on "Integer". Output is not shown because of the number of lines in the output.

> nm /usr/lib/libcryptopp.a | grep 'Integer'

To dump the first eight demangled Integer entries from the library. Unused entries - those of type U - can be removed with option --defined-only.

> nm --demangle /usr/lib/libcryptopp.a | grep 'Integer' | head -8
00000000 B CryptoPP::g_pAssignIntToInteger
         U CryptoPP::g_pAssignIntToInteger
         U CryptoPP::g_pAssignIntToInteger
         U CryptoPP::a_exp_b_mod_c(CryptoPP::Integer const&, CryptoPP::Integer const&, CryptoPP::Integer const&)
00000850 T CryptoPP::PublicBlumBlumShub::PublicBlumBlumShub(CryptoPP::Integer const&, CryptoPP::Integer const&)
00000b60 T CryptoPP::PublicBlumBlumShub::PublicBlumBlumShub(CryptoPP::Integer const&, CryptoPP::Integer const&)
         U CryptoPP::Integer::Integer(CryptoPP::Integer::Sign, unsigned long long)
         U CryptoPP::Integer::Integer(CryptoPP::Integer const&)

Below is a dump of unique Integer constructors offered by the library. The command should be entered on a single line (the command spans two lines for readability). The --bytes=12- option instructs cut to remove bytes 0-11 by specifying 12 to End of Line ( 12- ). Note that the trailing dash of 12- is not optional. sort performs an ascending sort, and uniq removes consecutive duplicates.

> nm --demangle --defined-only /usr/lib/libcryptopp.a |
      grep 'CryptoPP::Integer::Integer' | cut --bytes=12- | sort | uniq
CryptoPP::Integer::Integer()
CryptoPP::Integer::Integer(char const*)
CryptoPP::Integer::Integer(CryptoPP::BufferedTransformation&)
CryptoPP::Integer::Integer(CryptoPP::BufferedTransformation&, unsigned int, CryptoPP::Integer::Signedness)
CryptoPP::Integer::Integer(CryptoPP::Integer const&)
CryptoPP::Integer::Integer(CryptoPP::Integer::Sign, unsigned int, unsigned int)
CryptoPP::Integer::Integer(CryptoPP::Integer::Sign, unsigned long long)
CryptoPP::Integer::Integer(CryptoPP::RandomNumberGenerator&, unsigned int)
CryptoPP::Integer::Integer(long)
CryptoPP::Integer::Integer(unsigned char const*, unsigned int, CryptoPP::Integer::Signedness)
CryptoPP::Integer::Integer(unsigned int, unsigned int)
CryptoPP::Integer::Integer(wchar_t const*)
[One contructor removed for screen formatting]

Finally, we can further clean up the output by specifying sed "s/CryptoPP:://g". The sed command will replace instances of "CryptoPP::" with an empty string.

> nm --demangle --defined-only /usr/lib/libcryptopp.a | grep 'CryptoPP::Integer::Integer' |
      cut --bytes=12- | sed "s/CryptoPP:://g" | sort | uniq
Integer::Integer()
Integer::Integer(BufferedTransformation&)
Integer::Integer(BufferedTransformation&, unsigned int, Integer::Signedness)
Integer::Integer(char const*)
Integer::Integer(Integer const&)
Integer::Integer(Integer::Sign, unsigned int, unsigned int)
Integer::Integer(Integer::Sign, unsigned long long)
Integer::Integer(long)
Integer::Integer(RandomNumberGenerator&, unsigned int)
Integer::Integer(unsigned char const*, unsigned int, Integer::Signedness)
Integer::Integer(unsigned int, unsigned int)
Integer::Integer(wchar_t const*)
[One contructor removed for screen formatting]

x86 vs x64

The Crypto++ makefile uses a CXXFLAG of -march=native, so Crypto++ builds correctly for the platform. There are no special options required.

On x86 Linux, the traditional /usr/lib directory is used for the library. Some 64-bit Linux's, such as Debian and Ubuntu, use two directories: /usr/lib and /usr/lib64. Both /usr/lib and /usr/lib64 contain 64 bit libraries. Other distributions, such as Fedora, use only /usr/lib64 (see Alexey Yurov, Maintainer of Crypto++ on Fedora, response to Linux: makefile, install and x86_64). The Crypto++ makefile only installs to /usr/lib on x64 machines.

Below, we use objdump to examine a Ubuntu 10.04 installation. The -f option to objdump indicates we only want the header. When dumping the archive (libcryptopp.a), we use head to display the first 12 lines of output. Otherwise, we would get a complete dump since an archive is a collection of objects to be used by the linker.

user@studio:~$ whereis libcryptopp
libcryptopp: /usr/lib/libcryptopp.so /usr/lib/libcryptopp.a /usr/lib64/libcrypto++.so /usr/lib64/libcrypto++.a

user@studio:~$ objdump -f /usr/lib/libcryptopp.so
/usr/lib/libcryptopp.so:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x000000000027f630

user@studio:~$ objdump -f /usr/lib/libcryptopp.a | head -12
In archive /usr/lib/libcryptopp.a:

3way.o:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

adler32.o:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

user@studio:~$ objdump -f /usr/lib64/libcrypto++.so
/usr/lib64/libcrypto++.so:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x000000000027f630

user@studio:~$ objdump -f /usr/lib64/libcrypto++.a | head -12
In archive /usr/lib64/libcrypto++.a:

3way.o:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

adler32.o:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

Common Errors

This section covers common errors encountered when working with Cryto++.

gcc/g++/ld Versions

Verify you are using a supported version of the g++ and ld. Compare the results to the platform matrix on the Crypto++ homepage. In general, GCC 3.3 and above is supported for the latest versions of Crypto++ (5.4, 5.5, and 5.6).

> g++ --version
g++ (SUSE Linux) 4.3.2 [gcc-4_3-branch revision 141291]
> ld --version
GNU ld (GNU Binutils; openSUSE 11.1) 2.19

-l option

According to the g++ man pages (around line 25), the -l option location is significant:

For the most part, the order you use doesn't matter. Order does matter when you use several options of the same kind; for example, if you specify -L more than once, the directories are searched in the order specified. Also, the placement of the -l option is significant.

Also see the note regarding object link order in GCC Options for Linking.

If you receive an error similar to undefined reference to CryptoPP::Integer::Integer() or undefined reference to vtable for CryptoPP::Integer, you most likely specified the library as an early option to g++:

> g++ -lcryptopp -o test test.cpp    # wrong!!!

We can verify the vtables are present using nm:

> nm --demangle --defined-only /usr/lib/libcryptopp.a | grep 'vtable for CryptoPP::Integer' | sort | uniq
00000000 V vtable for CryptoPP::Integer
00000000 V vtable for CryptoPP::Integer::DivideByZero
00000000 V vtable for CryptoPP::Integer::OpenPGPDecodeErr
00000000 V vtable for CryptoPP::Integer::RandomNumberNotFound

SHA-2 Crash and Binutils

If you experience a crash during validation (cryptest.exe v) and you are using the lates SVN code, verify your version of binutils. See "crytest v" hangs up and Conflict between Crypto++ 5.6.0 and GNU binutils 2.19.91.20091014-0ubuntu1.

GCC 4.5.2 Internal Compiler Error

If you experience an internal compiler error when using GCC 4.5.2 on Ubuntu 11.04:

$ make
g++ -DNDEBUG -g -O2 -march=native -pipe -c 3way.cpp
g++ -DNDEBUG -g -O2 -march=native -pipe -c adler32.cpp
g++ -DNDEBUG -g -O2 -march=native -pipe -c algebra.cpp
g++ -DNDEBUG -g -O2 -march=native -pipe -c algparam.cpp
g++ -DNDEBUG -g -O2 -march=native -pipe -c arc4.cpp
g++ -DNDEBUG -g -O2 -march=native -pipe -c asn.cpp
asn.cpp: In member function ‘void
CryptoPP::OID::DEREncode(CryptoPP::BufferedTransformation&) const’:
asn.cpp:254:1: error: unrecognizable insn:
(insn 194 178 195 2 asn.cpp:248 (set (reg:SI 2 cx)
        (mem:QI (plus:SI (reg/f:SI 1 dx [orig:61 D.44160 ] [61])
                (const_int 4 [0x4])) [16 S1 A32])) -1 (nil))
asn.cpp:254:1: internal compiler error: in extract_insn, at recog.c:2104
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.5/README.Bugs> for instructions.
make: *** [asn.o] Error 1

Then comment out the -mtune=native in GNUMakefile:

cat GNUMakefile
...
ifneq ($(GCC42_OR_LATER),0)
ifeq ($(UNAME),Darwin)
CXXFLAGS += -arch x86_64 -arch i386
else
# CXXFLAGS += -march=native
endif
endif

stdlibc

If you start with an error regarding __static_initialization_and_destruction, with hundreds following, you most likely used gcc rather than g++:

> gcc -o test test.cpp -lcryptopp    # wrong!!!

Undefined Crypto++ Type

If gcc/g++ does not recognize a Crypto++ type (such as CryptoPP::Integer), verify the correct header is being included and verify the CryptoPP namespace is being used. Finally, verify gcc/g++ header paths. To display the default search directories of GCC, try:

> echo "" | gcc -o /tmp/tmp.o -v -x c -
> echo "" | g++ -o /tmp/tmp.o -v -x c++ -

Cannot find -lcryptopp (or -lcrypto++)

If you receive an error from collect2/ld stating cannot find -lcryptopp, the library is not installed or on path.

> g++ -o test test.cpp -lcryptopp
 .../i586-suse-linux/bin/ld: cannot find -lcryptopp
 collect2: ld returned 1 exit status

Verify the library is installed:

> whereis libcryptopp
 libcryptopp: /usr/lib/libcryptopp.a /usr/lib64/libcryptopp.a

If installed, try specifying the path with the -L option (below, change /usr/lib to the library location). (Also see GCC Options for Linking)

> g++ -o test test.cpp -L/usr/lib -lcryptopp

If the library is not installed and it cannot be found in the distribution, it might be named libcrypto++.a or libcrypto++.so (or vice-versa: libcryptopp.a or libcryptopp.so):

> g++ -o test test.cpp -lcrypto++

Undefined Reference to WSA Sockets

If you encounter link errors relating to sockets such as the following, you might need to add -lws2_32 to the link command. See trungantran's comments on Compile Error in socketft.cpp.

undefined reference to '_WSAEnumNetworkEvents@12' 
undefined reference to '_WSAEventSelect@12' 
undefined reference to '_WSAGetOverlappedResult@20' 
undefined reference to '_WSAGetOverlappedResult@20' 
undefined reference to '_WSARecv@28' 
undefined reference to '_WSASend@28'

Undefined Reference to pthread

If you encounter link errors relating to pthreads such as "undefined reference to pthread_key_create" when creating libcryptopp.so or cryptest.exe, add -pthread to the LDFLAGS (encountered on OpenBSD 4.8/4.9).

./libcryptopp.so: undefined reference to `pthread_getspecific'
./libcryptopp.so: undefined reference to `pthread_key_delete'
./libcryptopp.so: undefined reference to `pthread_key_create'
./libcryptopp.so: undefined reference to `pthread_setspecific'

If you encounter link errors relating to pthreads such as "undefined reference to pthread_key_create" when linking against a shared object, you most likely did not link against the pthread library. See Eugene Zolenko's comments on the Crypto++ user group.

/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/libcryptopp.so: 
undefined reference to `pthread_key_create' 
/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/libcryptopp.so: 
undefined reference to `pthread_getspecific' 
/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/libcryptopp.so: 
undefined reference to `pthread_key_delete' 
/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/libcryptopp.so: 
undefined reference to `pthread_setspecific'

Try including the pthread library:

> g++ -o test test.cpp -lcryptopp -lpthread

File number X already allocated

If using precompiled headers and you get a message similar to "file number 2 already allocated", see Including a precompiled header from another header causes invalid assembly to be generated. The take away: upgrade to GCC 4.5.

No such instruction: pclmulqdq

pclmulqdq is part of Intel AVX. According to Intel Software Development Emulator, "GCC 4.4 includes support for these [AESNI and PCLMULQDQ] instructions". H.J. Lu's patch was submitted in 2008 and can be found at PATCH: Enable Intel AES/CLMUL.

cpu.h:53:no such instruction: `pclmulqdq $16, -64(%rbp),%xmm0' 
cpu.h:53:no such instruction: `pclmulqdq $0, -192(%rbp),%xmm0' 
cpu.h:53:no such instruction: `pclmulqdq $0, -80(%rbp),%xmm0' 
cpu.h:53:no such instruction: `pclmulqdq $16, -112(%rbp),%xmm0' 
cpu.h:53:no such instruction: `pclmulqdq $1, -144(%rbp),%xmm1' 
...

According to X86 Built-in Functions, GCC requires the following to generate the instruction:

The following built-in function is available when -mpclmul is used.

v2di __builtin_ia32_pclmulqdq128 (v2di, v2di, const int)
    Generates the pclmulqdq machine instruction.

If your processor does not support the instruction, or you don't want to generate AESNI and PCLMULQDQ instructions, define CRYPTOPP_DISABLE_AESNI.

Debugging

If you attempt to debug a program linked to libcryptopp.a (or libcryptopp.so) and you cannot list your source file:

> (gdb) list main                                                               
No line number known for main.

Verify that you have compiled with debugging information (the -g option):

> g++ -g -ggdb test.cpp -o test -lcryptopp

If you are using a distribution's library, make sure you have installed the development library and the debug symbols:

> # Debian, Ubuntu, and other Debian derivatives
> apt-get install libcryptopp-dev libcryptopp-dbg
$ # Fedora and other RPM based systems
$ yum install cryptopp cryptopp-devel cryptopp-develdebug

With debug symbols present, listing and stepping should be available:

(gdb) list
5       #include "cryptopp/osrng.h"
6       #include "cryptopp/secblock.h"
7       using CryptoPP::AutoSeededRandomPool;
8       using CryptoPP::SecByteBlock;        
9                                            
10      int main( int, char** ) {            
11
12        AutoSeededRandomPool prng;
13        SecByteBlock block(16);
14
15        prng.GenerateBlock(block, block.size());
16
17        return 0;
18      }

Downloads

Cryptopp-SO-Test.zip - test harness with multiple threads that calls one of four [test] shared objects (each is distinct). The four [test] shared objects each loads the libcryptopp.so shared object. See Note for Distribution Packagers above.