【问题标题】:gcc -g flag: Moving the Source Codegcc -g 标志:移动源代码
【发布时间】:2017-04-16 18:26:38
【问题描述】:

我的理解是,当你使用gcc -g 编译 C 代码时,gcc 会插入调试信息,其中包括对原始源代码的引用(例如行号)。然后其他程序(例如 gdb 和 objdump)可以稍后恢复这些引用。举个例子,我们将使用objdump -S 打印与相应源代码交错的程序集。

我的目标是将编译后的二进制文件复制到另一台计算机上,并且仍然能够检索此调试信息。但是,目前,当我这样做时,所有调试信息都会丢失。我也不介意复制源文件,但是第二台计算机运行的是不同的操作系统,所以文件结构不同,我不能将源文件放在完全相同的绝对位置,这会阻止 objdump 找到源代码。我查看了二进制文件,看到一个看起来像这样的部分穿插着一堆二进制文件:

/home/path/to/source/code

我尝试编辑它以匹配源的新路径,但它只是使二进制文件无效。

我还研究了gcc flags,希望其中一个允许指定源代码的相对路径而不是绝对路径,但我找不到类似的东西。

作为参考,这是我希望从objdump - S 获得的那种输出:

0804840b <main>:
#include <stdio.h>
int main(){
 804840b:       8d 4c 24 04             lea    0x4(%esp),%ecx
 804840f:       83 e4 f0                and    $0xfffffff0,%esp
 8048412:       ff 71 fc                pushl  -0x4(%ecx)
 8048415:       55                      push   %ebp
 8048416:       89 e5                   mov    %esp,%ebp
 8048418:       51                      push   %ecx
 8048419:       83 ec 14                sub    $0x14,%esp
  for(int varName = 0; varName < 100; varName++){
 804841c:       c7 45 f0 00 00 00 00    movl   $0x0,-0x10(%ebp)
 8048423:       eb 32                   jmp    8048457 <main+0x4c>
    for(int innerLoop = 0; innerLoop < 30; innerLoop++){
 8048425:       c7 45 f4 00 00 00 00    movl   $0x0,-0xc(%ebp)
 804842c:       eb 1f                   jmp    804844d <main+0x42>
      if(innerLoop == varName){
 804842e:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048431:       3b 45 f0                cmp    -0x10(%ebp),%eax
 8048434:       75 13                   jne    8048449 <main+0x3e>
        printf("%d\n", innerLoop);
 8048436:       83 ec 08                sub    $0x8,%esp
 8048439:       ff 75 f4                pushl  -0xc(%ebp)
 804843c:       68 f0 84 04 08          push   $0x80484f0
 8048441:       e8 9a fe ff ff          call   80482e0 <printf@plt>
 8048446:       83 c4 10                add    $0x10,%esp
#include <stdio.h>
int main(){
  for(int varName = 0; varName < 100; varName++){
    for(int innerLoop = 0; innerLoop < 30; innerLoop++){
 8048449:       83 45 f4 01             addl   $0x1,-0xc(%ebp)
 804844d:       83 7d f4 1d             cmpl   $0x1d,-0xc(%ebp)
 8048451:       7e db                   jle    804842e <main+0x23>
#include <stdio.h>
int main(){
  for(int varName = 0; varName < 100; varName++){
 8048453:       83 45 f0 01             addl   $0x1,-0x10(%ebp)
 8048457:       83 7d f0 63             cmpl   $0x63,-0x10(%ebp)
 804845b:       7e c8                   jle    8048425 <main+0x1a>
 804845d:       b8 00 00 00 00          mov    $0x0,%eax
      if(innerLoop == varName){
        printf("%d\n", innerLoop);
      }
    }
  }
}

注意:虽然我使用 objdump 作为使用源文件信息的程序示例,但它实际上并不是我感兴趣的 objdump 的输出。我正在运行一个不同的程序,它需要访问它相同的信息。问题是关于如何修复二进制文件,而不是如何使用 objdump。

【问题讨论】:

  • 看起来不像objcopy,常用的修改目标文件的方式,目前支持改这个。但是 gcc 的 -fdebug-prefix-map 选项应该在编译时做你想做的事。 cc foo.c -g -fdebug-prefix-map=$(pwd)=. 应该在 DW_AT_comp_dir 属性中输出 . 而不是当前目录的路径名(这是您通常看到的)。运行objdump -Wi foo进行检查。
  • @MarkPlotnick 这似乎可行,谢谢!如果您将其作为答案,我会接受。
  • 我建议使用gcc -S -fverbose-asm(可能还使用-g和/或-O)来获取汇编代码

标签: c gcc gdb objdump


【解决方案1】:

gcc 和 clang 在生成调试信息时,会将 DWARF 属性 DW_AT_comp_dir 设置为目标文件中每个编译单元的工作目录。

cc a.c b.c -g -o foo
objdump -Wi foo

会显示类似

Contents of the .debug_info section:

  Compilation Unit @ offset 0x0:
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <11>   DW_AT_name        : a.c
    <15>   DW_AT_comp_dir    : (indirect string, offset: 0x0): /home/user/src

  Compilation Unit @ offset 0x4d:
 <0><58>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <5e>   DW_AT_name        : b.c
    <62>   DW_AT_comp_dir    : (indirect string, offset: 0x0): /home/user/src

通常用于转换目标文件的程序objcopy,目前不支持更改这些 DWARF 属性。

但是 gcc 和 clang 采用 -fdebug-prefix-map 选项,它应该在编译时做你想做的事情。

由于 gcc 使用 libiberty 的 getpwd 函数获取当前目录,该函数使用 PWD 环境变量(在检查其正确性之后)优先于 libc 的 getcwd,我们可以通过运行 shell 的 @ 来获得相同的值987654329@ 内置。

cc a.c b.c -g -fdebug-prefix-map=$(pwd -L)=. -o foo

将在DW_AT_comp_dir 属性中输出.,而不是当前目录的路径名。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-09
    • 2020-09-07
    • 1970-01-01
    • 2022-10-04
    • 2021-11-24
    • 2012-05-15
    • 1970-01-01
    • 2015-05-06
    相关资源
    最近更新 更多