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

前言

在 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,可以快速定位到是访问空指针产生的段错误。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

javaWeb学习04

AOP核心概念: 连接点: JoinPoint, 可以被AOP控制的方法 通知: Advice 指哪些重复的逻辑&#xff0c;也就是共性功能(最终体现为一个方法) 切入点: PointCut, 匹配连接点的条件&#xff0c;通知仅会在切入点方法执行时被应用 目标对象: Target, 通知所应用的对象 通知类…

nginx(三)实现反向代理客户端 IP透传

正常情况下&#xff0c;客户端去访问代理服务器&#xff0c;然后代理服务器再取访问真实服务器&#xff0c;在真实服务器上&#xff0c;只能显示代理服务器的ip地址&#xff0c;而不显示客户端的ip地址&#xff0c;如果想让客户端的ip地址也能在真实服务端看见&#xff0c;这一…

数仓开发环境链接

这里写目录标题 1开发工具链接大数据组件1.1 启动hiveserver21.2配置DataGrip连接1.3测试使用 2 环境问题排查思路 1开发工具链接大数据组件 1.1 启动hiveserver2 数仓开发工具datagrip 需要用到JDBC协议链接到Hive&#xff0c;需要启动hiveserver2。 cd /opt/module/hive h…

string 类 经典习题之数字字符相加

题目&#xff1a; 给定两个字符串形式的非负整数 num1 和num2 &#xff0c;计算它们的和并同样以字符串形式返回。 你不能使用任何內建的用于处理大整数的库&#xff08;比如 BigInteger&#xff09;&#xff0c; 也不能直接将输入的字符串转换为整数形式。 题目来源&#xff1…

进程2月29日

题目&#xff1a;要求将当前路径下&#xff0c;所有文件的权限及最后一次的访问时间提取出来&#xff0c;写入到file.txt中。&#xff08;提示:opendir readir stat -->提取出来的数据写入到file.txt中&#xff09; 代码&#xff1a; #include <stdio.h> #include &…

C语言:数据在内存中的存储

C语言&#xff1a;数据在内存中的存储 整数存储原码、反码、补码转换规则数据与内存的关系 大小端字节序浮点数存储IEEE 754标准存储过程取用过程 数据的存储范围 整数存储 原码、反码、补码 整数的2进制表示方法有三种&#xff0c;即原码、反码和补码 三种表示方法均有符号位…

使用Python操作SQLite数据库

大家好&#xff0c;在数据涌现的今天&#xff0c;数据库已成为生活中不可或缺的工具。Python作为一种流行的编程语言&#xff0c;内置了多种用于操作数据库的库&#xff0c;其中之一就是SQLite。SQLite是一种轻量级的关系型数据库管理系统&#xff0c;它在Python中的应用非常广…

http模块学习

http模块 客户端&#xff1a;负责消费资源的电脑 服务器&#xff1a;负责对外提供网络资源的电脑&#xff0c;与普通电脑的区别就在于服务器上 安装了web服务器软件。 http模块是Node.js官方提供用来 创建web服务器的模块&#xff0c;通过http模块提供的http.createServer()方…

java之Bean对象

1. 什么是Bean&#xff1f; Bean被实例化的&#xff0c;是被Spring框架所管理的Java对象。 Spring容器会自动完成Bean的实例化。将所创建的的Bean自动注入到Ioc容器中以供调用。 spring框架中 IOC容器中管理的对象就是Bean对象 2. 第三方bean Bean 因为第三方bean&#xff0…

找不到mfc140.dll怎么办?教你五种mfc140.dll丢失的解决方法

当计算机系统中mfc140.dll文件丢失时&#xff0c;可能会引发一系列运行问题&#xff0c;影响到系统的正常功能及应用程序的稳定执行。具体来说&#xff0c;由于mfc140.dll是Microsoft Visual C Redistributable Package的重要组成部分&#xff0c;它的缺失会导致依赖于该动态链…

