内核打印应用程序出错信息,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-gcccrash:${CC} crash.c -o crash.out -g -no-piecp:cp crash.out ~/tftpclean: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, #410434:       e24dd008        sub     sp, sp, #810438:       e3a03000        mov     r3, #01043c:       e50b3008        str     r3, [fp, #-8]10440:       e51b3008        ldr     r3, [fp, #-8]10444:       e5933000        ldr     r3, [r3]10448:       e1a01003        mov     r1, r31044c:       e3000504        movw    r0, #1284       @ 0x50410450:       e3400001        movt    r0, #110454:       ebffffad        bl      10310 <printf@plt>10458:       e3a03000        mov     r3, #01045c:       e1a00003        mov     r0, r310460:       e24bd004        sub     sp, fp, #410464:       e8bd8800        pop     {fp, pc}

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

   10438:       e3a03000        mov     r3, #01043c:       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, #410434:       e24dd008        sub     sp, sp, #8int *p = NULL;10438:       e3a03000        mov     r3, #01043c:       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, r31044c:       e3000504        movw    r0, #1284       @ 0x50410450:       e3400001        movt    r0, #110454:       ebffffad        bl      10310 <printf@plt>return 0;10458:       e3a03000        mov     r3, #01045c:       e1a00003        mov     r0, r310460:       e24bd004        sub     sp, fp, #410464:       e8bd8800        pop     {fp, pc}

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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# EF Core迁移数据库

现象&#xff1a; 在CodeFirst时&#xff0c;先写字段与表&#xff0c;创建数据库后&#xff0c;再添加内容 但字段与表会变更&#xff0c;比如改名删除增加等 需求&#xff1a; 当表字段变更时&#xff0c;同时变更数据库&#xff0c;执行数据库迁移 核心命令 Add-Migrat…

06|Mysql内部组件结构

1. 连接器 客户端要向mysql发起通信都必须先跟Server端建立通信连接&#xff0c;而建立连接的工作就是由连接器完成的 mysql -h host[数据库地址] -u root[用户] -p root[密码] -P 3306连接步骤: 1、如果用户名或密码不对&#xff0c;你就会收到一个"Access denied for us…

大道至简,聊聊工作中需注意的数据库开发规范

前言&#xff1a;最近要做一次数据访问组件的分享&#xff0c;想着趁此机会结合这几年的工作经历&#xff0c;好好梳理一下数据库相关的开发规范&#xff0c;之前我也写过很多这方面的文章了&#xff0c;且数据库相关的知识也没什么新意可言&#xff0c;但我之所以还是决定提笔…

Android Studio level过滤查看各个等级的日志

Android Studio level过滤查看各个等级的日志 旧版as可以在下方的日志输出框选择debug、info&#xff0c;warn、error日志&#xff0c;新版的需要通过在过滤框手动/联想输入 level:xxx&#xff0c;过滤相应等级的日志&#xff0c;如图&#xff1a; android studio/idea返回/前进…

ulimit命令

ulimit命令 ulimit 命令用于查看和设置 shell 运行时的资源限制。它可以控制各种资源&#xff0c;如文件打开数量、堆栈大小、CPU 时间等。ulimit 命令通常用于限制 shell 启动的进程的资源使用量&#xff0c;以防止系统资源被耗尽。ulimit命令的主要作用是提高系统的性能和稳…

RabbitMQ 面试八股题整理

前言&#xff1a;本文是博主网络自行收集的一些RabbitMQ相关八股文&#xff0c;还在准备暑期实习&#xff0c;后续应该会持续更新...... 参考&#xff1a;三天吃透RabbitMQ面试八股文_牛客网 目录 RabbitMQ概述 什么是 RabbitMQ&#xff1f; 说一说RabbitMQ中的AMQP 为什么…

【Vue】路由

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;Vue ⛺️稳中求进&#xff0c;晒太阳 目录 路由 单页应用程序 总结&#xff1a; VueRouter 核心步骤&#xff1a; 组件存放目录的问题 路由的封装 声明式导航 声明式导航 - 导航链…

​LeetCode解法汇总2476. 二叉搜索树最近节点查询

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; GitHub - September26/java-algorithms: 算法题汇总&#xff0c;包含牛客&#xff0c;leetCode&#xff0c;lintCode等网站题目的解法和代码&#xff0c;以及完整的mode类&#…

企业数字化转型的第一步:由被动多云向主动多云转变

随着经济环境、市场形势、技术发展、用户需求等诸多因素的变化&#xff0c;数字化转型为企业进一步提升效率和竞争力、提供更加丰富的个性化产品和服务、进行业务场景创新、探寻新的增长机会和运营模式提供了崭新的途径。越来越多的企业意识到&#xff0c;数字化转型已不是企业…

[UUCTF 2022 新生赛]ez_rce

这个题目是很简单的&#xff0c;有很多中解法&#xff0c;我来说几种&#xff0c;大家可以参考一下 1.有一个命令是l\s等于ls&#xff0c;但是我尝试codel\s结果还是被过滤了&#xff0c;于是使用printf命令包含l\s&#xff0c;加上反引号就是先执行反引号里的内容&#xff0c…

UE5 UE4 不同关卡使用Sequence动画

参考自&#xff1a;关于Datasmith导入流程 | 虚幻引擎文档 (unrealengine.com) 关卡中的Sequence动画序列&#xff0c;包含特定关卡中的Actor的引用。 将同一个Sequcen动画资源放入其他关卡&#xff0c;Sequence无法在新关卡中找到相同的Actor&#xff0c;导致报错。 Sequen…

我写了个ImageWindow应用

文章目录 0 引言1 应用简介2 主要功能和特点2.1 多图像同/异步像素级对比2.2 支持多达30种图像格式2.3 高效率的图像处理性能 3 简明使用教程3.1 软件下载安装与更新3.1.1 软件下载与安装3.1.2 软件更新 3.2 多视窗添加并自动最优排列3.3 多样化图像导入方式3.4 自动切换显示模…