内核打印应用程序出错信息,DEBUG_USER

news2024/11/20 7:18:29

前言

在 Linux 系统中,运行一个应用程序,突然提示段错误,并停止运行

# ./crash.out 
Segmentation fault

如果这个时候操作系统能多提示点错误信息,那将会缩短我们 debug 的时间。
core dump 就是一个办法,可以查看我之前写的一篇文章《core dump》。
今天我们来介绍另外一种方法,那就是内核编译选项 DEBUG_USER。

DEBUG_USER

在这里插入图片描述
该编译选项位于 > Kernel hacking > arm Debugging,含义是:详细的用户故障信息。

当用户程序由于异常而崩溃时,内核可以打印一条简短的消息来说明问题所在。这有时对调试很有帮助,但对生产系统没有任何作用。大多数人应该在这里说 N。
此外,你需要在内核命令行上传递 user_debug=N 来启用此特性。N 由以下和组成:

1 - 未定义的指令事件
2 - 系统调用
4 - 无效的数据中止
8 - sigsecv 故障
16 - SIGBUS 故障

测试

实验环境:ARM Linux 32bit,qemu

crash.c

#include <stdio.h>
#include <unistd.h>

int main()
{
	int *p = NULL;

    printf("*p = %d\n", *p);

	return 0;
}

Makefile

CC=/home/liyongjun/project/board/buildroot/Vexpress_2/host/bin/arm-linux-gcc

crash:
	${CC} crash.c -o crash.out -g -no-pie

cp:
	cp crash.out ~/tftp

clean:
	rm *.out

设置内核的命令行参数,添加 user_debug=0xff

# cat /proc/cmdline 
console=ttyAMA0,115200 rootwait root=/dev/mmcblk0 user_debug=0xff

将编译好的程序拷贝到 ARM Linux,为方便调试,关闭地址随机化,参考《ASLR 和 PIE》,然后执行代码

# tftp -gr crash.out 192.168.31.223
# chmod +x crash.out
# echo 0 > /proc/sys/kernel/randomize_va_space
# ./crash.out 
8<--- cut here ---
crash.out: unhandled page fault (11) at 0x00000000, code 0x017
[00000000] *pgd=611d0831, *pte=00000000, *ppte=00000000
CPU: 0 PID: 131 Comm: crash.out Not tainted 6.1.44 #1
Hardware name: ARM-Versatile Express
PC is at 0x10444
LR is at 0x76eb8868
pc : [<00010444>]    lr : [<76eb8868>]    psr: 60080010
sp : 7efffcf8  ip : 7efffd80  fp : 7efffd04
r10: 76ffece0  r9 : 7efffe7c  r8 : 00000000
r7 : 00011ed8  r6 : 00011ed8  r5 : 00000001  r4 : 7efffe74
r3 : 00000000  r2 : 7efffe7c  r1 : 7efffe74  r0 : 00000001
Flags: nZCv  IRQs on  FIQs on  Mode USER_32  ISA ARM  Segment user
Control: 10c5387d  Table: 61b74059  DAC: 00000055
Segmentation fault

程序执行出现段错误,显示 PC 位于 0x10444
我们去 host 主机,反汇编,查看 0x10444 附近的指令是什么

