使用gdb调试core文件和breakpad的简单使用

news2024/11/20 11:32:47

1 core文件的配置

默认情况下,如果程序崩溃了是不会生成core文件的,因为生成core文件受到系统ulimit配置的影响。

ulimit -c是core文件的大小,默认为0,因此,就不会生成core文件,因此,为了能够生成core文件,可以使用ulimit -c filesize命令使得程序在崩溃时能够生成core文件。

默认情况下,会在崩溃的程序所在的路径下生成core文件,当然也可以通过修改/proc/sys/kernel/core-pattern将core文件放到某个路径下。

2 gdb查看堆栈

当有了core文件后,就可以用gdb查看core文件,得到core的堆栈信息。

gdb binary core.11111

binary就是执行时崩溃的二进制程序,core.11111就是崩溃时产生的core文件。

然后执行bt命令就可以查看程序崩溃时的堆栈,并定位到具体崩溃的业务代码。

3 breakpoint & watchpoint

在使用gdb进行调试时,通常需要使用断点,即breakpoint,在使用gdb运行程序时,可以执行以下命令增加断点:

b func_name

然后使用info b就可以查看断点信息,注意,如果程序需要加载其他的so,此时还拿不到so中的符号信息,gdb会提示:Make breakpoint pending on future shared library load?

使用breakpoint可以让程序运行到某个地方暂停,然后查看此时的变量或者内存的情况,但是,有时候,某个变量由于某个bug导致变成了非预期的值,就可以使用watchpoint对变量进行监控,当变量的值变化时程序就会暂停。

如果需要对变量进行监控,那gdb肯定是需要有该变量的信息,监控变量相当于监控某块内存空间,是需要程序启动才能添加watchpoint的,可以在程序最开始打breakpoint,当程序暂停时再打watchpoint:

w variable_name
3.1 breakpoint

通过break命令添加断点时,有三种方式可以指定断点所在的地方:

  • 指定函数名或者类的方法名,例如,某个文件中的函数是Person:Eat(),那么可以使用b Person:Eat在这个函数的入口处加断点
  • 指定所在的文件以及行号,例如,某个源文件person.cpp的100行,那么可以使用b person.cpp:100在这里加断点,唯一需要注意的是文件名是用全路径还是相对路径,如果不好确定,可以先用函数名的方式加断点,然后运行,当程序暂停时,gdb会打印暂停的文件名和行号,文件名可以从这里取

除了常规的断点,还有两种特殊的断点:

  • 临时断点:tbreak ,只会在这里停止一次,之后断点自动删除
  • 条件断点:break if ,当条件满足时停止

临时断点和条件断点的结合:

比如某个采集进程信息的程序,需要在程序启动后,查看某个特定的进程,那么,可以先用tbreak让程序在比较靠前的位置停止,当程序停止时,再执行用例,然后用条件断点,让程序在收到该进程信息时停止。

4 debug vs release

debug和release是程序发布的两种模式,两者的主要区别是:

  • debug版本包含调试信息,即编译时会带上-g选项,而release不包含调试信息
  • debug版本是默认的优化级别,也就是编译时不带-O选项,而release为了性能的考虑,会用较高的优化级别,一般会带上-O选项
  • debug版本不包含壳,release版本会加壳,是为了对程序进行加密和反混淆,提高程序被破解的难度

当使用gdb进行调试时,如果不加-g的话,程序就不带调试信息,例如,变量的名称和文件名,那么在用gdb进行调试时,就无法通过函数或者变量名添加断点,因此,在使用gdb进行调试之前编译选项需要加上-g。

5 break_pad的使用

break_pad是Google提供的一款可以上报coredump文件的工具,客户端程序可以集成该库,在程序core时,获取当前堆栈信息,可以用于在不方便登录到这些环境只能远程分析的场景。

5.1 升级gcc
5.2 breakpad的简单使用
git clone https://github.com/google/breakpad.git
cd breakpad
git clone https://github.com/getsentry/linux-syscall-support.git src/third_party/lss

然后在breakpad目录执行./configure&&make进行编译,然后在src目录下编写以下程序:

#include "client/linux/handler/exception_handler.h"

static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void*context, bool succeeded) {
	printf("Dump path: %s\n", descriptor.path());
	return succeeded;
}

void crash() {
	volatile int* a = (int*)NULL;
	*a = 1;
}

int main() {
	google_breakpad::MinidumpDescriptor descriptor("/tmp");
	google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1);
	crash();
	return 0;
}

执行以下命令进行编译:

cp client/linux/libbreakpad_client.a /usr/local/lib
g++ test.c -o test -lbreakpad_client -I./

然后执行./test就可以在/tmp目录下生成dump文件,那么在实际中如何使用breakpad呢?

5.3 breakpad的实际使用

