gdbgdbserver

gdb remote debugging: symbol addresses in local file not relocated


The following workflow worked for me at one point, and then it suddenly stopped working. I'd like to figure out why and get it to work again.

  1. on the host, build binary for target system with debug information
  2. send the stripped version of the binary to the target system
  3. on the target, run the binary with gdbserver :6006 mybinary args...
  4. on the host, run gdb-multiarch mybinary. This is the unstripped version. It shows that it loaded symbols from the local binary.
  5. At the gdb prompt, run target remote <ip_of_target>:6006
  6. Then, if I say b main, it inserts a breakpoint at an unrelocated address like 0x621730, which is the offset of the main function in the local binary, whereas it should be added on top of the VM address the remote binary is loaded at (0x5555555000 in this case.) Obviously the unrelocated address doesn't work.

So step 6 was working at one point. I don't know what I'm doing now differently to make the relocation no longer work. Help would be appreciated.

Version of gdbserver and that of host gdb are both Ubuntu 8.1.1-0ubuntu1. The remote system is aarch64.


Solution

  • So step 6 was working at one point. I don't know what I'm doing now differently to make the relocation no longer work.

    I suspect that you have upgraded your toolchain, and that your upgraded toolchain produces a Position-Independent Executable mybinary by default, where the old toolchain didn't.

    Try adding -no-pie to the link line of mybinary.

    Obviously the unrelocated address doesn't work.

    Actually, this does work for local debugging -- GDB is smart enough to realize that the code got loaded at a different address:

    gdb -q a.out
    Reading symbols from a.out...
    
    (gdb) b main
    Breakpoint 1 at 0x112d: file t.c, line 1.      <<< Note: unrelocated address
    (gdb) run
    Starting program: /tmp/a.out
    
    Breakpoint 1, main () at t.c:1
    1       int main() {return 0; }
    (gdb) p/x $pc
    $1 = 0x55555555512d                            <<< Note: breakpoint worked.
    

    It's possible that remote debugging doesn't work, although this worked fine for me using GDB-10.0:

    strip a.out -o b.out
    gdbserver :6006 ./b.out
    Process ./b.out created; pid = 239653
    Listening on port 6006
    
    ... in another window:
    gdb -q ./a.out
    Reading symbols from ./a.out...
    
    (gdb) target remote :6006
    Remote debugging using :6006
    Reading /lib64/ld-linux-x86-64.so.2 from remote target...
    warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
    Reading /lib64/ld-linux-x86-64.so.2 from remote target...
    Reading symbols from target:/lib64/ld-linux-x86-64.so.2...
    Reading symbols from /usr/lib/debug/.build-id/a8/97a1105e21dd270bd418fe58c441700a6d8ec5.debug...
    0x00007ffff7fe4940 in _start () from target:/lib64/ld-linux-x86-64.so.2
    (gdb) b main
    Breakpoint 1 at 0x55555555512d: file t.c, line 1.