Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gcc -g flag: Moving the Source Code

Tags:

c

gcc

gdb

objdump

My understanding is that when you compile C code using gcc -g, gcc will insert debugging information that includes references to the original source code (e.g. line numbers). Then other programs such as gdb and objdump can recover these references later on. For sake of an example, we'll use objdump -S which prints assembly interleaved with corresponding source code.

My goal is to copy the compiled binaries to a different computer and still be able retrieve this debug information. Currently, though, when I do this all of the debugging information is lost. I don't mind copying over the source files as well, but the second computer is running a different OS, so the file structure is different and I can't place the source files in exactly the same absolute location, which prevents objdump from finding the source code. I looked at the binary and saw a section that looks like this interspersed with a bunch of binary:

/home/path/to/source/code

I tried editing that to match the new path to the source but it just made the binary invalid.

I also researched gcc flags hoping that one of them would allow specifying a relative path to the source code instead of an absolute path, but I couldn't find anything like that.

For reference, here is the sort of output that I'm hoping to get from 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);
      }
    }
  }
}

Note: Although I used objdump as an example of a program which uses information about the source file, it is not actually the output of objdump which I'm interested in. I'm running a different program which needs access to this same information. The question is about how to fix the binaries, not how to use objdump.

like image 793
Flight Odyssey Avatar asked Apr 16 '17 18:04

Flight Odyssey


Video Answer


1 Answers

gcc and clang, when generating debug info, will set the DWARF attribute DW_AT_comp_dirto the working directory for each compilation unit in the object file.

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

will show something like

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

The program usually used to transform object files, objcopy, doesn't currently support changing these DWARF attributes.

But gcc and clang take an -fdebug-prefix-map option, which ought to do what you want at compilation time.

Since gcc gets the current directory using libiberty's getpwd function, which uses the PWD environment variable (after checking it for correctness) in preference to libc's getcwd, we can get the same value by running the shell's pwd -L builtin.

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

will output ., instead of the pathname of the current directory, in the DW_AT_comp_dir attribute.

like image 79
Mark Plotnick Avatar answered Sep 20 '22 08:09

Mark Plotnick