【问题标题】:How to debug program with custom elf interpreter?如何使用自定义精灵解释器调试程序?
【发布时间】:2015-04-12 09:25:42
【问题描述】:

我可以像这样调试一些程序(比如 /bin/ls):

[ks@localhost ~]$ gdb -q --args /bin/ls
Reading symbols from /bin/ls...Reading symbols from /bin/ls...(no debugging symbols found)...done.
(no debugging symbols found)...done.
Missing separate debuginfos, use: debuginfo-install coreutils-8.22-19.fc21.x86_64
(gdb) start 
Temporary breakpoint 1 at 0x402990
Starting program: /usr/bin/ls 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Temporary breakpoint 1, 0x0000000000402990 in main ()
(gdb) 

这里我可以在main设置临时断点并停在它上面。

但我必须像这样使用自定义精灵解释器运行程序:

[ks@localhost ~]$ gdb -q --args /lib64/ld-linux-x86-64.so.2 /bin/ls
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/usr/lib64/ld-2.20.so.debug...done.
done.
(gdb) start 
Function "main" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Temporary breakpoint 1 (main) pending.
Starting program: /usr/lib64/ld-linux-x86-64.so.2 /bin/ls
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
1234            glibc-2.20      python     tmp
[Inferior 1 (process 2610) exited normally]
Missing separate debuginfos, use: debuginfo-install libacl-2.2.52-7.fc21.x86_64 libattr-2.4.47-9.fc21.x86_64 libcap-2.24-7.fc21.x86_64 pcre-8.35-8.fc21.x86_64
(gdb) 

这里 gdb 没有在 main 停止,因为 /bin/ls 的符号没有加载。 在这种情况下,如何强制 gdb 加载符号并在 main 处停止?

【问题讨论】:

    标签: debugging gdb ld elf


    【解决方案1】:

    你可以这样做:

    cat t.c
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
      printf("Hello\n");
      return 0;
    }
    
    gcc -g t.c
    gdb -q --args /usr/lib64/ld-linux-x86-64.so.2 ./a.out
    (gdb) start
    Function "main" not defined.
    Starting program: /usr/lib64/ld-linux-x86-64.so.2 ./a.out
    Hello
    [Inferior 1 (process 7134) exited normally]
    

    到目前为止,一切都与您观察到的相符。现在寻求解决方案:

    (gdb) set stop-on-solib-events 1
    (gdb) r
    Starting program: /usr/lib64/ld-linux-x86-64.so.2 ./a.out
    Stopped due to shared library event (no libraries added or removed)
    (gdb) c
    Continuing.
    Stopped due to shared library event:
      Inferior loaded /usr/lib64/ld-linux-x86-64.so.2
    (gdb) c
    Continuing.
    Stopped due to shared library event:
      Inferior loaded /usr/lib64/libc.so.6
    

    此时./a.out也已经加载完毕,可以通过以下方式确认:

    (gdb) info proc map
    process 7140
    Mapped address spaces:
    
              Start Addr           End Addr       Size     Offset objfile
                0x400000           0x401000     0x1000        0x0 /tmp/a.out
                0x600000           0x601000     0x1000        0x0 /tmp/a.out
                0x601000           0x602000     0x1000     0x1000 /tmp/a.out
          0x555555554000     0x555555579000    0x25000        0x0 /usr/lib64/ld-2.19.so
          0x555555779000     0x55555577a000     0x1000    0x25000 /usr/lib64/ld-2.19.so
          0x55555577a000     0x55555577c000     0x2000    0x26000 /usr/lib64/ld-2.19.so
          0x7ffff7c2a000     0x7ffff7c2d000     0x3000        0x0
          0x7ffff7c2d000     0x7ffff7df0000   0x1c3000        0x0 /usr/lib64/libc-2.19.so
          0x7ffff7df0000     0x7ffff7fef000   0x1ff000   0x1c3000 /usr/lib64/libc-2.19.so
          0x7ffff7fef000     0x7ffff7ff3000     0x4000   0x1c2000 /usr/lib64/libc-2.19.so
          0x7ffff7ff3000     0x7ffff7ff5000     0x2000   0x1c6000 /usr/lib64/libc-2.19.so
          0x7ffff7ff5000     0x7ffff7ff9000     0x4000        0x0
          0x7ffff7ff9000     0x7ffff7ffa000     0x1000        0x0 /etc/ld.so.cache
          0x7ffff7ffa000     0x7ffff7ffd000     0x3000        0x0
          0x7ffff7ffd000     0x7ffff7fff000     0x2000        0x0 [vdso]
          0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]
      0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]
    

    不幸的是,GDB 不明白它还应该为./a.out 加载符号。你必须告诉它:

    (gdb) add-symbol-file ./a.out
    The address where ./a.out has been loaded is missing
    

    有人会认为GDB需要的地址来自上面的info proc map:0x400000。一个是错误的。 GDB 需要的实际地址是.text 部分的开头,您可以从 readelf 获得:

    readelf -WS ./a.out | grep text
       [13] .text             PROGBITS        0000000000400440 000440 000182 00  AX  0   0 16
    

    返回 GDB:

    (gdb) add-symbol-file ./a.out 0x0000000000400440
    add symbol table from file "./a.out" at
        .text_addr = 0x400440
    Reading symbols from ./a.out...done.
    

    现在我们可以继续main

    (gdb) b main
    Breakpoint 1 at 0x400531: file t.c, line 6.
    (gdb) c
    Continuing.
    
    Breakpoint 1, main () at t.c:6
    6     printf("Hello\n");
    (gdb) n
    Hello
    7     return 0;
    

    瞧!

    附:重新运行二进制文件可能会给您带来一些问题:

    (gdb) r
    Starting program: /usr/lib64/ld-linux-x86-64.so.2 ./a.out
    Error in re-setting breakpoint 1: Cannot access memory at address 0x40052d
    Error in re-setting breakpoint 1: Cannot access memory at address 0x40052d
    Stopped due to shared library event (no libraries added or removed)
    

    这是因为ld-linux 尚未映射./a.out。但您可以继续:

    (gdb) c
    Continuing.
    Stopped due to shared library event:
      Inferior loaded /usr/lib64/ld-linux-x86-64.so.2
    (gdb) c
    Continuing.
    Stopped due to shared library event:
      Inferior loaded /usr/lib64/libc.so.6
    

    现在,./a.out 也已加载,因此您可以重新启用断点:

    (gdb) enable
    (gdb) continue
    Continuing.
    
    Breakpoint 1, main () at t.c:6
    6     printf("Hello\n");
    

    【讨论】:

    • 如果 GDB 能够以某种方式自动化该工作流,那将会很有趣。
    猜你喜欢
    • 2012-06-07
    • 2014-08-07
    • 2020-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-09
    • 2017-03-12
    • 1970-01-01
    相关资源
    最近更新 更多