5 Linux中的用户空间调试工具

时间:2020-03-05 15:30:06  来源:igfitidea点击:

根据定义,调试工具是那些程序,其中允许我们在执行时监视,控制和纠正其他程序中的错误。
我们为什么要使用调试工具?
要回答这一点,我们在运行一些程序时会陷入困境的各种情况,并且需要了解究竟发生了什么。
例如,我们可能正在运行应用程序,它会产生一些错误消息。
要修复这些错误,我们应该首先找出原因和错误消息来自其中。
应用程序可能会突然挂起,我们必须知道当时正在运行的其他进程。
我们也可能必须弄清楚在挂起时的过程'x'。
为了解剖这些细节,我们需要帮助调试工具。
Linux中有一些用户空间调试工具和技术在分析用户空间问题时非常有用。
他们是:

  • '打印'语句
  • 查询(/proc,/sys等)
  • 追踪(strace/ltrace)
  • Valgrind(Memwatch)
  • GDB.

1.'print'语句

这是调试问题的基本或者原始方式。
我们可以在程序的中间插入打印语句以了解控制流程并获取键变量的值。
虽然这是一种简单的技术,但它对它有一些缺点。
需要编辑程序以添加"打印"语句,然后必须重新编译并重新运行输出。
如果要调试的程序相当大,这是一种耗时的方法。

2.查询

在某些情况下,我们可能希望弄清楚运行进程在内核中的状态或者其占用的内存映射是什么样的。
为了获得此类信息,我们不需要将任何代码插入到其中核心。
相反,人们可以使用/proc文件系统。
/proc是一个伪文件系统,通过运行运行并运行一次运行时间系统信息(CPU信息,内存量等)。

'ls/proc'的输出

如我们所见,系统中运行的每个进程都以其进程ID的形式在/proc文件系统中具有条目。
可以通过查看其进程ID目录中存在的文件来获得有关这些进程中的每一个的详细信息

'ls/proc/pid'的输出

解释/proc文件系统内的所有条目超出了本文档的范围。
一些有用的有用的人如下所示:

/proc/cmdline - > kernel命令行

/proc/cpuinfo - >关于处理器的制作,型号等的信息

/proc/filesystems - >内核支持的文件系统信息

/proc //cmdline - >命令行参数传递给当前进程

/proc //mem - >内存由过程持有

/proc //状态 - >过程的状态

3.追踪

strace和ltrace是Linux中使用的两个跟踪程序执行详细信息的跟踪工具。

strace:

Scrace拦截和记录过程中的系统调用和由其接收的信号。
对于用户,它显示系统调用,传递给它们的参数和返回值。
scrace可以添加到已经运行或者新过程的过程中。
它是开发人员和系统管理员的诊断和调试工具。
它也可以用作理解系统如何通过跟踪不同的程序来了解系统的工具。
此工具的优势在于,不需要源代码,并且不需要重新编译程序。

使用strace的基本语法是:

scrace命令有各种可用的选项可用于strace命令。
一个可以查看SCRARIS工具的"手册"页面以获取更多详细信息。

strace的输出可能非常冗长,我们可能不会有兴趣通过每个显示的每一行。
我们可以使用"-e expr"选项来过滤不需要的数据。
使用'-p pid'选项将其添加到运行进程。

命令的输出可以使用"-o"选项重定向到文件

STRARIS滤波的输出仅是开放系统调用

LTRACE:

LTRACE轨道并记录流程(运行时)库调用和由其接收的信号。
它还可以跟踪在进程中进行的系统调用。
它的用法与strace类似

ltrace命令'-i'选项在库 调用时打印指令指针

'-s'选项用于显示两个系统调用和库调用

有关所有可用选项,请参阅LTRACE MAN页面。

LTRACE捕获"StrcMP"库调用的输出

4.Valgrind

Valgrind是一套调试和分析工具。
其中一个广泛使用的和默认工具是一个名为'memcheck'的内存检查工具,它拦截到malloc(),new(),free()和delete()所做的调用。
换句话说,它可以在检测以下问题:

  • 内存泄漏
  • 双重释放
  • 边界泛朗
  • 使用未初始化的内存
  • 在它被释放之后使用内存等

它直接与可执行文件一起工作。

Valgrind也有一些缺点。
它可以减慢程序,因为它会增加内存占用空间。
它有时可以产生误报和假阴性。
它无法检测到静态分配的数组的超出超出访问权限

