我正在使用Linux并尝试进行远程调试程序。
我从.xinitrc启动gdbserver到目标上,命令如下:
gdbserver localhost:9134 /root/game/game
我在我的本地电脑上,使用虚拟机中运行的方式,通过以下命令从gdb连接到目标:
target remote 192.168.1.20:9134
它能够成功连接。我可以在 main 函数处设置断点。
b main
然后我可以继续操作,但程序会在那里中断。我可以单步执行一段时间,直到调用SDL_Init(),此时它将永远不会返回到gdb。 如果我不单步执行到SDL_Init而是设置一个进程更深的断点,程序将启动并正常运行(所以它能够通过SDL_Init)。但当它到达断点时,它会在目标机器上冻结,我的本地机器上的gdb从未显示提示。整个过程都挂起了,并且必须重新启动。但它并没有完全冻结,因为目标上的鼠标指针仍然移动,您可以对其进行ping测试,但gdb连接不再起作用。因此,似乎图形系统会在某种程度上干扰此过程,因为在图形系统初始化之前的断点确实有效,但在之后就无法使用了。
我尝试将remotetimeout设置为500秒,并出现了相同的行为。当我从本地计算机ping远程目标时,报告的时间约为0.3至0.4毫秒。因此,这似乎并不寻常,但我不能排除任何其他配置有误的网络设置。
这是一个遗留系统(但是,嘿,它仍然赚钱),具有gdbserver版本6.8-19.fc10和gdb版本6.8-29.fc10。升级版本可能是可能的,但可能不必要(我对我的计算机进行的任何升级都必须对州监管机构的系统进行升级,因为他们使用gdb设置进行测试,在此过程中需要升级)。远程调试在我接手之前曾经工作过,之前参与其中的任何人都已离职。gdbserver版本肯定有效,因为我正在使用以前使用的确切程序。
更新1:
我将主机上的gdb版本更新到了7.0.1版本,它仍然表现出相同的行为。我不能使用版本8,因为它需要C++11编译器,而这个遗留系统是在那个时期之前。
更新2:
我在另一个虚拟机中尝试了这个,并且甚至构建了一个全新的专用Linux安装(因此没有虚拟机),重建了软件,但我得到了相同的行为。因此,问题似乎可能在目标机器的配置上。
更新3:
我找到了一个串行电缆,并最终通过串行获得了远程调试设置。它仍然无法正常工作,但它给了我更多的错误消息。我收到了错误信息。
gdbserver: error initializing thread_db library: version mismatch between libthread_db and libpthread
我认为这是有道理的,因为在图形系统初始化后(涉及创建一些线程),我的断点无法工作。通过搜索该错误,我尝试使用set solib-absolute-prefix
、set solib-search-path
和set sysroot
将这些变量设置为主机上目标机器文件系统副本的根目录(即在主机上,/fw_dev/fgs/cf/initrd/expand包含initrd所制造的文件系统)。
但是,当我试图设置断点时,我得到了Error accessing memory address 0xb5eb60: Input/output error.
我还尝试将这些变量设置为lib子目录,但也不起作用。我还尝试仅从主机的/lib
目录复制本地线程库到目标的/lib
,但此时x窗口甚至无法启动。
更新#4:
我尝试从主机上的目标文件系统副本的根目录(/fw_dev/fgs/cf/initrd/expand)启动gdb,gdb仍然挂在断点上,但不再收到关于libthread_db和libpthread不匹配的错误消息,所以又回到了原点。
更新#5:
也许我已经到了应该单独提问的地步,但我编译了gdb,然后在其本身上运行了gbd。然后使用file
将它设置为主机上的程序,在远程目标上设置断点,然后运行continue
。当我到达断点时,gdb总是挂起。但现在当我在gdb中按下ctrl-c时,我得到这个回溯。
#0 0x00110416 in __kernel_vsyscall ()
#1 0x00b3f39d in ___newselect_nocancel () from /lib/libc.so.6
#2 0x08203b9a in ser_base_wait_for (scb=0x96a2930, timeout=1) at ser-base.c:206
#3 0x08203c89 in do_ser_base_readchar (scb=0x96a2930, timeout=-1) at ser-base.c:256
#4 0x08204046 in generic_readchar (scb=0x96a2930, timeout=-1, do_readchar=0x8203c60 <do_ser_base_readchar>) at ser-base.c:326
#5 0x082040b0 in ser_base_readchar (scb=0x96a2930, timeout=-1) at ser-base.c:391
#6 0x081ecac2 in serial_readchar (scb=0x96a2930, timeout=-1) at serial.c:376
#7 0x080c4357 in readchar (timeout=<value optimized out>) at remote.c:5922
#8 0x080c5e35 in getpkt_or_notif_sane_1 (buf=0x839f140, sizeof_buf=0x839f144, forever=1, expecting_notif=0) at remote.c:6440
#9 0x080d1e0a in getpkt_sane (ops=0x839f180, ptid=..., status=0xbffff388, options=0) at remote.c:6534
#10 remote_wait_as (ops=0x839f180, ptid=..., status=0xbffff388, options=0) at remote.c:4736
#11 remote_wait (ops=0x839f180, ptid=..., status=0xbffff388, options=0) at remote.c:4843
#12 0x08184d4b in target_wait (ptid=..., status=0xbffff388, options=0) at target.c:2098
#13 0x0815daf2 in wait_for_inferior (treat_exec_as_sigtrap=0) at infrun.c:2028
#14 0x0815ddd4 in proceed (addr=4294967295, siggnal=TARGET_SIGNAL_DEFAULT, step=0) at infrun.c:1652
#15 0x08153729 in continue_1 (all_threads=0) at infcmd.c:668
#16 0x08153ea2 in continue_command (args=0x0, from_tty=0) at infcmd.c:760
#17 0x0808e9e8 in execute_command (p=0x83b89a1 "", from_tty=0) at top.c:453
#18 0x0816b028 in command_handler (command=0x83b89a0 "c") at event-top.c:511
#19 0x0816bd5a in command_line_handler (rl=0x8ce83e8 "\340&\266\b\340\230\321\b") at event-top.c:736
#20 0x0822d5a5 in rl_callback_read_char () at callback.c:205
#21 0x0816b17b in rl_callback_read_char_wrapper (client_data=0x0) at event-top.c:178
#22 0x0816ac54 in handle_file_event (data=...) at event-loop.c:812
#23 0x08169e6b in process_event () at event-loop.c:394
#24 0x0816aba4 in gdb_do_one_event (data=0x0) at event-loop.c:459
#25 0x0816500b in catch_errors (func=0x816a950 <gdb_do_one_event>, func_args=0x0, errstring=0x82ccc3d "", mask=6) at exceptions.c:510
#26 0x080f072a in tui_command_loop (data=0x0) at ./tui/tui-interp.c:153
#27 0x08165684 in current_interp_command_loop () at interps.c:291
#28 0x0808653b in captured_command_loop (data=0x0) at ./main.c:226
#29 0x0816500b in catch_errors (func=0x8086530 <captured_command_loop>, func_args=0x0, errstring=0x82ccc3d "", mask=6) at exceptions.c:510
#30 0x08085ecc in captured_main (data=0xbffff7a4) at ./main.c:902
#31 0x0816500b in catch_errors (func=0x80853d0 <captured_main>, func_args=0xbffff7a4, errstring=0x82ccc3d "", mask=6) at exceptions.c:510
#32 0x080851d1 in gdb_main (args=0xbffff7a4) at ./main.c:911
#33 0x08085195 in main (argc=128, argv=0x0) at gdb.c:33
看起来gdb卡在__kernel_vsyscall()里了。在主机的/lib目录和目标机器上的libc.so.6上进行diff后发现不同之处。我试过使用LD_PRELOAD和LD_LIBRARY_PATH,但是backtrace总是显示/lib/libc.so.6,而不是指向目标机器上的拷贝。也许我没有正确设置它们,但我已经尝试在gdb中用set env设置它们,也尝试在命令行上设置并导出它们,但都无济于事。我还尝试将主机计算机的libc放到目标机器上,但它甚至无法启动,它在libc中得到segfault。
那么我该如何让gdb加载不同的库呢?
更新#6:
所以我用目标系统的磁盘映像作为基础制作了一个可启动的USB键。我对它进行了最少的更改,使其在标准PC上运行,并添加了gdb和gdb所需的库。所以现在,主机和目标机器上的libc是相同的,但它仍然卡住了我。
最终结果:虽然我知道gdb 6.8过去可以工作,但我无法找出配置。在升级了所有gdb和gdbserver到7.12之后,它终于可以工作了。
dmesg
有什么有趣的信息吗?此外,系统有多少 RAM? - oxr463