arm栈推导

news2024/12/29 9:15:30

按照栈生长方向分:可以分为递增栈(向高地址生长);递减栈(向低地址生长)

按照sp执行位置来分:满栈(sp指向栈顶元素的位置);空栈(sp指向即将入栈的元素位置)

我这个环境是满减栈

 其实通过函数栈推导函数调用过程主要就是结合sp的位置以及汇编代码的压栈信息。找到LR寄存器的位置。

代码示例

起了一个内核线程,在函数f3里面会访问空指针,然后进入kdb

void f3(void ) {
  int i     = 0;
  int* addr = NULL; 
  for (i = 0; i < 10; ++i)
  {
     printk("%d\n", i);
  }
  *addr = 0x123;
  return;
}
void f2(int a, int b) {
  int d = 0;
  int *addr = 0;
  f3();
  d = a + b;
  printk("%d, %p\n", d, addr);
  return;
}

void f1(int a, int b) {
  int c = 0;
  c = a + b;
  f2(c,20);
  while (c > 0)
  {  
	printk("%d\n", c);
	--c;
  }
  return;
}
struct timer_list timer;
spinlock_t mylock;
static struct task_struct *test_task;
int test_thread(void* a)
{
	unsigned long flags;
	printk(KERN_EMERG "\r\n softlockup simulate, in_interrupt %u in_softirq %u, cpu id %d\n", in_interrupt(), in_softirq(), smp_processor_id());
	
	/*local_irq_disable();
	while (1){}*/
	f1(10, 20);
	return 0;
}

对应的汇编代码如下 

