当前位置:   article > 正文

gnuTLS链接错误:undefined reference to ‘mpz_XXXX’_/tmp/.mount_ss941r/usr/lib/libgnutls.so.30: versio

/tmp/.mount_ss941r/usr/lib/libgnutls.so.30: version `gnutls_3_6_9' not found

在工作过程中,编译并使用libgnutls.a静态库时出现如下报错:

./lib/libs/libgnutls.a(provable-prime.o): In function `st_provale_prime_small`:
/root/gnutls-3.6.4/lib/nettle/int/provable-prime.c:1026: undefined reference to `mpz_init`
……
  • 1
  • 2
  • 3

问题现象为:没有 mpz_init()接口的定义,即链接时没有找到这个符号的定义。

1、查看libgnutls.a静态库的符号表,确认请求的符号mpz_init格式

$ nm -A ./libgnutls.a | grep mpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:dsa-keygen-fips186.o: U mpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:dsa-validate.o: U mpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:lt18-mpi.o: U mpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:lt19-pk.o: U mpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:provable-prime.o: U mpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:rsa-keygen-fips186.o: U mpz_init

2、查看libgmp.a静态库的符号表,确认是否包含符号mpz_init

$ nm -A /usr/lib/x86_64-linux-gnu/libgmp.a | grep mpz_init
/usr/lib/x86_64-linux-gnu/libgmp.a:bin_ui.o: U __gmpz_init
/usr/lib/x86_64-linux-gnu/libgmp.a:bin_ui.o: U __gmpz_init_set_ui
/usr/lib/x86_64-linux-gnu/libgmp.a:mfac_uiui.o: U __gmpz_init
/usr/lib/x86_64-linux-gnu/libgmp.a:lt22-init.o:0000000000000000 T __gmpz_init
/usr/lib/x86_64-linux-gnu/libgmp.a:lt23-init2.o:0000000000000000 T __gmpz_init2
/usr/lib/x86_64-linux-gnu/libgmp.a:lt24-inits.o:0000000000000000 T __gmpz_inits
/usr/lib/x86_64-linux-gnu/libgmp.a:lt26-iset.o:0000000000000000 T __gmpz_init_set
/usr/lib/x86_64-linux-gnu/libgmp.a:lt27-iset_d.o:0000000000000000 T __gmpz_init_set_d
/usr/lib/x86_64-linux-gnu/libgmp.a:lt28-iset_si.o:0000000000000000 T __gmpz_init_set_si
/usr/lib/x86_64-linux-gnu/libgmp.a:lt29-iset_str.o:0000000000000000 T __gmpz_init_set_str
/usr/lib/x86_64-linux-gnu/libgmp.a:lt30-iset_ui.o:0000000000000000 T __gmpz_init_set_ui
/usr/lib/x86_64-linux-gnu/libgmp.a:remove.o: U __gmpz_init
/usr/lib/x86_64-linux-gnu/libgmp.a:remove.o: U __gmpz_init_set
/usr/lib/x86_64-linux-gnu/libgmp.a:randlc2s.o: U __gmpz_init_set_str
/usr/lib/x86_64-linux-gnu/libgmp.a:randlc2x.o: U __gmpz_init
/usr/lib/x86_64-linux-gnu/libgmp.a:randlc2x.o: U __gmpz_init2
/usr/lib/x86_64-linux-gnu/libgmp.a:randlc2x.o: U __gmpz_init_set
/usr/lib/x86_64-linux-gnu/libgmp.a:randmts.o: U __gmpz_init2
/usr/lib/x86_64-linux-gnu/libgmp.a:randmts.o: U __gmpz_init_set

注意这一行:
/usr/lib/x86_64-linux-gnu/libgmp.a:lt22-init.o:0000000000000000 T __gmpz_init
根据上面的内容,可以确定libgmp.a中,符号格式为__gmpz_init

问题原因初步可以确定

请求的符号格式与 静态库提供的符号内容不一致,在链接的时候没有找到函数定义,从而编译失败了。

3、查看报错位置的原文件内容

源文件/lib/nettle/int/provable-prime.c包含头文件内容如下:

#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <assert.h>
#include <stdlib.h>
#include <nettle/memxor.h>
#include <nettle/bignum.h>    //注意这一行,该文件包含头文件 gmp.h
#include <dsa-fips.h>

#include <nettle/macros.h>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

继续查看头文件 <nettle/bignum.h>: /usr/include/nettle/bignum.h

#ifndef NETTLE_BIGNUM_H_INCLUDED
#define NETTLE_BIGNUM_H_INCLUDED

#include "nettle-meta.h"

#include "nettle-types.h"

/* For NETTLE_USE_MINI_GMP */
#include "version.h"

#if NETTLE_USE_MINI_GMP
# include "mini-gmp.h"                   // 注意该行

# define GMP_NUMB_MASK (~(mp_limb_t) 0)

/* Function missing in older gmp versions, and checked for with ifdef */
# define mpz_limbs_read mpz_limbs_read
/* Side-channel silent powm not available in mini-gmp. */
# define mpz_powm_sec mpz_powm
#else
# include <gmp.h>                      // 注意该行
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

头文件中通过宏开关NETTLE_USE_MINI_GMP来指明包含哪个头文件。

4、分别查看 mini-gmp.hgmp.h 文件中 函数的声明

mini-gmp.h 中内容摘取如下:

……
void mpz_init (mpz_t);
void mpz_init2 (mpz_t, mp_bitcnt_t);
……
  • 1
  • 2
  • 3
  • 4

gmp.h 中内容摘取如下:

……
#define mpz_init __gmpz_init
__GMP_DECLSPEC void mpz_init (mpz_ptr) __GMP_NOTHROW;

#define mpz_init2 __gmpz_init2
__GMP_DECLSPEC void mpz_init2 (mpz_ptr, mp_bitcnt_t);
……
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

当调用 gmp.h头文件,在预编译阶段会将所用的 mpz_init字段替换为 __gmpz_init,结合第2步骤中查看的 libgmp.a静态库符号表,可以确定 编译 libgmp时包含的头文件时gmp.h

根据上面内容进而可以判断出

在编译libgnutls.a静态库时调用的头文件是mini-gmp.h

证明该结论可以在头文件/usr/include/nettle/bignum.h添加error打印来确定:

……
/* For NETTLE_USE_MINI_GMP */
#include "version.h"

#if NETTLE_USE_MINI_GMP
# error "use mini-gmp.h"    //添加的error打印
# include "mini-gmp.h"

# define GMP_NUMB_MASK (~(mp_limb_t) 0)

/* Function missing in older gmp versions, and checked for with ifdef */
# define mpz_limbs_read mpz_limbs_read
/* Side-channel silent powm not available in mini-gmp. */
# define mpz_powm_sec mpz_powm
#else
# error "gmp.h"    //添加的error打印
# include <gmp.h>
#endif
……
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

重新编译libgnutls.a,根据编译错误打印可以证明前面所述的结论成立。

5、解决编译问题

临时解决方法:在头文件/usr/include/nettle/bignum.h中,取消宏定义开关NETTLE_USE_MINI_GMP,如下:

……

#undef NETTLE_USE_MINI_GMP     // 取消宏定义开关

#if NETTLE_USE_MINI_GMP
# include "mini-gmp.h"

# define GMP_NUMB_MASK (~(mp_limb_t) 0)

/* Function missing in older gmp versions, and checked for with ifdef */
# define mpz_limbs_read mpz_limbs_read
/* Side-channel silent powm not available in mini-gmp. */
# define mpz_powm_sec mpz_powm
#else
# include <gmp.h>     // 此时会包含该头文件
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

再次编译 libgnutls.a静态库,编译好后查看静态库中需要的符号格式内容如下:

$ nm -A /usr/lib/x86_64-linux-gnu/libgnutls.a | grep mpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:dsa-keygen-fips186.o: U __gmpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:dsa-validate.o: U __gmpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:lt18-mpi.o: U __gmpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:lt19-pk.o: U __gmpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:provable-prime.o: U __gmpz_init
/usr/lib/x86_64-linux-gnu/libgnutls.a:rsa-keygen-fips186.o: U __gmpz_init

继续项目编译,问题解决

正规解决方法: 在编译 libnettle.a 静态库,在nettle项目中执行 命令:

./configure

时,添加选项参数 --enable-mini-gmp=no, 重新编译 libgmp.a,并重新安装 libgmp*(没有测试确认)*

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/190988
推荐阅读
相关标签
  

闽ICP备14008679号