为什么GDB" step"进入标准库调用的机器语言?

时间:2017-11-09 14:35:06

标签: c gdb

在我的一些系统上,当我调试非常简单的代码时,GDB的行为与我预期的不同。在某些系统上,当我进入'步骤时,gdb"掩盖"标准库调用;在其他系统上,' step'下载到每个库调用的机器语言。

首先,我从GDB习惯的行为示例:

$ gdb ./testapp
GNU gdb (GDB) CentOS (7.0.1-45.el5.centos)
(...)
(gdb) break main
Breakpoint 1 at 0x80483b6: file testapp.c, line 6.
(gdb) run
Starting program: ./testapp

Breakpoint 1, main () at testapp.c:6
6               char str[] = {"Test string"};
(gdb) step
8               printf("String: %s\n", str );
(gdb)
String: Test string
9               printf("Len: %zu\n", strlen( str ));
(gdb)
Len: 11
10              return 0;
(gdb)

这是GDB逐步进入printf()到机器语言步骤的一个例子。

$ gdb ./testapp
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
(...)
(gdb) break main
Breakpoint 1 at 0x40050c: file testapp.c, line 6.
(gdb) run
Starting program: ./testapp

Breakpoint 1, main () at testapp.c:6
6               char str[] = {"Test string"};
(gdb) step
8               printf("String: %s\n", str );
(gdb)
__printf (format=0x400668 "String: %s\n") at printf.c:30
30      {
(gdb)
34        va_start (arg, format);
(gdb)
35        done = vfprintf (stdout, format, arg);
(gdb)
_IO_vfprintf_internal (s=0x383958f040, format=0x400668 "String: %s\n", ap=0x7fffffffe330) at vfprintf.c:236
236       int save_errno = errno;
(gdb)
201     {
(gdb)
236       int save_errno = errno;
(gdb)
1283      ORIENT;
(gdb)
1287      ARGCHECK (s, format);
(gdb)
1298      if (UNBUFFERED_P (s))
(gdb)
1309      __va_copy (ap_save, ap);
(gdb)
1320      f = lead_str_end = __find_specmb ((const UCHAR_T *) format);
(gdb)
__find_specmb (s=0x383958f040, format=0x400668 "String: %s\n", ap=0x7fffffffe330) at printf-parse.h:109
109       return (const unsigned char *) __strchrnul ((const char *) format, '%');
(gdb)
_IO_vfprintf_internal (s=0x383958f040, format=0x400668 "String: %s\n", ap=0x7fffffffe330) at vfprintf.c:1309
1309      __va_copy (ap_save, ap);
(gdb)
1320      f = lead_str_end = __find_specmb ((const UCHAR_T *) format);
(gdb)
__find_specmb (s=0x383958f040, format=0x400668 "String: %s\n", ap=0x7fffffffe330) at printf-parse.h:109
109       return (const unsigned char *) __strchrnul ((const char *) format, '%');
(gdb)
strchrnul () at ../sysdeps/x86_64/strchrnul.S:27
27              movd    %esi, %xmm1
(gdb)
28              movq    %rdi, %rcx
(gdb)
29              punpcklbw %xmm1, %xmm1
(gdb)

以下是" testapp.c"的来源:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(){
        char str[] = {"Test string"};

        printf("String: %s\n", str );
        printf("Len: %zu\n", strlen( str ));
        return 0;
}

该程序在两种环境中编译如下:

cc -g -o testapp testapp.c

这是我关于Stack Overflow的第一个问题!任何帮助将不胜感激!谢谢!

3 个答案:

答案 0 :(得分:3)

你没有看到&#34;机器语言&#34;。你看到了图书馆的源代码。

在某些机器上,库显然安装了调试信息和源代码。做一个&#34;步骤&#34;在那台机器上将进入程序。在另一台机器上,库显然没有安装调试信息,所以&#34;步骤&#34;命令步骤。

注意:&#34;步骤&#34;在所有情况下,命令都应该进入库。如果没有源代码,您应该看到(真实的)机器语言。似乎gdb没有这样做(VS确实如此)。

答案 1 :(得分:1)

约翰对原始帖子的评论将其钉住了。

我发现正在进入库的机器安装了两个调试包:glibc-debuginfoglibc-debuginfo-common

使用yum remove glibc-debuginfo glibc-debuginfo-common删除它们之后,GDB现在按照我预期的方式工作!

非常感谢,约翰!

答案 2 :(得分:0)

您似乎对gdb的“步骤”和“下一步”命令有误解。

'step'尝试执行到执行路径中的下一行代码(其全名是'step into'。

'next'尝试执行当前行之后的代码行。 (它不会停留在被调用的函数中。