使用PID通过GDB远程调试共享库(SO文件)

问题描述 投票:0回答:1

我有一台 Windows PC,连接到 LAN 中的 Linux 服务器。 Windows 运行 Windows 10 64 位,而 Linux 运行 Ubuntu 12.04 LTS (GNU/Linux 3.2.0-24-generic x86_64) CPU:Intel(R) Xeon(R) CPU E3-1505M v6 @ 3.00GHz。

我正在尝试调试一个用 C 编写的针对 Linux 服务器的 .so 文件。

我得到了访问我的 .so 文件的 PID 的进程,并使用此命令运行 gdbserver

gdbserver --attach :9999 <pid>

在使用 cygwin64 gdb 的 Windows PC 上,我使用

file
命令读取 .so 文件的本地副本,并使用
gdb target attach <linuxServerIp>:9999
连接到 gdbserver。

问题是我无法从 Windows 电脑远程添加断点。任何添加断点的命令都会导致访问内存失败。

(gdb) break my_func
Breakpoint 1 at 0x36a13: my_func. (2 locations)
(gdb) c
Continuing.
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x36a13

经过一些检查,我尝试运行

(gdb) print my_func
$1 = {int ()} 0x369ff <my_func>

然后我尝试在 Linux 服务器本地运行 gdb。我运行 print my_func 并检索到相同的地址

(gdb) print my_func
$1 = {int ()} 0x369ff <my_func>

然后我尝试使用附加 PID 连接到进程

(gdb) attach 28290
Attaching to process 28290

然后尝试打印

my_func
地址并添加断点。

(gdb) print my_func
$2 = false
(gdb) break my_func
Breakpoint 1 at 0x7fffe5b46a13: file src/myFlow/my_func.c, line 55.
(gdb) c
Continuing.

注意这里的地址与之前的不一样。 使用这个新内存,我能够逐行进行中断和检查。然后,我重新启动了 gdbserver,从 Windows 的 gdb 重新连接,并尝试在主机 PC 中使用此地址进行中断。现在可以正确破解了。

(gdb) break *0x7fffe5b46a13
Breakpoint 1 at 0x7fffe5b46a13

为什么我的SO文件在被外部进程加载后会改变函数地址?为什么 Linux PC 中的 gdb 在附加到 PID 时能够正确转换函数地址,而使用 GDBServer 连接的 Windows PC 中的 gdb 无法转换地址?

c debugging gdb shared-libraries gdbserver
1个回答
0
投票

经过更多阅读后,我发现 SO 文件的内存将根据使用它的进程进行加载。 SO 文件的地址正好是加载的 SO 文件的内存中的偏移量。

从这个网站

如果您正在调试共享对象库,请避免将 .so 文件指定为符号文件。使用 .so 作为符号文件,调试器将源位置解析为两个位置:一处解析为内存中的实际地址,另一处解析为 .so 文件内的文件地址,该地址不是有效的内存地址。因此,单步执行和其他调试操作无法正常工作。

因此作为解决方案,我们需要使用 add-symbol-file 命令在正确的地址加载 SO 文件: https://ftp.gnu.org/old-gnu/Manuals/gdb/html_chapter/gdb_14.html#:~:text=%20add%2Dsymbol%2Dfile%20命令,%20正在运行%20程序%20 .

添加符号文件 文件名 地址
添加符号文件 文件名 地址 [ -readnow ] [ -mapped ]
添加符号文件文件名-节地址
add-symbol-file 命令从文件 filename 中读取附加符号表信息。当 filename 已动态加载(通过其他方式)到正在运行的程序中时,您将使用此命令。地址应该是文件已加载的内存地址; GDB 自己无法解决这个问题。您还可以指定任意数量的“-ssection地址”对,以给出该节的显式节名称和基地址。您可以将任何地址指定为表达式。文件filename的符号表被添加到最初使用symbol-file命令读取的符号表中。您可以多次使用 add-symbol-file 命令;由此读取的新符号数据不断添加到旧符号数据中。要放弃所有旧符号数据,请使用不带任何参数的符号文件命令。如果使用后按 RET,add-symbol-file 不会重复。您可以像使用符号文件命令一样使用“-mapped”和“-readnow”选项来更改GDB管理文件名符号表信息的方式。

所以我需要使用

add-symbol-file <mySoFile> address
在正确的地址加载.so文件。

谢谢你,

© www.soinside.com 2019 - 2024. All rights reserved.