这里又要提到上面的debug和release:debug是开发和功能测试过程中用的构建模式,编译时会带上-g选项,使用默认的优化级别_O0,release是性能测试和实际发布的构建模式,编译时会去掉-g选项,并使用高优化级别,例如-O2,同时,为了反逆向,还会对二进制进行加壳操作,提高外部对二进制分析的门槛。

# 生成debug程序
g++ test.c -g -o test.debug -lbreakpad_client -I./

# 生成release程序
g++ test.c -O2 -o test.release -lbreakpad_client -I./

下面要用到dump_syms(位于breakpad/src/tools/linux/dump_syms/dump_syms),该工具可以将二进制的符号导出来用于后续分析。

./tools/linux/dump_syms/dump_syms test.release > test.sym

当程序使用release模式进行编译后,还需要对二进制进行strip去掉里面的符号,一方面可以减小二进制的大小,另一方面当然也是防止程序被逆向。

以上面的程序为例,对生成的二进制进行strip:

strip -o test.user test.release

会发现,进行strip前,test.release二进制大小为1.6M,进行strip后,test.user二进制大小为107K。

现在为止,我们就有两个文件:其中test.user是不带调试信息并且去掉符号信息的二进制,在进行一些加密的操作后就可以给用户使用,另一个是test.sym符号文件,可以用于后续分析。

下一步就是执行test.user,此时会在/tmp目录下生成dmp文件,下面对该文件进行分析,假设生成的dump文件路径为:/tmp/d5f4ae04-2bdd-4460-a63bff89-0790bde8.dmp。

先使用minidump_stackwalk工具将dump文件和符号文件进行展开:

./processor/minidump_stackwalk /tmp/d5f4ae04-2bdd-4460-a63bff89-0790bde8.dmp ./test.sym > dump.result

查看dump.result文件,然后使用addr2line得到地址所在的程序的地方:

addr2line -f -C -e test.debug 0x405f

但是会发现,在release版本的情况下,由于加了优化级别,通过地址查不到具体导致crash的代码行,而用debug版本的情况下,是可以定位到具体报错的行。

6 定位容器中的core

如果在宿主机上用gdb定位容器中产生的core文件,会出现找不到so的问题,比如:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一方面,可能宿主机本地确实没有这些so,另一方方面,容器中使用的so跟宿主机的也可能不同。

gdb下面的提示也给出了解决办法:

  • set solib-search-path:设置so的搜索路径
  • set sysroot:设置so的根路径

将命令放到~/.gdbinit中:

set sysroot /root/gdb_root

将容器中对应路径的so拷贝到/root/gdb_root中,例如,当缺少/usr/lib/libgcc_s.so.1时,就将容器中的/usr/lib/libgcc_s.so.1放到宿主机的/root/gdb_root/usr/lib/libgcc_s.so.1,然后用gdb开启调试,此时就可以读取到对应的so,但是这种方式就需要将依赖的so都下载放到这里。

而另一个命令,set solib-search-path则适合用于会通过路径去查找so的场景,如果有时候就是查找特定路径的so,则该命令没啥用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1088571.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【DRAM存储器十六】DDR2介绍-DDR到DDR2的变化、DDR2框图详解、模式寄存器

👉个人主页:highman110 👉作者简介:一名硬件工程师,持续学习,不断记录,保持思考,输出干货内容 参考资料:《镁光DDR数据手册》 目录 DDR2 SDRAM介绍 DDR2相对DDR的变化…

C++day07(auto、lambda、类型转换、STL、文件操作)

今日任务 试编程: 封装一个学生的类,定义一个学生这样类的vector容器, 里面存放学生对象(至少3个) 再把该容器中的对象,保存到文件中。 再把这些学生从文件中读取出来,放入另一个容器中并且遍历输出该容…

go-gin-api 本地部署调试问题总结

1.告警邮箱设置 保存后会自动将配置信息保存在fat_configs.toml 文件中; 可能出现问题:报错 550和 anth 问题,说明你的邮箱配置有问题(密码或者授权码); 2.生成数据表curd 执行结果报错 exec: “gormge…

三防PDA手持终端开发板-联发科MTK6765平台安卓主板方案

三防手持终端安卓主板方案采用了联发科12nm八核MT6765处理器,配备4G64GB内存(可选配6GB256GB),并搭载最新的Android 10.0操作系统。该方案支持许多功能,包括高亮显示屏、高清摄像头、NFC、3A快速充电、1D/2D扫描(可选配)、高精度定位(可选配)…

Torch生成类激活图CAM

import torch from torch.nn import functional as F from torchvision import models, transforms from PIL import Image import os os.environ[KMP_DUPLICATE_LIB_OK]TRUE# 加载经过训练的 ResNet 模型 model models.resnet50(pretrainedTrue) model.eval()# 载入图像并进行…

NFT Insider111:The Sandbox 推出乐天世界主题公园元宇宙,Aavegotchi 与 CARV达成合作

引言:NFT Insider由NFT收藏组织WHALE Members、BeepCrypto联合出品,浓缩每周NFT新闻,为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周报将从NFT市场数据,艺术新闻类,游戏新闻类,虚拟世界类&#…

