如何使用自定义elf解释器来调试程序? [英] How to debug program with custom elf interpreter?

查看:280
本文介绍了如何使用自定义elf解释器来调试程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  [ks @ localhost〜] $ gdb我可以调试一些程序(比如/ bin / ls) -q --args / bin / ls 
从/bin/ls../中读取符号/从/bin/ls...读取符号(找不到调试符号)...完成。
(找不到调试符号)...完成。
缺少单独的debuginfos,请使用:debuginfo-install coreutils-8.22-19.fc21.x86_64
(gdb)start
临时断点1在0x402990
启动程序:/ usr / bin / ls
[使用libthread_db启用线程调试]
使用主机libthread_db库/lib64/libthread_db.so.1。

main()中的临时断点1,0x0000000000402990
(gdb)

在这里,我可以在 main 处设置临时断点,然后停下来。



但是我必须运行程序自定义的elf解释器是这样的:

$ p $ [ks @ localhost〜] $ gdb -q --args / lib64 / ld-linux -x86-64.so.2 / bin / ls
读取/lib64/ld-linux-x86-64.so.2...中的符号从/ usr / lib / debug / usr / lib64 / LD-2.20.so.debug ...完成。
完成。
(gdb)start
未定义函数main。
在将来的共享库加载时使断点处于待处理状态? (y或[n])y
临时断点1(主)正在等待。
启动程序:/usr/lib64/ld-linux-x86-64.so.2 / bin / ls
[使用libthread_db启用线程调试]
使用主机libthread_db库/ lib64 /的libthread_db.so.1\" 。
1234 glibc-2.20 python tmp
[不足1(进程2610)正常退出]
缺少单独的debuginfos,请使用: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

解决

  cat tc 
#include

stdio.h中>
#include< stdlib.h>

int main()
{
printf(Hello \\\
);
返回0;
}

gcc -g tc
gdb -q --args /usr/lib64/ld-linux-x86-64.so.2 ./a.out
(gdb)start
未定义函数main。
启动程序:/usr/lib64/ld-linux-x86-64.so.2 ./a.out
您好
[劣1(进程7134)正常退出]

到目前为止,所有内容都与您观察到的相符。现在的解决方案:

 (gdb)set stop-on-solib-events 1 
(gdb)r
启动程序:/usr/lib64/ld-linux-x86-64.so.2 ./a.out
由于共享库事件而停止(不添加或删除库)
(gdb )c
继续。
由于共享库事件而停止:
劣化加载/usr/lib64/ld-linux-x86-64.so.2
(gdb)c
继续。
由于共享库事件而停止:
劣质加载的/usr/lib64/libc.so.6

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

 (gdb)info proc map 
过程7140
映射的地址空间:

开始地址结束地址大小偏移量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 /
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 0x 1c3000 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 
地址./a.out已被加载失踪

有人会认为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 
从文件中添加符号表./a.out在
.text_addr = 0x400440
阅读./a.out...done中的符号。

现在我们可以打破 main

 (gdb)b main 
0x400531的断点1:file tc,line 6.
(gdb )c
继续。

断点1,main()在t.c:6
6 printf(Hello \\\
);
(gdb)n
你好
7返回0;

Voila!



重新运行二进制文件可能会给你一些小问题:

 (gdb)r 
启动程序:/ usr / lib64 /ld-linux-x86-64.so.2 ./a.out
重新设置断点的错误1:无法访问地址0x40052d的内存
重新设置断点的错误1:无法访问内存地址0x40052d
由于共享库事件而停止(不添加或删除库)

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

 (gdb)c 
继续。
由于共享库事件而停止:
劣化加载/usr/lib64/ld-linux-x86-64.so.2
(gdb)c
继续。
由于共享库事件而停止:
劣质加载的/usr/lib64/libc.so.6

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

 (gdb)启用
(gdb)继续
继续。

断点1,main()在t.c:6
6 printf(Hello \\\
);


I can debug some program (say /bin/ls) like this:

[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) 

Here I can set temporary breakpoint at main and stop at it.

But I have to run program with custom elf interpreter like this:

[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) 

Here gdb did not stop at main because symbols for /bin/ls were not loaded. How can I force gdb to load symbols and stop at main in this case?

解决方案

Here is how you can do it:

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]

So far everything is matching what you observed. Now for the solution:

(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

At this point, ./a.out has also been loaded, and you can confirm that with:

(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]

Unfortunately, GDB does not understand that it should also load symbols for ./a.out. You have to tell it:

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

One would think that the address that GDB needs would be from the above info proc map: 0x400000. One would be wrong. The actual address GDB needs is the start of .text section, which you can get from readelf:

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

Back to 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.

And now we can break on 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;

Voila!

P.S. Re-running the binary may give you some glitches:

(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)

This is happening because the ld-linux is yet to map the ./a.out. But you can continue:

(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

And now, ./a.out has also been loaded, so you can re-enable the breakpoint(s):

(gdb) enable
(gdb) continue
Continuing.

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

这篇关于如何使用自定义elf解释器来调试程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