如何调试产生畸形可执行文件的实验性工具链 [英] How to debug an experimental toolchain producing malformed executables

查看:180
本文介绍了如何调试产生畸形可执行文件的实验性工具链的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 clang (而不是), compiler-rt (而不是libgcc),libunwind(在 http://llvm.org/git/libunwind.git )(而不是libgcc_s), lld (而不是GNU ld), libcxxabi (而不是不确定,我不清楚libstdc++及其ABI之间的GNU区别)和 musl (而不是glibc).

使用基于gcc交叉编译器的 rel ="nofollow"> 和一些补丁成功地编译了所有上述内容,并成功地编译并链接了一个简单的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 asmstepi逐步完成程序集,所以我真的不知道如何找出错误发生的确切位置(调试我的工具链).

我已经确认问题出在lld上,方法是使用GNU binutils ld使用交叉编译的库和目标文件成功地(静态地)链接hello world对象,这将导致功能正常的hello world程序.但是,由于lld成功链接,所以我无法查明发生故障的位置.

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

请注意在线GDB文档对上述内容有以下看法错误:

在Unix系统上,默认情况下,如果目标计算机上有外壳程序,则gdb)使用它来启动程序. run命令的参数传递给外壳程序,该外壳程序执行变量替换,扩展通配符并执行I/O重定向.在某些情况下,例如在调试外壳程序本身或诊断启动失败时,例如,禁用外壳程序的使用可能是有用的:

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

表示用exec-wrapper指定的外壳或包装崩溃了,而不是程序崩溃了.

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

解决方案

croscompilling意味着编译是在主机机器上完成的,编译的输出是二进制文件,应在该二进制文件上运行目标计算机.因此,编译后的二进制文件与您的主机 CPU不兼容.相反,如果您的 target 支持此功能,则可以在此处运行二进制文件,并使用工具链中的调试器(如果支持)远程连接到正在运行的二进制文件.或者,也可以在 target 上使用调试器,并且可以调试已经存在的二进制文件.

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

I am working on cross compiling an experimental GNU free Linux toolchain using clang (instead of gcc), compiler-rt (instead of libgcc), libunwind (available at http://llvm.org/git/libunwind.git) (instead of libgcc_s), lld (instead of GNU ld), libcxx (instead of libstdc++), libcxxabi (instead of not sure, I'm unclear on the GNU distinction between libstdc++ and its ABI) and musl (instead of glibc).

Using a musl based gcc cross compiler and a few patches I've managed to successfully compile all of the above and sucessfully compile and link a simple hello world C program with it. Something seems to have gone wrong, however, as running the hello world program results in a segmentation fault:

$ ./hello
Segmentation fault
$ 

Normally I would simply debug it with gdb, but herein lies the problem:

$ 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) 

I can't seem to step through the program in any way, I'm guessing because the error is occuring somewhere in early C runtime startup. I can't even step through the assembly using layout asm and stepi, so I really don't know how to find out where exactly the error is occuring (to debug my toolchain).

I have confirmed that the problem resides with lld by using a GNU binutils ld to successfully link the hello world object (statically) using the cross compiled libraries and object files, which results in a functional hello world program. Since lld successfully links, however, I can't pinpoint where failure is occuring.

Note I compiled hello as a static executable and used the -v gcc/clang option to verify that all the correct libraries and object files were linked it.

Note online GDB documentation has the following to say about the above error:

On Unix systems, by default, if a shell is available on your target, gdb) uses it to start your program. Arguments of the run command are passed to the shell, which does variable substitution, expands wildcard characters and performs redirection of I/O. In some circumstances, it may be useful to disable such use of a shell, for example, when debugging the shell itself or diagnosing startup failures such as:

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

which indicates the shell or the wrapper specified with ‘exec-wrapper’ crashed, not your program.

I don't think this is true, considering what I'm working with and that the problem doesn't happen when I use GNU ld, and because the suggested solution (set startup-with-shell off) doesn't work.

解决方案

The croscompilling means that the compilation is done on a host machine, and the output of the compilation is the binary which shall run on a target machine. Therefore the compiled binary is not compatible with your host CPU. Instead, if your target supports this, you could run the binary there and use the debugger from your toolchain to connect to the running binary remotely if supported. Or alternatively, the debugger may also be available at the target and you can debug the binary already at place.

Just to get more feeling, try to use command file for the compiled binary, and some other binaries of your host to see possible differences.

这篇关于如何调试产生畸形可执行文件的实验性工具链的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