gdb即使使用-no-pie编译也无法插入断点
gdb fails to insert a breakpoint even if compiled with -no-pie
我正试图让gdb在Ubuntu 20.04上使用C++程序。我需要的是能够设置一个断点(例如,break main.cpp:3
gdb命令(,然后设置run
直到断点,但此时start
和run
都失败了,因为它们";无法插入断点"以及";无法访问内存";。对我来说,gdb即使有非常简单的例子也会失败。这是main.cpp的内容:
#include <iostream>
int main() {
std::cout << "Hello World!";
return 0;
}
我在某个地方发现,使用-no-pie
可能有助于让gdb工作(带断点(,所以我通过运行g++ -ggdb3 -no-pie -o main main.cpp
来编译程序(我还尝试了-g
而不是-ggdb3
,以及-fno-PIE
而不是-no-pie
(。当我尝试使用gdb时,它会抱怨"无法插入断点1":
gdb -q main
Reading symbols from main...
(gdb) start
Temporary breakpoint 1 at 0x1189: file main.cpp, line 3.
Starting program: /tmp/main
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x1189
没有CCD_ 11的结果是一样的无论有没有-no-pie
,唯一改变的是十六进制地址,没有-no-pie,它的低位像0x1189(如上所示(,有-no-pies,它可以是0x401176,但其他一切都完全一样,我一直得到";无法访问地址"处的存储器;在这两种情况下都发出警告
如果我使用starti
而不是start
,它一开始是有效的,但经过几次nexti
迭代后,它会打印出通常的消息";无法插入断点":
gdb -q main
Reading symbols from main...
(gdb) starti
Starting program: /tmp/main
Program stopped.
0x00007ffff7fd0100 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) nexti
0x00007ffff7fd0103 in ?? () from /lib64/ld-linux-x86-64.so.2
...
(gdb) nexti
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x4
0x00007ffff7fd0119 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) nexti
0x00007ffff7fd011c in ?? () from /lib64/ld-linux-x86-64.so.2
...
(gdb) nexti
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x1c
0x000055555556ca22 in ?? ()
(gdb) nexti
[Detaching after fork from child process 3829827]
...
[Detaching after fork from child process 3829840]
Hello World![Inferior 1 (process 3819010) exited normally]
所以我可以使用nexti
,但不能使用next
,而且显然不能插入断点。
我尝试了-Wl,-no-pie
(通过运行g++ -Wl,-no-pie -ggdb3 -o main main.cpp
;添加-no-pie
不会更改任何内容(,但此选项会导致一个奇怪的链接器错误:
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
当我搜索错误时,我只找到了尝试-no-pie
而不是-Wl,-no-pie
的建议,没有其他解决方案。由于调试C++程序是一项非常常见的活动,我觉得我错过了一些显而易见的东西,但到目前为止我还没有找到解决方案。
为了更容易理解我使用的确切命令,并明确我没有混淆目录,并显示我使用的g++和gdb的版本,这里是完整的终端日志:
$ ls
main.cpp
$ g++ --version | grep Ubuntu
g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0
$ g++ -ggdb3 -no-pie -o main main.cpp
$ ls
main main.cpp
$ gdb --version | grep Ubuntu
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
$ readelf -h main | grep 'Type: .*EXEC'
Type: EXEC (Executable file)
$ gdb -q main
Reading symbols from main...
(gdb) start
Temporary breakpoint 1 at 0x401176: file main.cpp, line 3.
Starting program: /tmp/main/main
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x401176
为了完整性,我在没有-no-pie
:的情况下尝试了同样的操作
$ rm main
$ g++ -ggdb3 -o main main.cpp
$ readelf -h main | grep 'Type: .*'
Type: DYN (Shared object file)
$ gdb -q main
Reading symbols from main...
(gdb) start
Temporary breakpoint 1 at 0x1189: file main.cpp, line 3.
Starting program: /tmp/main/main
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x1189
正如您所看到的,使用或不使用-no-pie
的唯一区别是内存地址,但问题和警告是相同的。如果没有-no-pie
,这可能是意料之中的事,但我不明白如果我使用-no-pie
编译,为什么会发生这种情况,以及我还能尝试解决什么问题
这:
g++ -ggdb3 -no-pie -o main main.cpp
应生成非PIE可执行文件。您应该能够通过查看readelf -h main | grep 'Type: .*EXEC'
(PIE二进制文件具有ET_DYN
类型(来验证它是否为PIE。
此:
Temporary breakpoint 1 at 0x1189: file main.cpp, line 3.
明确地是一个PIE二进制文件(在x86_64
Linux上,非PIE二进制程序不会有低于0x40000
的任何代码(。
结论:您正在调试错误的二进制文件(例如,您在与正在调试的目录不同的目录中编译main
(,或您没有说明全部情况。
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 预处理器:插入结构名称中的前一个行号
- 在未初始化映射的情况下,将值插入到映射的映射中
- 如何在c++中只将键插入到bimap的一侧
- 如何将结构插入到集合中并打印集合的成员
- C++json插入数组
- Visual Studio 2019:插入多个C++风格的单行注释
- nlohmann-json将一个数组插入到另一个数组中
- 有效地使用std::unordered_map来插入或增加键的值
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- 正在插入动态数组
- 插入或删除时获取usb的dos_name
- 无法删除指针,已触发断点
- 条件断点在不应该触发时触发
- 叮叮当当在修复时插入多个"覆盖"说明符
- 如何在Visual Studio 2013 Ultimate Edition中包含某个单词的每一行中插入断点
- 如何在执行 gdb 时插入断点
- GDB 无法插入内部断点
- 在Visual Studio中调试:断点移动并插入新行