4

我正在使用clang(而不是gcc)、compiler-rt(而不是libgcc)、libunwind(可在http://llvm.org/git/libunwind.git上获得)(而不是libgcc_s)、lld(而不是 GNU ld)交叉编译一个实验性的 GNU 自由 Linux 工具链,libcxx(而不是libstdc++),libcxxabi(而不是不确定,我不清楚 GNUlibstdc++及其 ABI 之间的区别)和musl(而不是glibc)。

使用musl基于gcc交叉编译器和一些补丁,我成功地编译了上述所有内容,并成功编译并链接了一个简单的 hello world C 程序。然而,似乎出了点问题,因为运行 hello world 程序会导致分段错误:

$ ./hello
Segmentation fault
$ 

通常我会简单地用 gdb 调试它,但问题就在这里:

$ gdb ./hello
Reading symbols from ./hello...Dwarf Error: Could not find abbrev number 5 in CU at offset 0x52 [in module /home/main/code/main/asm/hello]
(no debugging symbols found)...done.
(gdb) start
Temporary breakpoint 1 at 0x206
Starting program: /hello 
During startup program terminated with signal SIGSEGV, Segmentation fault.
(gdb) 

我似乎无法以任何方式逐步执行程序,我猜是因为错误发生在早期 C 运行时启动的某个地方。我什至无法使用layout asmand逐步完成程序集stepi,所以我真的不知道如何找出错误发生的确切位置(调试我的工具链)。

我已经确认问题在于lld使用 GNU binutilsld使用交叉编译的库和目标文件成功链接 hello world 对象(静态),从而产生一个功能性的 hello world 程序。但是,由于lld成功链接,我无法确定发生故障的位置。

注意我编译hello为静态可执行文件并使用-v gcc/clang选项来验证所有正确的库和目标文件是否已链接它。

注意在线 GDB 文档对上述错误有以下说法:

在 Unix 系统上,默认情况下,如果您的目标上有可用的 shell,gdb) 使用它来启动您的程序。run 命令的参数被传递给 shell,shell 执行变量替换、扩展通配符和执行 I/O 重定向。在某些情况下,禁用 shell 的这种使用可能很有用,例如,在调试 shell 本身或诊断启动失败时,例如:

(gdb) run
Starting program: ./a.out
During startup program terminated with signal SIGSEGV, Segmentation fault.

这表明用 'exec-wrapper' 指定的外壳或包装器崩溃了,而不是你的程序。

我认为这不是真的,考虑到我正在使用的东西,并且当我使用 GNU 时问题不会发生ld,并且因为建议的解决方案 ( set startup-with-shell off) 不起作用。

4

1 回答 1

2

交叉编译意味着编译是在主机上完成的,编译的输出是要在目标机器上运行的二进制文件。因此编译后的二进制文件与您的主机CPU不兼容。相反,如果您的目标支持这一点,您可以在那里运行二进制文件并使用工具链中的调试器远程连接到正在运行的二进制文件(如果支持)。或者,调试器也可能在目标上可用,您可以在适当的位置调试二进制文件。

只是为了获得更多感觉,尝试对file编译的二进制文件和主机的其他一些二进制文件使用命令来查看可能的差异。

于 2016-01-08T08:09:18.773 回答