CSwin Transformer 学习笔记

Cswin提出了上图中使用交叉形状局部attention,为了解决VIT模型中局部自注意力感受野进一步增长受限的问题,同时提出了局部增强位置编码模块,超越了Swin等模型,在多个任务上效果SOTA(当时的SOTA,已经被SG Fo…

滑动窗口算法题

更新结果 1、判断条件成立后更新结果 2、入窗口后即可更新结果 判断: 出窗口后状态更新,循环回去再判断。 1、长度最小的子数组 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

【C++STL基础入门】排序和遍历容器

文章目录 前言使用前须知头文件 一、for_each算法1.1 for_each是什么1.2 函数原型1.3 示例代码1:将容器中的每个元素打印出来1.4 示例代码2:将容器中的每个字符串转换为大写形式 二、sort算法2.1 sort算法是什么?2.2 函数原型2.3 示例代码1:按…

Win10找不到hosts文件的解决方案

正常情况下,Windows10系统的C:\Windows\System32\drivers\etc目录下应该有hosts文件,但偏偏有些电脑没有,哪怕你打开了查看“隐藏的项目”也没见到hosts文件,如下: 解决方案 1、先点击查看,再点击选项&…

红队专题-工具Fscan

红队专题 招募六边形战士队员简介主要功能 ubuntu 安装windows 安装常用命令:项目框架源文件common目录Plugins目录Webscan目录爆破插件Webtitle函数webpoc扫描类型common.Scantype 免杀源码特征 参考链接 招募六边形战士队员 一起学习 代码审计、安全开发、web攻防…

有哪些免费的PPT模板网站,推荐这6个PPT模板免费下载网站!

混迹职场的打工人,或是还在校园的学生党,在日常的工作汇报或课程作业中,必然少不了PPT的影子,而每当提到做PPT,许多人首先会想到:有哪些免费的PPT模板下载网站? 本着辛苦自己,造福所…

(vue)el-select根据下拉框显示隐藏的visible-change的事件使用

(vue)el-select根据下拉框显示隐藏的visible-change的事件使用 <el-select v-model"value1"multiple:multiple-limit"2"placeholder"请选择" visible-change"visibleChange" ><el-option...></el-option> </el-s…

【C++STL基础入门】list基本使用

文章目录 前言一、list简介1.1 list是什么1.2 list的头文件 二、list2.1 定义对象2.2 list构造函数2.3 list的属性函数 总结 前言 STL&#xff08;Standard Template Library&#xff09;是C标准库的一个重要组成部分&#xff0c;提供了一套丰富的数据结构和算法&#xff0c;可…

【算法练习Day19】二叉搜索树的最近公共祖先二叉搜索树中的插入操作删除二叉搜索树中的节点

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 二叉搜索树的最近公共祖先叉…

MS5611的ZYNQ驱动试验之一 分析

0&#xff0c;MS5611框图 1&#xff0c;原理图 项目需要用到MS5611气压计模块&#xff0c;原理图很简单明了&#xff0c;如下&#xff1a; 这里PS接GND是SPI接口模式&#xff0c;PS接VDD是I2C接口模式。我在设计原理图时候直接设置成了SPI模式&#xff0c;当然这个SPI不是纯粹意…

ubuntu 22.04.3 live server图文安装流程

备注&#xff1a;以下操作全用键盘&#xff0c;tab切换&#xff0c;enter确认&#xff0c;方向键移动&#xff1b; 一、安装操作系统 1、 选择安装&#xff0c;第一个&#xff1b; 2、选择语言&#xff0c;这里只能选择英语&#xff0c;无中文&#xff1b; 3、继续而不更新 4、…

springcloud笔记(7)-限流降级Sentinel

官方文档&#xff1a;概述 | Spring Cloud Alibaba basic-api-resource-rule | Sentinel (sentinelguard.io) Sentinel是SpringCloudAlibaba的组件。 sentinel的功能 introduction | Sentinel 流量控制 熔断降级&#xff1a;降低调用链路中的不稳定资源 系统负载保护&am…

什么是接口自动化?为什么要做?和怎么做接口自动化?

服务端接口测试介绍 什么是服务端&#xff1f; 一般所说的服务端是指为用户在 APP 或 PC 使用的互联网功能提供数据服务的背后的一切。以天猫精灵智能音箱系列的产品链路为例&#xff0c;服务端便是网关&#xff08;包括网关在内&#xff09;之后的链路。 什么是接口&#xf…

数据结构—— AVL树

&#xff08;一&#xff09; 基础补充 二叉搜索树(BST) 定义&#xff1a; 二叉搜索树&#xff08;Binary Search Tree&#xff09;&#xff0c;简写BST&#xff0c;是满足某些条件的特殊二叉树。任何一个节点的左子树上的点&#xff0c;都必须小于当前节点。任何一个…