void f3(void ) {
    3ed0:	e92d4010 	push	{r4, lr}
  int i     = 0;
  int* addr = NULL; 
  for (i = 0; i < 10; ++i)
    3ed4:	e3a04000 	mov	r4, #0
  {
     printk("%d\n", i);
    3ed8:	e1a01004 	mov	r1, r4
    3edc:	e59f001c 	ldr	r0, [pc, #28]	; 3f00 <f3+0x30>
	dev->dev_addr[5] = (u8)(mac_high16 >> 8);
}
void f3(void ) {
  int i     = 0;
  int* addr = NULL; 
  for (i = 0; i < 10; ++i)
    3ee0:	e2844001 	add	r4, r4, #1
  {
     printk("%d\n", i);
    3ee4:	ebfffffe 	bl	0 <printk>
	dev->dev_addr[5] = (u8)(mac_high16 >> 8);
}
void f3(void ) {
  int i     = 0;
  int* addr = NULL; 
  for (i = 0; i < 10; ++i)
    3ee8:	e354000a 	cmp	r4, #10
    3eec:	1afffff9 	bne	3ed8 <f3+0x8>
  {
     printk("%d\n", i);
  }
  *addr = 0x123;
    3ef0:	e3a03000 	mov	r3, #0
    3ef4:	e3002123 	movw	r2, #291	; 0x123
    3ef8:	e5832000 	str	r2, [r3]
    3efc:	e8bd8010 	pop	{r4, pc}
    3f00:	0000034c 	.word	0x0000034c

00003f04 <f2>:
  return;
}
void f2(int a, int b) {
    3f04:	e92d4038 	push	{r3, r4, r5, lr}
    3f08:	e1a04000 	mov	r4, r0
    3f0c:	e1a05001 	mov	r5, r1
  int d = 0;
  int *addr = 0;
  f3();
    3f10:	ebfffffe 	bl	3ed0 <f3>
  d = a + b;
  printk("%d, %p\n", d, addr);
    3f14:	e0841005 	add	r1, r4, r5
    3f18:	e3000000 	movw	r0, #0
    3f1c:	e3a02000 	mov	r2, #0
    3f20:	e3400000 	movt	r0, #0
  return;
}
    3f24:	e8bd4038 	pop	{r3, r4, r5, lr}
void f2(int a, int b) {
  int d = 0;
  int *addr = 0;
  f3();
  d = a + b;
  printk("%d, %p\n", d, addr);
    3f28:	eafffffe 	b	0 <printk>

00003f2c <f1>:
  return;
}

void f1(int a, int b) {
    3f2c:	e92d4010 	push	{r4, lr}
  int c = 0;
  c = a + b;
    3f30:	e0804001 	add	r4, r0, r1
  f2(c,20);
    3f34:	e3a01014 	mov	r1, #20
    3f38:	e1a00004 	mov	r0, r4
    3f3c:	ebfffffe 	bl	3f04 <f2>
  while (c > 0)
    3f40:	e3540000 	cmp	r4, #0
    3f44:	d8bd8010 	pople	{r4, pc}
  {  
	printk("%d\n", c);
    3f48:	e1a01004 	mov	r1, r4
    3f4c:	e59f000c 	ldr	r0, [pc, #12]	; 3f60 <f1+0x34>
    3f50:	ebfffffe 	bl	0 <printk>

void f1(int a, int b) {
  int c = 0;
  c = a + b;
  f2(c,20);
  while (c > 0)
    3f54:	e2544001 	subs	r4, r4, #1
    3f58:	1afffffa 	bne	3f48 <f1+0x1c>
    3f5c:	e8bd8010 	pop	{r4, pc}
    3f60:	0000034c 	.word	0x0000034c

00003f64 <test_thread>:
}
struct timer_list timer;
spinlock_t mylock;
static struct task_struct *test_task;
int test_thread(void* a)
{
    3f64:	e92d4008 	push	{r3, lr}
    3f68:	e1a0200d 	mov	r2, sp
    3f6c:	e3c23d7f 	bic	r3, r2, #8128	; 0x1fc0
	unsigned long flags;
	printk(KERN_EMERG "\r\n softlockup simulate, in_interrupt %u in_softirq %u, cpu id %d\n", in_interrupt(), in_softirq(), smp_processor_id());
    3f70:	e3a01cff 	mov	r1, #65280	; 0xff00
    3f74:	e3c3303f 	bic	r3, r3, #63	; 0x3f
    3f78:	e340101f 	movt	r1, #31
    3f7c:	e3000000 	movw	r0, #0
    3f80:	e3400000 	movt	r0, #0
    3f84:	e5932004 	ldr	r2, [r3, #4]
    3f88:	e5933014 	ldr	r3, [r3, #20]
    3f8c:	e0021001 	and	r1, r2, r1
    3f90:	e2022cff 	and	r2, r2, #65280	; 0xff00
    3f94:	ebfffffe 	bl	0 <printk>
	
	/*local_irq_disable();
	while (1){}*/
	f1(10, 20);
    3f98:	e3a0000a 	mov	r0, #10
    3f9c:	e3a01014 	mov	r1, #20
    3fa0:	ebfffffe 	bl	3f2c <f1>
	return 0;
}
    3fa4:	e3a00000 	mov	r0, #0
    3fa8:	e8bd8008 	pop	{r3, pc}

从上面的汇编代码可以看到每个函数的入栈信息如下。假设函数f3里面的栈顶指针为 sp_f3

完整的异常log如下: 

Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 817 [#1] SMP ARM

Entering kdb (current=0xeea2e880, pid 649) on processor 3 Oops: (null)
due to oops @ 0xc03087a8

dCPU: 3 PID: 649 Comm: test_task Not tainted 3.16.0 #65
dtask: eea2e880 ti: ee226000 task.ti: ee226000
PC is at f3+0x28/0x34
LR is at f3+0x18/0x34
pc : [<c03087a8>]    lr : [<c0308798>]    psr: 60000013
sp : ee227f40  ip : 00000001  fp : 00000000
r10: 00000000  r9 : 00000000  r8 : 00000000
r7 : c0308814  r6 : 00000000  r5 : 00000014  r4 : 0000000a
r3 : 00000000  r2 : 00000123  r1 : 20000093  r0 : 00000001
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 10c53c7d  Table: 8e30006a  DAC: 00000015
dCPU: 3 PID: 649 Comm: test_task Not tainted 3.16.0 #65
[<c0014320>] (unwind_backtrace) from [<c0010fa4>] (show_stack+0x10/0x14)
[<c0010fa4>] (show_stack) from [<c045cc6c>] (dump_stack+0x74/0x90)
[<c045cc6c>] (dump_stack) from [<c00823f4>] (kdb_dumpregs+0x30/0x50)
[<c00823f4>] (kdb_dumpregs) from [<c0084754>] (kdb_main_loop+0x31c/0x70c)
[<c0084754>] (kdb_main_loop) from [<c0087128>] (kdb_stub+0x1e0/0x44c)
[<c0087128>] (kdb_stub) from [<c007dbac>] (kgdb_cpu_enter+0x3c4/0x6e0)
[<c007dbac>] (kgdb_cpu_enter) from [<c007e150>] (kgdb_handle_exception+0x168/0x1d0)
[<c007e150>] (kgdb_handle_exception) from [<c0013998>] (kgdb_notify+0x24/0x3c)
[<c0013998>] (kgdb_notify) from [<c003f95c>] (notifier_call_chain+0x44/0x84)
[<c003f95c>] (notifier_call_chain) from [<c003f9b4>] (__atomic_notifier_call_chain+0x18/0x20)
[<c003f9b4>] (__atomic_notifier_call_chain) from [<c003f9d4>] (atomic_notifier_call_chain+0x18/0x20)
[<c003f9d4>] (atomic_notifier_call_chain) from [<c0040108>] (notify_die+0x3c/0x44)
[<c0040108>] (notify_die) from [<c0011090>] (die+0xe8/0x2c8)
[<c0011090>] (die) from [<c0459e8c>] (__do_kernel_fault.part.8+0x54/0x74)
[<c0459e8c>] (__do_kernel_fault.part.8) from [<c0019a28>] (do_page_fault+0x1a8/0x3a4)
[<c0019a28>] (do_page_fault) from [<c00084dc>] (do_DataAbort+0x34/0x98)
[<c00084dc>] (do_DataAbort) from [<c0011a18>] (__dabt_svc+0x38/0x60)
Exception stack(0xee227ef8 to 0xee227f40)
7ee0:                                                       00000001 20000093
7f00: 00000123 00000000 0000000a 00000014 00000000 c0308814 00000000 00000000
7f20: 00000000 00000000 00000001 ee227f40 c0308798 c03087a8 60000013 ffffffff
[<c0011a18>] (__dabt_svc) from [<c03087a8>] (f3+0x28/0x34)
[<c03087a8>] (f3) from [<c03087c4>] (f2+0x10/0x28)
[<c03087c4>] (f2) from [<c03087f0>] (f1+0x14/0x38)
[<c03087f0>] (f1) from [<c0308854>] (test_thread+0x40/0x48)
[<c0308854>] (test_thread) from [<c003c4fc>] (kthread+0xcc/0xe8)
[<c003c4fc>] (kthread) from [<c000e4f8>] (ret_from_fork+0x14/0x3c)

 

从异常log我们可以知道f3的栈顶指针为 sp : ee227f40

f2的返回地址为ee227f40 + 4指向的地址里面的内容

同理一级一级往上推

 

 

 c03087c4 = 0xc03087c4 (f2+0x10)

c03087f0 = 0xc03087f0 (f1+0x14)
c0308854 = 0xc0308854 (test_thread+0x40)
c003c4fc = 0xc003c4fc (kthread+0xcc)

和异常log里面的一样
[<c03087a8>] (f3) from [<c03087c4>] (f2+0x10/0x28)
[<c03087c4>] (f2) from [<c03087f0>] (f1+0x14/0x38)
[<c03087f0>] (f1) from [<c0308854>] (test_thread+0x40/0x48)
[<c0308854>] (test_thread) from [<c003c4fc>] (kthread+0xcc/0xe8)
[<c003c4fc>] (kthread) from [<c000e4f8>] (ret_from_fork+0x14/0x3c)

另外也可以用命令mds直接查看 

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

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

相关文章

ChatGPT 和 Elasticsearch:APM 工具、性能和成本分析

作者&#xff1a;LUCA WINTERGERST 在本博客中&#xff0c;我们将测试一个使用 OpenAI 的 Python 应用程序并分析其性能以及运行该应用程序的成本。 使用从应用程序收集的数据&#xff0c;我们还将展示如何将 LLMs 成到你的应用程序中。 在之前的博客文章中&#xff0c;我们构建…

SpringBoot+Vue 整合websocket实现简单聊天窗口

效果图 1 输入临时名字充当账号使用 2 进入聊天窗口 3 发送消息 &#xff08;复制一个页面&#xff0c;输入其他名字&#xff0c;方便展示效果&#xff09; 4 其他窗口效果 代码实现 后端SpringBoot项目&#xff0c;自行创建 pom依赖 <dependency><groupId…

docker安装xxl-job连接数据库时显示无法连接问题

背景&#xff1a; 在项目中需要定时任务调度&#xff0c;需要在docker容器中安装xxl-job 遇到的问题 部署成功后&#xff0c;可以访问xxl-job登录界面&#xff0c;点登录没反应&#xff0c;但过一段时间就弹出数据库拒绝连接&#xff0c;说MyBatis连接用户失败 原因&#xf…

华为云API图像识别Image的趣味性—AI识别迈克尔·杰克逊

云服务、API、SDK&#xff0c;调试&#xff0c;查看&#xff0c;我都行 阅读短文您可以学习到&#xff1a;人工智能AI图像识别的图像识别、名人识别 1 IntelliJ IDEA 之API插件介绍 API插件支持 VS Code IDE、IntelliJ IDEA等平台、以及华为云自研 CodeArts IDE&#xff0c;基…

深度学习算法

深度学习算法 1. 各种网络框架及其联系1.1 两阶段与一阶段区别1.1.1 detectron算法框架套路&#xff1a;1.1.2 multi-stage1.1.3 two-stage 算法1.1.4 one-stage 算法 2. 常用算法2.1 SS(选择性搜索算法&#xff0c;Selective Search) 3. 神经元模型4. 神经网络分类4.1 前馈神经…

Linux内核分析与应用5-中断

本系列是对 陈莉君 老师 Linux 内核分析与应用[1] 的学习与记录。讲的非常之好&#xff0c;推荐观看 留此记录&#xff0c;蜻蜓点水,可作抛砖引玉 中断机制概述 中断是CPU对系统发生的某个事件作出的一种反应, 当中断发生时,CPU暂停正在执行的程序,保留现场后,自动转去执行相应…

一本快速入门Java的书

关于这本书 很高兴&#xff0c;我又一本书籍《Java编程动手学》上市了。记得早在2017年&#xff0c;在我跟人邮出版社的傅道坤编辑合作完《Tomcat内核设计剖析》这本书后&#xff0c;傅编就问我考不考虑写一本面向Java初学者的图书&#xff0c;当时我谢绝了傅编的邀请。一来是我…

总结986

时间记录&#xff1a; 7:10起床 8:00~下午2:00课程设计&#xff0c;偷学了3小时 2:17~3:55午觉 4:10~5:30计网 5:35~6:41数据结构 7:00~7:22继续数据结构课后习题重做 7:23~8:07考研政治&#xff0c;做题20道纠错 8:15~8:39每日长难句 8:39~10:21 14年tex2纠错标记 1…

Unity下如何实现RTMP或RTSP播放端录像?

好多开发者问我们&#xff0c;Unity环境下&#xff0c;除了RTSP或RTMP的播放&#xff0c;如果有录像诉求&#xff0c;怎么实现&#xff1f;实际上录像相对播放来说&#xff0c;更简单一些&#xff0c;因为不涉及到绘制&#xff0c;只要拉流下来数据&#xff0c;直接写mp4文件就…

pytorch代码实现之SAConv卷积

SAConv卷积 SAConv卷积模块是一种精度更高、速度更快的“即插即用”卷积&#xff0c;目前很多方法被提出用于降低模型冗余、加速模型推理速度&#xff0c;然而这些方法往往关注于消除不重要的滤波器或构建高效计算单元&#xff0c;反而忽略了特征内部的模式冗余。 原文地址&am…

BUUCTF Reverse/[羊城杯 2020]login(python程序)

查看信息,python文件 动调了一下&#xff0c;该程序创建了一个线程来读入数据&#xff0c;而这个线程的代码应该是放在内存中直接执行的&#xff0c;本地看不到代码&#xff0c;很蛋疼 查了下可以用PyInstaller Extractor工具来解包&#xff0c;可以参考这个Python解包及反编译…

华为云云服务器云耀L实例评测 | 在华为云耀L实例上搭建电商店铺管理系统:一次场景体验

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

sqli第一关

1.在下使用火狐访问sqlilabs靶场并使用burpsuite代理火狐。左为sqlilabs第一关&#xff0c;右为burpsuite。 2.输入?id1 and 11 与?id1 and 12试试 可以看出没有变化哈&#xff0c;明显我们输入的语句被过滤了。在?id1后面尝试各种字符&#xff0c;发现单引号 包…

Linux内核分析与应用4-内存管理

本系列是对 陈莉君 老师 Linux 内核分析与应用[1] 的学习与记录。讲的非常之好&#xff0c;推荐观看 留此记录&#xff0c;蜻蜓点水,可作抛砖引玉 4.1 Linux内存管理机制 lscpu[2] 命令, 类似是优化后的 cat /proc/cpuinfo 实现虚拟内存的几种机制: 当 程序一旦跑起来,那就变成…

IDEA在创建包时如何把包分开实现自动分层

IDEA在创建包时如何把包分开实现自动分层 文章目录 IDEA在创建包时如何把包分开实现自动分层一、为什么要把包分开二、建包时如何把包自动分开三、如何编写配置文件路径&#xff1f; 一、为什么要把包分开 一开始的时候&#xff0c;我也一直以为包连在一起和分开没什么区别&am…

二叉搜索树/二叉排序树/二叉查找树

文章目录 1.概念2.操作3.实现3.1框架3.2BSTree.h3.3test.cpp 1.概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;…

python 学习笔记(5)——SMTP 使用QQ邮箱发送邮件

目录 发送邮件 1、准备工作&#xff1a; 2、发送纯文本信息内容&#xff1a; 3、发送 HTML 格式的内容&#xff1a; 4、发送带附件的邮件&#xff1a; 5、群发&#xff08;一个邮件&#xff0c;发给多个人&#xff09;&#xff1a; 发送邮件 以下都 以 QQ邮箱 为发送方举…

敏捷开发方法管理项目,适应变化,引领未来

​敏捷开发方法是一种灵活且高效的项目管理方法&#xff0c;旨在应对不断变化的需求和快速发展的项目环境。使用敏捷开发方法可以帮助团队更好地应对不确定性&#xff0c;提高项目的质量和效率。以下是使用敏捷开发方法管理项目的具体步骤&#xff1a; 明确项目目标和范围 在…

算法通过村第六关-树白银笔记|层次遍历

文章目录 前言1. 层次遍历介绍2. 基本的层次遍历与变换2.1 二叉树的层次遍历2.2 层次遍历-自底向上2.3 二叉树的锯齿形层次遍历2.4 N叉树的层次遍历 3. 几个处理每层元素的题目3.1 在每棵树行中找出最大值3.2 在每棵树行中找出平均值3.3 二叉树的右视图3.4 最底层最左边 总结 前…

C高级day4(shell脚本)

一、Xmind整理&#xff1a; 二、上课笔记整理&#xff1a; 1.创建一个文件&#xff0c;给组用户可读权限&#xff0c;所属用户可写权限&#xff0c;其他用户可执行权限&#xff0c;使用if判断文件有哪些权限 #!/bin/bash touch 1 chmod 241 1 if [ -r 1 ] thenecho "文件…