GCC ARM可执行文件“找不到该文件或目录”,错误的动态库。

6

我正在尝试在Windows上为gcc-linaro-arm-linux-gnueabihf-4.8-2013.11创建可用的设置。 在动态链接时发生了一些问题:

$(CC)-gcc   -o test main.c -Wall -lc

该程序编译正常,但在ARM上部署时显示:“没有这样的文件或目录”。
查找该问题,似乎静态构建可以解决,但可执行文件很大。
$(CC)-gcc   -static -o test main.c -Wall -lc

现在我已经安装了VisualGDB工具链,使用它自己的工具链在IDE中构建了一个类似的可执行文件(小型、动态),所以我想这可能与我的ARM发行版没有问题。
我是否遗漏了什么或者gcc-linaro-arm-linux-gnueabihf-4.8-2013.11的包含有误?
非常感谢您的提前帮助,
再做一次调查:
file test

working (compiled with VisualGDB toolchain)
test: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, not stripped

mot working (compiled with gcc-linaro-arm-linux-gnueabihf-4.8-2013.11)
test: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.1.1, BuildID[sha1]=0x13accf06af902cd8b96d85b8a412e1d7822a302b, not stripped

my ARM
3.8.13

我运行了-readelf命令(针对非工作状态):
Dynamic section at offset 0x474 contains 24 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000c (INIT)                       0x82a0
 0x0000000d (FINI)                       0x8434
 0x00000019 (INIT_ARRAY)                 0x10468
 0x0000001b (INIT_ARRAYSZ)               4 (bytes)
 0x0000001a (FINI_ARRAY)                 0x1046c
 0x0000001c (FINI_ARRAYSZ)               4 (bytes)
 0x00000004 (HASH)                       0x8194
 0x00000005 (STRTAB)                     0x820c
 0x00000006 (SYMTAB)                     0x81bc
 0x0000000a (STRSZ)                      65 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x1055c
 0x00000002 (PLTRELSZ)                   32 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x8280
 0x00000011 (REL)                        0x8278
 0x00000012 (RELSZ)                      8 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x8258
 0x6fffffff (VERNEEDNUM)                 1
 0x6ffffff0 (VERSYM)                     0x824e
 0x00000000 (NULL)                       0x0

并且工作中:

Dynamic section at offset 0x4d0 contains 24 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000c (INIT)                       0x8274
 0x0000000d (FINI)                       0x8490
 0x00000019 (INIT_ARRAY)                 0x104c4
 0x0000001b (INIT_ARRAYSZ)               4 (bytes)
 0x0000001a (FINI_ARRAY)                 0x104c8
 0x0000001c (FINI_ARRAYSZ)               4 (bytes)
 0x00000004 (HASH)                       0x8168
 0x00000005 (STRTAB)                     0x81e0
 0x00000006 (SYMTAB)                     0x8190
 0x0000000a (STRSZ)                      65 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x105b8
 0x00000002 (PLTRELSZ)                   32 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x8254
 0x00000011 (REL)                        0x824c
 0x00000012 (RELSZ)                      8 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x822c
 0x6fffffff (VERNEEDNUM)                 1
 0x6ffffff0 (VERSYM)                     0x8222
 0x00000000 (NULL)                       0x0

strace日志:

