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.
gcc and clang, when generating debug info, will set the DWARF attribute DW_AT_comp_dir
to 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With