【发布时间】:2019-08-12 05:19:48
【问题描述】:
重现步骤:
- 克隆 emacs 存储库
git clone https://github.com/emacs-mirror/emacs.git
- 运行样板程序以准备构建/创建 Makefile
i@user:~/emacs$ ./autogen.sh; ./configure
- 导航到目录
lib-src/以构建etags二进制文件cd lib-src/
-
通过编辑
lib-src/目录中的Makfile,确保我编译的etags二进制文件具有最多的调试符号和尽可能少的优化CC=gccCFLAGS=-fno-eliminate-unused-debug-types -g3 -O0CPPFLAGS =LDFLAGS =
-
构建
etags二进制目标make tags
- 只需在
gdb中使用如下参数进行简单的测试运行,即可测试在调试时不会跳过任何代码:etags --help
gdb etags
(gdb) b main
Breakpoint 1 at 0x37ca: file etags.c, line 1071.
(gdb) r
Starting program: /home/i/emacs/lib-src/etags
Breakpoint 1, main (argc=1, argv=0x7fffffffdfb8) at etags.c:1071
1071 {
(gdb) n
1078 bool help_asked = false;
(gdb) n
1083 progname = argv[0];
(gdb) n
1084 nincluded_files = 0;
(gdb) n
1085 included_files = xnew (argc, char *);
(gdb)
如您所见,gdb 跳过了对应于以下代码的第 1072-1077 行:
// ...
// ...
// ...
int // Line 1069
main (int argc, char **argv) // Line 1070
{ // Line 1071
int i; // Line 1072
unsigned int nincluded_files; // Line 1073
char **included_files; // Line 1074
argument *argbuffer; // Line 1075
int current_arg, file_count; // Line 1076
linebuffer filename_lb; // Line 1077
bool help_asked = false; // Line 1078
ptrdiff_t len; // Line 1079
char *optstring; // Line 1080
int opt; // Line 1081
// ...
// ...
// ...
我错过了什么吗?我是否应该添加一个标志以确保在生成调试符号时不会跳过任何代码行?
【问题讨论】:
-
要真正理解这一点,您需要查看汇编代码。您会发现有一个函数序言为所有变量分配了足够的堆栈空间(通常通过从堆栈指针中减去预先计算的值)。所以对于像 1072 这样的行没有任何代码。
i的内存在函数序言中分配,以及所有其他变量的内存(第 73 到 77 行和 79 到 81 行)。第 78 行是唯一实际做某事的行(除了声明一个变量)。