设置
- 从 CPAN 安装 Enbugger:
cpan install Enbugger
- 将以下内容添加到你的
.gdbinit
文件中:
define perl_eval
call (void*)Perl_eval_pv((void*)Perl_get_context(), $arg0, 0)
end
define perl_stop
perl_eval "Enbugger->stop"
continue
end
define perl_init
python import os
python gdb.execute("set $tty=\"" + os.ttyname(0) + "\"")
call open($tty, 0)
set $tty_in=$
call open($tty, 1)
set $tty_out=$
call (int) 'dup@plt'(0)
set $old_stdin=$
call (int) 'dup@plt'(1)
set $old_stdout=$
call (int) 'dup@plt'(2)
set $old_stderr=$
call (int) 'dup2@plt'($tty_in, 0)
call (int) 'dup2@plt'($tty_out, 1)
call (int) 'dup2@plt'($tty_out, 2)
eval "perl_eval \"$ENV{PERLDB_OPTS}='TTY=%s'\"", $tty
perl_eval "require Enbugger"
end
define attach_perl
attach $arg0
perl_init
perl_stop
end
基本上,perl_init
为 Perl 调试器设置了终端。如果标准输入/标准输出/标准错误流被调试进程重定向,你将无法在没有上述设置的情况下与 Perl 调试器进行交互。如果需要,你可以从备份描述符 $old_stdin/$old_stdout/$old_stderr 恢复旧的重定向。
连接到 Perl 进程
通过GDB根据PID附加到您的perl程序:
(gdb) attach_perl 640368
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007fd0b1313984 in __GI___select (nfds=0, readfds=0x0, writefds=0x0, exceptfds=0x0, timeout=0x7fff19c97240) at ../sysdeps/unix/sysv/linux/select.c:69
69 ../sysdeps/unix/sysv/linux/select.c: No such file or directory.
$1 = 7
$2 = 8
$3 = 9
$4 = 10
$5 = 11
$6 = 0
$7 = 1
$8 = 2
$9 = (void *) 0x562cae6a7810
$10 = (void *) 0x562cad300ee0
从perl5db.pl版本1.60加载DB例程
支持编辑器。
输入h或'h h'获取帮助,或键入'man perldebug'获取更多帮助。
$11 = (void *) 0x562cad6322d0
My::SafeProcess::(lib/My/SafeProcess.pm:543):
543: $millis++ if $millis < 1000;
DB<1>
有时您在第3步中可能无法获得提示符,因此可以按Ctrl+C并运行perl_stop
:
输入h或'h h'获取帮助,或键入'man perldebug'获取更多帮助。
$11 = (void *) 0x560577ff45a0
^C
Program received signal SIGINT, Interrupt.
0x00007fd8f9ee25a7 in __GI___wait4 (pid=626998, stat_loc=0x7fffbbeedf1c, options=0, usage=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
30 in ../sysdeps/unix/sysv/linux/wait4.c
(gdb) perl_stop
main::((eval 20)[/home/midenok/src/mariadb/10.4/build/opt/mysql-test/mysql-test-run:5]:1):
1: Enbugger->stop
DB<1>
只要加载了Enbugger,您随时可以通过perl_stop
从GDB进入perl调试器。
您可能只需要知道堆栈跟踪:
DB<1> T
@ = DB::DB called from file '(eval 39)[/usr/lib/x86_64-linux-gnu/perl-base/IO/Select.pm:130]' line 1
$ = eval 'Enbugger->stop' called from file '/usr/lib/x86_64-linux-gnu/perl-base/IO/Select.pm' line 130
@ = IO::Select::can_read(ref(IO::Select), 1) called from file '/home/midenok/src/mariadb/10.4/src/mysql-test/mysql-test-run.pl' line 594
@ = main::run_test_server(ref(IO::Socket::INET), ref(ARRAY), ref(HASH)) called from file '/home/midenok/src/mariadb/10.4/src/mysql-test/mysql-test-run.pl' line 485
. = main::main() called from file '/home/midenok/src/mariadb/10.4/src/mysql-test/mysql-test-run.pl' line 343
这里最新的执行点是Select.pm的第130行,请不要对注入的eval 'Enbugger->stop'
感到惊讶,但有时您会看到普通的堆栈跟踪。
从 Perl 进程分离
在perl调试器中运行"continue":
DB<1> c
[从子进程641324分离后]
[从子进程641326分离后]
[从子进程641328分离后]
[从子进程641329分离后]
按下Ctrl+C然后Ctrl+D:
^C
程序收到信号SIGINT,中断。
0x00007fd0b1313984 in __GI___select (nfds=0, readfds=0x0, writefds=0x0, exceptfds=0x0, timeout=0x7fff19c97240) at ../sysdeps/unix/sysv/linux/select.c:69
69 in ../sysdeps/unix/sysv/linux/select.c
(gdb) quit
从程序中分离:/usr/bin/perl,进程640368
[Inferior 1 (process 640368) detached]