$ /home/liyongjun/project/board/buildroot/Vexpress_2/host/bin/arm-linux-objdump -d crash.out
...
0001042c <main>:
   1042c:       e92d4800        push    {fp, lr}
   10430:       e28db004        add     fp, sp, #4
   10434:       e24dd008        sub     sp, sp, #8
   10438:       e3a03000        mov     r3, #0
   1043c:       e50b3008        str     r3, [fp, #-8]
   10440:       e51b3008        ldr     r3, [fp, #-8]
   10444:       e5933000        ldr     r3, [r3]
   10448:       e1a01003        mov     r1, r3
   1044c:       e3000504        movw    r0, #1284       @ 0x504
   10450:       e3400001        movt    r0, #1
   10454:       ebffffad        bl      10310 <printf@plt>
   10458:       e3a03000        mov     r3, #0
   1045c:       e1a00003        mov     r0, r3
   10460:       e24bd004        sub     sp, fp, #4
   10464:       e8bd8800        pop     {fp, pc}

PC 位于 0x10444,说明代码在执行前一条指令(0x10440)时出问题了,该指令是 ldr 指令,ldr 指令的作用是将内存地址中的数据存入寄存器中,而内存地址的值为[fp, #-8],再往前两条指令

   10438:       e3a03000        mov     r3, #0
   1043c:       e50b3008        str     r3, [fp, #-8]

作用是将立即数 0 赋值给 r3,然后再将 r3 的值赋值给 [fp, #-8],所以 0x10440 处 [fp, #-8] 的值为 0,从 0 地址处取数据,超出了该应用程序所能访问的段的范围,于是发生了段错误。

objdump -S

或者我们直接使用 objdump -S 选项,来显示 C 源码和汇编的混合代码

int main()
{
   1042c:       e92d4800        push    {fp, lr}
   10430:       e28db004        add     fp, sp, #4
   10434:       e24dd008        sub     sp, sp, #8
        int *p = NULL;
   10438:       e3a03000        mov     r3, #0
   1043c:       e50b3008        str     r3, [fp, #-8]

    printf("*p = %d\n", *p);
   10440:       e51b3008        ldr     r3, [fp, #-8]
   10444:       e5933000        ldr     r3, [r3]
   10448:       e1a01003        mov     r1, r3
   1044c:       e3000504        movw    r0, #1284       @ 0x504
   10450:       e3400001        movt    r0, #1
   10454:       ebffffad        bl      10310 <printf@plt>

        return 0;
   10458:       e3a03000        mov     r3, #0
   1045c:       e1a00003        mov     r0, r3
   10460:       e24bd004        sub     sp, fp, #4
   10464:       e8bd8800        pop     {fp, pc}

出错指令对应的 C 代码为 printf("*p = %d\n", *p);,结合前面指针 p 的值为 NULL,可以快速定位到是访问空指针产生的段错误。

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

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

相关文章

网络工程师笔记2

TCP-----FTP&#xff0c;可靠连接&#xff0c;三次握手&#xff0c;四次挥手 UDP-----TFTP&#xff0c;两次握手&#xff0c;不可靠连接 应用层 传输层 网络层 网络接口层 源/目数据校验 数据帧&#xff1a; header date trailer…

每天十条linux知识点-24-0226(1)

文章目录 1.在哪下载linux内核源码&#xff1f;2.linux文件夹都有哪些文件&#xff1f;arch&#xff1a;包含和硬件体系结构相关的代码&#xff0c;每种平台占一个相应的目录&#xff0c;如i386、arm、arm64、powerpc、mips等。block&#xff1a;块设备驱动程序I/O调度。certs&…

企业文件图纸加密有哪些?图纸文件加密防泄密软件如何选?

在现在的市场发展中&#xff0c;对于企业的图纸文件安全问题越来越重视&#xff0c;如设计图纸&#xff0c;重要文件等&#xff0c;一旦泄漏就会给企业造成巨大的经济损失。所以对企业管理者来讲&#xff0c;如何才能选择一款好用的适合本企业的图纸文件加密软件是非常重要的&a…

【转载】Windows 11 任务栏位置调整

更改注册表&#xff08;部分win11版本有效&#xff09; Win R快捷键打开「运行」——执行regedit命令打开「注册表编辑器」进入路径&#xff1a; 计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects3 修改Settings这个二进制的第 2 行…

一台工控机的能量

使用Docker搭建EPICS的IOC记录 Zstack EPICS Archiver在小课题组的使用经验 以前电子枪调试&#xff0c;用一台工控机跑起束测后台&#xff0c;这次新光源用的电子枪加工回来又是测试&#xff0c;又是用一台工控机做起重复的事&#xff0c;不过生命在于折腾&#xff0c;重复的…

VR文化旅游虚拟现实介绍|虚拟现实产品销售

VR文化旅游虚拟现实&#xff08;Virtual Reality Cultural Tourism&#xff09;是指利用虚拟现实技术来提供沉浸式的文化旅游体验&#xff0c;使用户可以通过虚拟现实设备&#xff0c;如头戴式显示器或VR眼镜等&#xff0c;在虚拟空间中探索和体验不同地域、历史和文化的景点和…

一个Bug搞懂浏览器缓存策略

最近项目遇到一个问题&#xff0c;发版之后&#xff0c;用户需要清除缓存才可以访问到最新的应用&#xff0c;但是我们访问却可以正常。经过1天的研究搞懂了浏览器缓存的机制&#xff0c;记录下分析轨迹。 浏览器缓存基础知识 浏览器强缓存和协议缓存都是用来提高网页加载速度…

Python中简单正则获取百度新闻页面所有超链接示例

一、示例代码&#xff1a; import re import requestsheaders {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/""85.0.4183.83 Safari/537.36"} resp requests.get(http://news.…

135.乐理基础-半音是小二度吗?全音是大二度吗?三全音

内存参考于&#xff1a;三分钟音乐社 上一个内容&#xff1a;134.乐理基础-音程名字的简写-CSDN博客 上一个内容里练习的答案&#xff1a; 半音可以与小二度划等号吗&#xff1f;全音可以和大二度划等号吗&#xff1f; 严格来说它们是不能划等号的&#xff0c;半音与全音是侧…

1.1 编程环境的安装

汇编语言 汇编语言环境部署 第二个运行程序直接双击安装一直下一步即可MASM文件复制到D盘路径下找到dosbox安装路径&#xff1a;C:\Program Files (x86)\DOSBox-0.74找到该文件双击打开它&#xff0c;修改一下窗口大小 把这两行改成如下所示 运行dos&#xff0c;黑框中输入mou…

【GB28181】wvp-GB28181-pro快速修改登录页面名称(前端)

引言 作为一个非前端开发人员,自己摸索起来比较费劲,也浪费了很多时间 本文快速帮助开发者修改为自己名称的一个国标平台 文章目录 一、 预期效果展示二、 源码修改-前端三、 验证修改效果一、 预期效果展示 二、 源码修改-前端 需要修改的文件位置: 项目工程下web_src目录…

复现nerfstudio并训练自己制作的数据集

网站&#xff1a;安装 - nerfstudio GitHub - nerfstudio-project/nerfstudio&#xff1a;NeRF 的协作友好工作室 安装之前要确保电脑上已经有CUDA11.8或以上版本&#xff08;更高版本的可以安装11.8的toolkit&#xff09; 创建环境 conda create --name nerfstudio -y pyt…

如何实现无公网ip远程访问本地安卓Termux部署的MySQL数据库【内网穿透】

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…

基于视觉识别的自动采摘机器人设计与实现

一、前言 1.1 项目介绍 【1】项目功能介绍 随着科技的进步和农业现代化的发展&#xff0c;农业生产效率与质量的提升成为重要的研究对象。其中&#xff0c;果蔬采摘环节在很大程度上影响着整个产业链的效益。传统的手工采摘方式不仅劳动强度大、效率低下&#xff0c;而且在劳…

AI智能电销机器人效果怎么样?呼叫部署

我们的生活早已变得无处不智能&#xff0c;从智能手机到无人车、虚拟VR到智能家居&#xff0c;你迎接的每一个清晨、享受的每一个夜晚&#xff0c;可能都离不开智能设备的服务。 工作中&#xff0c;智能化产业也正在影响着企业&#xff0c;电销机器人正在帮助各大企业获得更高的…

【C++】结构体类

文章目录 问题提出一、结构体1.1结构体的声明1.1.1正常定义的结构体1.1.2在声明结构体的同时声明变量1.1.3typedef1.1.4成员变量 1.2结构体成员变量的使用1.2.1成员运算符 .1.2.2成员运算符 -> 1.3内存对齐1.3.1什么是内存对齐1.3.2内存对齐原则1.3.3结构体成员的定义顺序 1…

八股文打卡day24——数据库(1)

面试题&#xff1a;左连接和右连接的区别&#xff1f; 我的回答&#xff1a; 左连接的SQL语句是&#xff1a;左表 left join 右表 on 连接条件&#xff0c;表示以左表为基础&#xff0c;将左表的的所有记录与右表进行连接。即使右表中没有与左表匹配的记录&#xff0c;左连接…

【InternLM 实战营笔记】大模型评测

随着人工智能技术的快速发展&#xff0c; 大规模预训练自然语言模型成为了研究热点和关注焦点。OpenAI于2018年提出了第一代GPT模型&#xff0c;开辟了自然语言模型生成式预训练的路线。沿着这条路线&#xff0c;随后又陆续发布了GPT-2和GPT-3模型。与此同时&#xff0c;谷歌也…

算法修炼-动态规划之斐波那契数列模型

一、动态规划的算法原理 这是本人动态规划的第一篇文章&#xff0c;所以先阐述一下动态规划的算法原理以及做题步骤。动态规划本人的理解就是通过题目所给的条件正确地填满dp表&#xff08;一段数组&#xff09;。首先要先确定好dp表每个位置的值所代表的含义是什么&#xff0c…

Spring底层源码分析

spring依赖注入底层原理解析 spring之bean对象生命周期步骤详情 流程&#xff1a; UserService.class —>推断构造方法—>普通对象----依赖注入------>初始化&#xff08;afterPropertiesSet方法&#xff09;------>初始化后&#xff08;AOP&#xff09;------…