Unity 游戏设计模式:工厂模式

本文由 简悦 SimpRead 转码&#xff0c; 原文地址 mp.weixin.qq.com 工厂模式是一种创建型设计模式&#xff0c;它提供了一种封装对象实例化过程的方式&#xff0c;使得客户端代码与具体类的实现解耦。 在 C# 的游戏设计中&#xff0c;模式有以下作用&#xff1a; 对象的创建…

C++重新入门-string容器

目录 1.包含头文件 2.创建字符串 3.获取字符串长度 4.字符串拼接 5.字符串比较 相等性比较 大小比较 使用比较函数 6.访问字符串 7.查找子串 8.字符串修改 替换子串 插入字符或子串 删除字符或子串 9.提取子串 10.总结 当谈到C中的字符串时&#xff0c;std::str…

Unity绘制六边形体

现在steam上面有很多下棋类/经营类的游戏都是用六边形的地形&#xff0c;比较美观而且实用&#xff0c;去年在版本末期我也自己尝试做了一个绘制六边体的demo&#xff0c;一年没接触unity竟然都要忘光了&#xff0c;赶紧在这边记录一下。 想cv代码可以直接拉到代码章节 功能 …

go语言魔法技能go:linkname

我们在看Go语言的源码时&#xff0c;经常会看到一些特别的注释&#xff0c;比如&#xff1a; //go:build //go:linkname //go:nosplit //go:noescape //go:uintptrescapes //go:noinline //go:nowritebarrierrec等等&#xff0c;这些特别的注释其实是Go编译器的指示指令。这里…

基于JAVA的毕业设计分配选题系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 专业档案模块2.2 学生选题模块2.3 教师放题模块2.4 选题审核模块 三、系统展示四、核心代码4.1 查询专业4.2 新增专业4.3 选择课题4.4 取消选择课题4.5 审核课题 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpri…

Go语言必知必会100问题-10 小心类型嵌入导致的问题

小心类型嵌入导致的问题 在定义结构体时&#xff0c;Go语言支持通过类型嵌入的形式定义结构体字段。但是&#xff0c;如果我们没有真正理解类型嵌入的意义&#xff0c;有时可能会导致意想不到的行为。本文将主要分析如何嵌入类型&#xff0c;类型嵌入的作用以及可能出现的问题…

lv20 QT对话框3

1 内置对话框 标准对话框样式 内置对话框基类 QColorDialog, QErrorMessage QFileDialog QFontDialog QInputDialog QMessageBox QProgressDialogQDialog Class帮助文档 示例&#xff1a;各按钮激发对话框实现基类提供的各效果 第一步&#xff1a;实现组件布局&…

Redis 之三:发布订阅(pub/sub)

概念介绍 Redis 发布订阅 (pub/sub) 是一种消息通信模式&#xff0c;它允许客户端之间进行异步的消息传递 Redis 客户端可以订阅任意数量的频道。 模型中的角色 在该模型中&#xff0c;有三种角色&#xff1a; 发布者&#xff08;Publisher&#xff09;&#xff1a;负责发送信…

【Hudi】核心概念

https://www.bilibili.com/video/BV1ue4y1i7na?p17&vd_sourcefa36a95b3c3fa4f32dd400f8cabddeaf 大数据新风口&#xff1a;Hudi数据湖&#xff08;尚硅谷&Apache Hudi联合出品&#xff09; 1 基础概念 1.1 时间轴(TimeLine) 1.2 文件布局(File Layout) 1.3 索引(In…

Unity-PDF分割器(iTextSharp)

PDF分割器 Unity-PDF分割器前言核心思路解决过程一、Unity安装iTextSharp二、运行时计算将要生成文件的大小三、分割核心代码四、使用StandaloneFileBrowser五、其他的一些脚本六、游戏界面主体的构建MainWindowWarningPanel & FinishPanel By-Round Moon Unity-PDF分割器 …