linux下可执行文件无法执行问题定位排查

引言:

     最近使用centos7.4 minimal装环境,在编译一个可执行文件后,无法运行改可执行文件。

参考:

https://www.cnblogs.com/wanghetao/p/3779611.html

https://blog.csdn.net/qq_26819733/article/details/50610129

https://www.cnblogs.com/findumars/p/7128511.html

问题排查

报错信息如下:

xxxxx>test
test: error while loading shared libraries: libmqic.so: wrong ELF class: ELFCLASS64

翻译过来大致意思如下: 加载动态库libmqic.so出错,原因是该库为64位文件。

的确,test是我编译的32bits的可执行文件,使flie可以查看出文件位数

>file test
test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=db1dfaa8ad3d16e5aa5c109b05ac22f1f092954d, not stripped

根据以上结果我推断出可能是依赖的 libmqic.so是32位的。于是查找对应的makefile文件。

gcc -m32 -o ../bin/test comm.o util.o test.o -L/opt/mqm/lib -lmqic 

发现编译的时候链接的动态库为 /opt/mqm/lib/libmqic.so,查看该库位数为32位

>file /opt/mqm/lib/libmqic.so
/opt/mqm/lib/libmqic.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=7003de3a60f76e90232a89982daa3e3b16b5d776, not stripped

那问题来了,为什么编译的使用的32的libmqic.so库(如果使用64的库链接的时候就会报错,压根到不了运行时)还是报错。这时候重点来了,使用ldd命令(ldd,命令介绍推荐)查看该bin文件依赖的动态库


>ldd test 
	linux-gate.so.1 =>  (0xf771c000)
	libmqic.so => not found
	libc.so.6 => /lib/libc.so.6 (0xf7548000)
	/lib/ld-linux.so.2 (0xf771d000)

通过ldd的结果可以看出 libmqic.so =>not found,意味着bin文件中没有找到对应的 libmqic.so动态库,但是 /opt/mqm/lib/存在libmqic.so库,从这里已经基本断定是环境变量的问题导致bin在执行的时候找不到关联的动态库。

一般找不到动态库的问题可以有三种方式解决:

  1. 添加对应软连接(软件存放路径/usr/lib 或者/lib) 如下:
ls -s /opt/mqm/libmqic.so /usr/lib/libmqic.so

    2. /etc/ld.so.conf 追加依赖的动态库路径,并使用运行一个命令:ldconfig (该命令用来刷新系统的共享库缓存,即 /etc/ld.so.cache 文件),

     3. 修改环境变量LD_LIBRARY_PATH增加对应动态库路径

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/mqm/lib:

建议使用第三种方式,简单方便灵活。

那最后一个问题,为什么bin文件在运行时报错:test: error while loading shared libraries: libmqic.so: wrong ELF class: ELFCLASS64呢?

原因是:编译的时候使用的/opt/mqm/lib/libmqic.so(32-bit),但是运行的时候找到的libmqic.so是/opt/mqm/lib64的,该库是64的库(/opt/mqm/lib64被我加到环境变量LD_LIBRARY_PATH中了,但是 /opt/mqm/lib没有放到环境变量中),但是执行文件是32-bit的。

总结:

   对动态库的链接方式有点模糊了,编译的时候指定的动态库进行链接的过程实际上只是编译时只获取必要的接口信息(全局符号)已经编译检查。动态库只有在执行的时候的才会被加载。但是如果程序运行的过程找不到对应的动态库就会报错。

猜你喜欢

转载自blog.csdn.net/u011461385/article/details/81776394