前言

GDB(GNU Debugger)是UNIX及UNIX-like下的强大调试工具,可以调试ada, c, c++, asm, minimal, d, fortran, objective-c, go, java,pascal等语言。本文以C程序为例,介绍GDB启动调试的多种方式。

哪类程序可被调试

对于C程序来说,需要在编译时加上-g参数,保留调试信息,否则不能使用GDB进行调试。
但如果不是自己编译的程序,并不知道是否带有-g参数,如何判断一个文件是否带有调试信息呢?

gdb 文件

例如:

$ gdb helloworld
Reading symbols from helloWorld...(no debugging symbols found)...done.

如果没有调试信息,会提示no debugging symbols found。
如果是下面的提示:

Reading symbols from helloWorld...done.

则可以进行调试。

readelf查看段信息

例如:

$ readelf -S helloWorld|grep debug
  [28] .debug_aranges    PROGBITS         0000000000000000  0000106d
  [29] .debug_info       PROGBITS         0000000000000000  0000109d
  [30] .debug_abbrev     PROGBITS         0000000000000000  0000115b
  [31] .debug_line       PROGBITS         0000000000000000  000011b9
  [32] .debug_str        PROGBITS         0000000000000000  000011fc

helloWorld为文件名,如果没有任何debug信息,则不能被调试。

file查看strip状况

下面的情况也是不可调试的:

file helloWorld
helloWorld: (省略前面内容) stripped

如果最后是stripped,则说明该文件的符号表信息和调试信息已被去除,不能使用gdb调试。但是not stripped的情况并不能说明能够被调试。

调试方式运行程序

程序还未启动时,可有多种方式启动调试。

调试启动无参程序

例如:

$ gdb helloWorld
(gdb)

输入run命令,即可运行程序

调试启动带参程序

假设有以下程序,启动时需要带参数:

#include<stdio.h>
int main(int argc,char *argv[])
{
    if(1 >= argc)
    {
        printf("usage:hello name\n");
        return 0;
    }
    printf("Hello World %s!\n",argv[1]);
    return 0 ;
}

编译:

gcc -g -o hello hello.c

这种情况如何启动调试呢?需要设置参数:

$ gdb hello
(gdb)run 编程珠玑
Starting program: /home/shouwang/workspaces/c/hello 编程珠玑
Hello World 编程珠玑!
[Inferior 1 (process 20084) exited normally]
(gdb)

只需要run的时候带上参数即可。
或者使用set args,然后在用run启动:

gdb hello
(gdb) set args 编程珠玑
(gdb) run
Starting program: /home/hyb/workspaces/c/hello 编程珠玑
Hello World 编程珠玑!
[Inferior 1 (process 20201) exited normally]
(gdb) 

调试core文件

当程序core dump时,可能会产生core文件,它能够很大程序帮助我们定位问题。但前提是系统没有限制core文件的产生。可以使用命令limit -c查看:

$ ulimit -c
0

如果结果是0,那么恭喜你,即便程序core dump了也不会有core文件留下。我们需要让core文件能够产生:

ulimit -c unlimied  #表示不限制core文件大小
ulimit -c 10        #设置最大大小,单位为块,一块默认为512字节

上面两种方式可选其一。第一种无限制,第二种指定最大产生的大小。
调试core文件也很简单:

gdb 程序文件名 core文件名

具体可参看《linux常用命令-开发调试篇》gdb部分。

调试已运行程序

如果程序已经运行了怎么办呢?
首先使用ps命令找到进程id:

ps -ef|grep 进程名

attach方式

假设获取到进程id为20829,则可用下面的方式调试进程:

$ gdb
(gdb) attach 20829

接下来就可以继续你的调试啦。

可能会有下面的错误提示:

Could not attach to process.  If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user.  For more details, see /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted.

解决方法,切换到root用户:
将/etc/sysctl.d/10-ptrace.conf中的

kernel.yama.ptrace_scope = 1

修改为

kernel.yama.ptrace_scope = 0

直接调试相关id进程

还可以是用这样的方式gdb program pid,例如:

gdb hello 20829  

或者:

gdb hello --pid 20829

已运行程序没有调试信息

为了节省磁盘空间,已经运行的程序通常没有调试信息。但如果又不能停止当前程序重新启动调试,那怎么办呢?还有办法,那就是同样的代码,再编译出一个带调试信息的版本。然后使用和前面提到的方式操作。对于attach方式,在attach之前,使用file命令即可:

$ gdb
(gdb) file hello
Reading symbols from hello...done.
(gdb)attach 20829

总结

本文主要介绍了两种类型的GDB启动调试方式,分别是调试未运行的程序和已经运行的程序。对于什么样的程序能够进行调试也进行了简单说明。

欢迎留言补充。

微信公众号【编程珠玑】:专注但不限于分享计算机编程基础,Linux,C语言,C++,算法,数据库等编程相关[原创]技术文章,号内包含大量经典电子书和视频学习资源。欢迎一起交流学习,一起修炼计算机“内功”,知其然,更知其所以然。

