如何调试生成格式错误的可执行文件的实验工具链

时间:2015-11-14 15:40:39

标签: c linux gcc clang lld

我正在使用clang(而非gcc),compiler-rt(而非libgcc),{{1}进行交叉编译实验性GNU免费Linux工具链(可在http://llvm.org/git/libunwind.git)(而不是libunwind),lld(而不是GNU libgcc_s),libcxx(而不是ld) ,libcxxabi(而不是不确定,我不清楚libstdc++与其ABI之间的GNU区别)和musl(而不是libstdc++)。

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

glibc

通常我只是用gdb调试它,但这就是问题所在:

$ ./hello
Segmentation fault
$ 

我似乎无法以任何方式单步执行该程序,我猜测是因为错误发生在早期C运行时启动的某个地方。我甚至无法使用$ 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) layout asm逐步完成程序集,所以我真的不知道如何确定错误发生的位置(调试我的工具链)。

我已经确认问题存在于stepi,使用GNU binutils lld使用交叉编译的库和目标文件成功链接hello world对象(静态),从而实现功能你好世界节目。但是,由于ld成功链接,我无法确定故障发生的位置。

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

注意online GDB documentation有关于上述错误的以下内容:

  

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

clang
  

表示用'exec-wrapper'指定的shell或包装器崩溃,而不是你的程序。

我不认为这是真的,考虑到我正在使用的内容,并且当我使用GNU (gdb) run Starting program: ./a.out During startup program terminated with signal SIGSEGV, Segmentation fault. 时问题不会发生,并且因为建议的解决方案({ {1}})不起作用。

1 个答案:

答案 0 :(得分:2)

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

为了获得更多感觉,请尝试使用命令file作为已编译的二进制文件,以及主机的其他一些二进制文件,以查看可能存在的差异。