execve("/usr/bin/test", ["test"], [/* 15 vars */]) = 0
brk(0)                                  = 0x17000
uname({sys="Linux", node="beaglebone", ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f8a000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=54751, ...}) = 0
mmap2(NULL, 54751, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb6f57000
close(3)                                = 0
open("/lib/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0@\321\0\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=1505830, ...}) = 0
mmap2(NULL, 152384, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6f31000
mprotect(0xb6f4f000, 28672, PROT_NONE)  = 0
mmap2(0xb6f56000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1d) = 0                                                                                   xb6f56000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\210\177\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1205468, ...}) = 0
mmap2(NULL, 1246600, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6e00000
mprotect(0xb6f24000, 28672, PROT_NONE)  = 0
mmap2(0xb6f2b000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x123) =                                                                                    0xb6f2b000
mmap2(0xb6f2e000, 9608, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb                                                                                   6f2e000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f89000
set_tls(0xb6f896d0, 0xb6f89da8, 0xb6f8c058, 0xb6f896d0, 0xb6f8c058) = 0
mprotect(0xb6f2b000, 8192, PROT_READ)   = 0
mprotect(0xb6f8b000, 4096, PROT_READ)   = 0
munmap(0xb6f57000, 54751)               = 0
brk(0)                                  = 0x17000
brk(0x38000)                            = 0x38000
close(1)                                = 0
close(2)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++
4个回答

9

我自己解决了,无论如何感谢您的支持。

Linaro的交叉编译器链接了一个新的库名(在Debian中有一些名称更改),例如/lib/ld-linux-armhf.so.3,但BBB(默认)发行版使用旧的名称/lib/ld-linux.so.3。这两个名称都应该在BBB上指向(符号链接)实际使用的库ld-2.16.so。

因此,创建另一个符号链接就可以了。

ln -s /lib/ld-2.16.so /lib/ld-linux-armhf.so.3

-rwxr-xr-x 1 root root 130304 Mar 20  2013 /lib/ld-2.16.so
lrwxrwxrwx 1 root root     15 Dec 24 23:14 /lib/ld-linux-armhf.so.3 -> /lib/ld-2.16.so          <-- new one
lrwxrwxrwx 1 root root     10 Jun 19  2013 /lib/ld-linux.so.3 -> ld-2.16.so

亲爱的大家,祝你们圣诞快乐!最好的问候!

1
我浪费了好几个小时在这上面,谢谢。 对于任何遇到类似问题的人,你可以使用“strings”命令来检查库(strings ~/development/test.elf | grep lib /lib/ld-linux-armhf.so.3 libstdc++.so.6 libm.so.6 libgcc_s.so.1 libc.so.6 __libc_start_main)。如果你使用不同的工具链,也可以参考此方法。 - John

1
可能是在部署机器上缺少共享库。
尝试运行$(CC)-readelf -d your-binary | grep NEEDED。这将显示所需的共享库的名称。请验证它们是否出现在目标机器上。
尝试在目标机器上运行ldd you-binary。它应报告所需的动态库及其是否已找到。
PS. 使用strace your-binary在目标上运行程序。查找返回错误ENOENTopenaccess调用。

strace 看上面(感谢指点,这是一个很好的工具),你能帮我一下理解错误吗?似乎 /etc/ld.so.preload 丢失了(或者我的 libc 只包含了一些来自那里的符号)。 - user1797147
不,ld.so.preload并不是严格要求的。我在这个strace输出中看不出任何问题 :( - chill

1
编译器在链接器中添加选项mfloat-abi=hardLDFLAGS,使用ld-linux-armhf.so.3加载程序,而不是ld-linux.so.3。无需符号链接。至少对于我的Yocto Poky工具链来说,它解决了这个问题。参见https://github.com/golang/go/issues/12443

0

我可以想到以下解决方法,因为我之前遇到过类似的问题。

ARM发行版在其分发中有所需的库,例如在/usr/lib或/lib等文件夹中,而您的编译环境将这些库放在不同的位置。如果是这种情况,则可以:

  • 使用ld_library_path环境变量(或.bashrc)设置库路径可能会有所帮助
  • 或者创建与您系统中相同的文件夹结构也可能有所帮助

我可以看出,您的交叉编译没有考虑任何硬件特定的库,而只是新硬件的系统库它将依赖于。

当然,我假设您已经对您的ARM硬件或模拟器进行了chmod以使您的程序可执行。


我尝试在Windows上为Linux Angstrom进行交叉编译,是的,我已经添加了+x权限 :) - user1797147

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接