GDB调试指南-启动调试的更多相关文章

  1. GDB调试指南-单步调试

    前言 前面通过<启动调试>,<断点设置>,<变量查看>,我们已经了解了GDB基本的启动,设置断点,查看变量等,如果这些内容你还不知道,建议先回顾一下前面的内容.在启 ...

  2. [原创]GDB调试指南-断点设置

    前言 上篇<GDB调试指南-启动调试>我们讲到了GDB启动调试的多种方式,分别应用于多种场景.今天我们来介绍一下断点设置的多种方式. 为何要设置断点 在介绍之前,我们首先需要了解,为什么需 ...

  3. GDB调试指南-变量查看

    前言 在启动调试以及设置断点之后,就到了我们非常关键的一步-查看变量.GDB调试最大的目的之一就是走查代码,查看运行结果是否符合预期.既然如此,我们就不得不了解一些查看各种类型变量的方法,以帮助我们进 ...

  4. GDB 调试指南

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复 「1024」 即可领取,欢迎大家关注,二维码文末可以扫. 00 介绍 ...

  5. 用qemu+gdb tcp server+CDT调试linux内核启动-起步

    用qemu+gdb tcp server+CDT调试linux内核启动-起步 说明: 环境信息与 用virtualbox+模拟串口+CDT调试linux内核 TCP IP协议栈-起步 提到的一样,并且 ...

  6. linux内核调试指南

    linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级调试 ***第一部分:基础知识*** 总纲:内核世界的陷阱 源码阅读的陷阱 代码调试的陷阱 原理理解的陷阱 ...

  7. Linux Kernel - Debug Guide (Linux内核调试指南 )

    http://blog.csdn.net/blizmax6/article/details/6747601 linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级 ...

  8. 【原创】LoadRunner Java Vuser脚本的配置和调试指南

    1 编写目的 本文介绍了Loadrunner多负载压力机的配置,并通过测试Java Vuser的数据库连接脚本对配置结果进行了验证,同时对配置过程中遇到的问题和解决的过程进行了记录,关于Java数据库 ...

  9. GDB:从单线程调试到多线程调试(MFiX单步调试)

    GDB:从单线程调试到多线程调试 1. 裸跑GDB 1.1 安装GDB sudo apt-get install gdb 1.2 编译程序 由于需要调试,因此编译的时候需要添加-g编译参数: 1.3 ...

随机推荐

  1. .NET Core protobuf-net、MessagePack、Json.NET序列化/反序列化性能测试

    测试代码Zonciu/SerializationTest.cs, 源自neuecc/ZeroFormatterBenchmark.cs. NuGet包及其版本 mgravell/protobuf-ne ...

  2. .net core使用Pipelines进行消息IO合并

    之前的文章讲述过通过IO合并实现百万级RPS和千万级消息推送,但这两篇文章只是简单地讲了一下原理和测试结果并没有在代码实现上的讲解,这一编文章主要通过代码的实现来讲述消息IO合并的原理.其实在早期的版 ...

  3. Chapter 5 Blood Type——11

    "I just wondered… if you could warn me beforehand the next time you decide to ignore me for my ...

  4. git版本控制工具的使用

    目录 git版本管理工具使用 一丶Git的下载与安装 1.windows下的git的下载与安装 2.linux下的git安装 二丶常用命令 三丶Git仓库 1.配置仓库信息 2.仓库的创建于管理 四丶 ...

  5. .Net Core SDK 命令介绍

    前言 本篇主要介绍 asp.net core 中,使用 dotnet tools 运行 dotnet run 之后的系统执行过程. 如果你觉得对你有帮助的话,不妨点个[推荐]. 目录 dotnet r ...

  6. c#调用com组件,程序 发生意外<hr=0x80020009>

    引用dll,确认dll没有问题,版本正确,可是一直报发生意外,没有任何其他提示. 解决方案: 看dll引用选项配置 复制到本地:设为true,我的就是false; 嵌入互操作类型:false,如果是t ...

  7. Mysql启动时执行文件init-file的使用

    可以在配置文件里指定mysql启动以后初始执行的SQL文件, 其语法是: 在[mysqld]下指定: init-file="D:/mysql/test.sql",  后面为具体的s ...

  8. Java开发笔记(五十二)对象的类型检查

    前面介绍了类的多态性,来自于鸡类的实例chicken,既能用来表达公鸡实例,也能用来表达母鸡实例.可是这导致了一个问题,假如在call方法内部需要手工判断输入参数属于公鸡实例还是母鸡实例,那该如何是好 ...

  9. jQuery 嵌套 event 会触发多次的原因

    Html代码如下: <div id="cover"> <input type="button" id="inside" v ...

  10. js中数组的map()方法

    map()方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值 map()方法按照原是数组顺序以此处理元素 注意:map()不会对空数组进行检测 :不会改变原始的数组 实例: var nu ...