I have a build issue that I can't seem to figure out. I'm building a command-line tool that is written in C with some portions in C++. My issue is however not related to C++.
The tool links statically to some other libraries such as a communication library and a custom Kerberos utility library that has been ported over from Windows. That has always worked. Recently the communication library on the Windows side has been updated to support encryption using the open source libraries tomcrypt (www.libtom.org) and tommath. They are wrapped using a small custom C++ library.
When I build the command-line tool I get the following error:
The first entry in the list (km.o) is part of the custom C++ wrapper library. The other entries are from within tomcrypt itself.Code:Undefined symbols: "_ltc_mp", referenced from: _ltc_mp$non_lazy_ptr in libcrypto.a(km.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(rsa_import.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(rsa_make_key.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(rsa_exptmod.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(ltc_ecc_mulmod.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(ltc_ecc_map.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(rand_prime.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(multi.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(ltc_ecc_projective_add_point.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(ltc_ecc_mul2add.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(ltc_ecc_projective_dbl_point.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(der_decode_integer.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(der_length_integer.o) _ltc_mp$non_lazy_ptr in liblibtomcrypt.a(der_encode_integer.o) ld: symbol(s) not found collect2: ld returned 1 exit status
ltc_mp is defined in the tomcrypt file misc/crypt/crypt_ltc_mp_descriptor.c. The file is short and sweet:
ltc_math_descriptor is defined in headers/tomcrypt_math.h:Code:#include "tomcrypt.h" ltc_math_descriptor ltc_mp;
It is used in the following way in the C++ wrapper to set the math library to use:Code:/** math descriptor */ typedef struct { /** Name of the math provider */ char *name; /** Bits per digit, amount of bits must fit in an unsigned long */ int bits_per_digit; int (*init)(void **a); int (*init_copy)(void **dst, void *src); void (*deinit)(void *a); int (*neg)(void *src, void *dst); int (*copy)(void *src, void *dst); int (*set_int)(void *a, unsigned long n); unsigned long (*get_int)(void *a); unsigned long (*get_digit)(void *a, int n); int (*get_digit_count)(void *a); int (*compare)(void *a, void *b); int (*compare_d)(void *a, unsigned long n); int (*count_bits)(void * a); int (*count_lsb_bits)(void *a); int (*twoexpt)(void *a , int n); int (*read_radix)(void *a, const char *str, int radix); int (*write_radix)(void *a, char *str, int radix); unsigned long (*unsigned_size)(void *a); int (*unsigned_write)(void *src, unsigned char *dst); int (*unsigned_read)(void *dst, unsigned char *src, unsigned long len); int (*add)(void *a, void *b, void *c); int (*addi)(void *a, unsigned long b, void *c); int (*sub)(void *a, void *b, void *c); int (*subi)(void *a, unsigned long b, void *c); int (*mul)(void *a, void *b, void *c); int (*muli)(void *a, unsigned long b, void *c); int (*sqr)(void *a, void *b); int (*mpdiv)(void *a, void *b, void *c, void *d); int (*div_2)(void *a, void *b); int (*modi)(void *a, unsigned long b, unsigned long *c); int (*gcd)(void *a, void *b, void *c); int (*lcm)(void *a, void *b, void *c); int (*mulmod)(void *a, void *b, void *c, void *d); int (*sqrmod)(void *a, void *b, void *c); int (*invmod)(void *, void *, void *); int (*montgomery_setup)(void *a, void **b); int (*montgomery_normalization)(void *a, void *b); int (*montgomery_reduce)(void *a, void *b, void *c); void (*montgomery_deinit)(void *a); int (*exptmod)(void *a, void *b, void *c, void *d); int (*isprime)(void *a, int *b); int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *modulus, int map); int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp); int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *modulus, void *mp); int (*ecc_map)(ecc_point *P, void *modulus, void *mp); int (*ecc_mul2add)(ecc_point *A, void *kA, ecc_point *B, void *kB, ecc_point *C, void *modulus); int (*rsa_keygen)(prng_state *prng, int wprng, int size, long e, rsa_key *key); int (*rsa_me)(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int which, rsa_key *key); } ltc_math_descriptor;
I am now primarily porting the code to Mac OS X (and later to Linux). g++ and gcc 4.2 vs 4.0 in Xcode doesn't make any difference, nor does building with 10.6, 10.5 or 10.4 as the target. I have also tried moving the "ltc_math_descriptor ltc_mp;" to another file but that didn't have an effect either.Code:// register a math library (in this case LibTomMath) ltc_mp = ltm_desc;
I'm sort of stumped as to why I at all get the undefined symbol error. The C libraries contain the appropriate "extern "C" {}" wrappers.
I'd me immensely grateful if somebody could shed some light upon why I see the error from the linker.