【WSL-DEBUG】修复WSL下GDB无法debug的错误(2022-12-23)
GDB 在 WSL 下 debug 时提示 :
warning: opening /proc/PID/mem file for lwp xxxxx.xxxxx failed: No such file or directory (2)
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x.......
错误发生的原因在于 WSL 中没有对 /proc/PID/mem 提供支持。
老版本的 GDB 在找不到 /proc/PID/mem 文件时,会转而使用 ptrace,而新版本的 GDB 则禁用了 ptrace,默认 /proc/PID/mem 是存在的。然而 WSL1 和 WSL2 中目前都没有这个文件。
解决方法:
修改 GDB 的二进制,让他支持 ptrace。
1. 打开 WSL,cd 到 gdb 的二进制路径,输入 explorer.exe . (不要漏掉后面的点)用windows的文件资源管理器打开当前目录,找到 gdb,将他复制粘贴到 windows 中的任意目录(不要放在 WSL 里)。
2. 用逆向工具 IDA 免费版( 官方下载地址:https://www.hex-rays.com/ida-free/ ) 打开刚刚粘贴出来的 gdb,打开方式默认即可。
3. 使用 " search for text " 查找 linux_proc_xfer_memory_partial

得到以下结果,看它的 function 地址:

看上面红框框出来的地方,我这里是 sub_30E3D0 (不同二进制不一样)。
4. 定位到上一步找到的 function 入口地址(.text:000000000030E3D0):

前面修改 rbp rsp 的那一坨不管他,直接看下图红框部分

导致 GDB 出错的是红框里的第二条指令,这是一个跳转指令,当 gdb 发现 mem 不存在,就从这里跳到错误处理点了。在这里,它的地址是 0x30E41D (记下来)

注意上图在不同二进制中可能不一样,比如某些指令出现顺序可能会不同,不用太在意,只需要找到 cmp esi 1 后面的那条跳转指令就好啦。同时注意对比一下上下的几条指令是不是都跟上图长得差不多,不要找错位置了(如果你在运行完第 5 步后发现地址不小心找错了,那需要重新安装 gdb,然后再次运行 5 中的命令)
5. 回到 WSL ,输入以下命令,注意用你的二进制中的跳转指令地址替换 0x30E41D
echo -ne '\x90\x90' | sudo dd of=/usr/bin/gdb seek=$((0x30E41D)) bs=1 count=2 conv=notrunc
,回车。
再次运行gdb:按序输入以下命令(这里用于测试 gdb 的二进制文件名为 ts)
gdb --> file ts --> b main --> run --> 让你下一个东西,选择 y(yes) --> 下载完成后,不出意外的话,gdb 正常工作。

上面提示让设置永久生效,可以将 set debuginfod enabled on 写进 .gdbinit
在 home 目录下 vim .gdbinit,把 "set debuginfod enabled on" 粘进去,保存退出,搞定。
参考文献:https://github.com/microsoft/WSL/issues/8356