为了使用它,首先下载它并在系统上安装它。
(Valgrind的下载页面)。

它可以使用用于一个人使用的操作系统的包管理器安装。

使用命令行的安装涉及解压缩和未下载的文件。

tar -xjvf valgring-x.y.z.tar.bz2 (其中x.y.z是我们尝试安装的版本号)

在新创建的目录(Valgrind-x.y.z)内部,运行以下命令:

./configure
make
make install

让我们使用小程序了解Valgrind如何工作(test.c):

#include <stdio.h>

void f(void)

{
int x = malloc(10 * sizeof(int));

x[10] = 0;
}

int main()
{
f();
return 0;
}

编译程序:

gcc -o test -g test.c

现在我们有一个名为'test'的可执行文件。
我们现在可以使用Valgrind来检查内存错误:

Valgrind -Tool = Memcheck -Leak-Check =是测试

以下是显示错误的Valgrind输出:

Valgrind的输出显示堆块溢出和内存泄漏

正如我们在上述消息中看到的那样,我们正在尝试访问超出在功能f中分配的区域,并且没有释放分配的内存。

5. GDB.

GDB是来自自由软件基金会的调试器。
它在定位和修复代码中的问题是有用的。
它给用户控制要调试的程序运行时执行各种操作,如:

  • 启动程序
  • 在指定的位置停止
  • 停止指定的条件
  • 检查必填信息
  • 对程序中的数据进行更改等。

人们还可以将崩溃的程序的核心转储添加到GDB并分析崩溃原因。

GDB为调试程序提供了大量选项。
但是,我们将在此处介绍一些重要的选择,以便可以获得如何使用GDB开始的感觉。

如果我们还没有安装GDB,则可以从GDB的官方下载。

编译计划:

为了使用GDB调试程序,必须使用GCC与"-G"选项进行编译。
这在操作系统的本机格式和GDB中生成调试信息与此信息一起工作。

这是一个简单的程序(example1.c)执行除以零以显示GDB的使用:

#include
int divide()
{
int x=5, y=0;
return x / y;
}

int main()
{
divide();
}

显示使用GDB的示例

调用GDB:

可以通过在命令行中执行"gdb"来启动GDB

一旦调用,它仍然存在从终端的命令等待并执行它们直到退出。
如果一个进程已经运行并且需要将gdb添加到它,可以通过指定进程ID来完成,假设程序已经崩溃,并且一个人想要分析问题的原因,然后将GDB添加到核心文件有帮助。

启动程序:

在GDB内部,使用"运行"命令启动要调试的程序

将参数传递给程序:

使用"SET ARGS"命令将参数发送到程序下次运行下次"show args"将显示传递给程序的参数

验证堆栈:

每当程序停止时,任何人想要理解的首先是它为什么停止以及它如何停止。
此信息称为回溯。
由程序生成的每个函数调用都与本地变量一起存储,在堆栈内的数据块中传递,调用位置等的参数,并称为帧。
使用GDB我们可以检查所有这些数据。
GDB通过从最内帧开始,通过给予它们的数字来识别这些帧。

BT:打印整个堆栈BT <n>的回溯打印N帧框架的倒退<帧编号>:切换到指定的帧并打印框架<n>:移动'n'框架向上<n>:移动'n'框架。
(n默认为1)

检查数据:

可以使用"print"命令在GDB内部检查程序的数据。
例如,如果'x'是调试程序内的变量,则'打印x'打印x的值。

检查来源:

可以在GDB中打印源文件的一部分。
"列表"命令默认打印10行代码。

列表<linenum>:列出"Linenum"列表<函数>若要源文件<函数>:从"函数"的开头列出源

Disas <函数>:显示功能的机器代码

停止并恢复程序:

使用GDB,我们可以设置断点,观察点等,以便在必需的情况下停止程序。

break <location>:在"位置"中设置一个断点。
当程序执行时,当该程序进行时,对用户提供控制。
观看<expr>:GDB停止当程序写入"expr"时,它的值更改捕获<event>:GDB在发生"事件"时停止。
禁用<断点>:禁用指定的断点启用<basspoint>:启用指定的断点删除<basterpoint>:如果未通过参数,则删除传递的断点/观察点/捕获点,如果未通过默认操作,则要在所有断点上工作

步骤:按步骤执行程序继续:继续进行程序执行,直到执行完成

退出GDB:

使用"quit"命令退出GDB,GDB有许多可用的选项。
有关更多详细信息,请在GDB内部使用帮助选项。