当前位置: 首页 > news >正文

arm 函数栈回溯

 大概意思就是arm每个函数开始都会将PC、LR、SP以及FP四个寄存器入栈。

 下面我们看一下这四个寄存器里面保存的是什么内存

arm-linux-gnueabi-gcc unwind.c -mapcs -w -g -o unwind(需要加上-mapcs才会严格按照上面说的入栈)

#include <stdio.h>
#include <stdlib.h>struct stackframe {unsigned long fp;//低地址unsigned long sp;unsigned long lr;unsigned long pc;//高地址
};
void backtrace() {struct stackframe *frame = NULL;unsigned long *sp = NULL;asm volatile ("mov %0, ip" : "=g"(sp));//ip里面保存的是还未压栈的spprintf("sp poniter 0x%lx\n", sp);frame = (char*)sp - sizeof(struct stackframe);printf("fp 0x%lx, pc 0x%lx, sp 0x%lx\n", frame->fp,frame->pc, frame->sp);//通过打印栈帧里面的sp确实和ip里面的一样的/* 不知道怎么结束循环.... */for (; frame->fp < 0xdeadbeef; frame = frame->fp - sizeof(struct stackframe) + sizeof(unsigned long)) {printf("Function enter at [<%08x>] from [<%08x>]\n", frame->pc, frame->lr);}
}void f3(int c) {printf("%d\n", c);backtrace();
}
void f2(int b) {f3(b);
}
void f1(int a) {char arr[5] = {0};f2(a);
}int main(int argc, char *argv[]) {printf("programe %s\n", argv[0]);f1(1);return 0;
}

arm-linux-gnueabi-objdump -S unwind > objdump 

void backtrace() {8500:	e1a0c00d 	mov	ip, sp8504:	e92dd810 	push	{r4, fp, ip, lr, pc}8508:	e24cb004 	sub	fp, ip, #4850c:	e24dd00c 	sub	sp, sp, #12
......................................000085c0 <f3>:void f3(int c) {85c0:	e1a0c00d 	mov	ip, sp85c4:	e92dd800 	push	{fp, ip, lr, pc}85c8:	e24cb004 	sub	fp, ip, #485cc:	e24dd008 	sub	sp, sp, #8
........................................85dc:	ebffff6b 	bl	8390 <_init+0x20>backtrace();85e0:	ebffffc6 	bl	8500 <backtrace>
}85e4:	e24bd00c 	sub	sp, fp, #1285e8:	e89da800 	ldm	sp, {fp, sp, pc}85ec:	0000878c 	.word	0x0000878c000085f0 <f2>:
void f2(int b) {85f0:	e1a0c00d 	mov	ip, sp85f4:	e92dd800 	push	{fp, ip, lr, pc}85f8:	e24cb004 	sub	fp, ip, #485fc:	e24dd008 	sub	sp, sp, #88600:	e50b0010 	str	r0, [fp, #-16]f3(b);8604:	e51b0010 	ldr	r0, [fp, #-16]8608:	ebffffec 	bl	85c0 <f3>
}860c:	e24bd00c 	sub	sp, fp, #128610:	e89da800 	ldm	sp, {fp, sp, pc}00008614 <f1>:
void f1(int a) {8614:	e1a0c00d 	mov	ip, sp8618:	e92dd800 	push	{fp, ip, lr, pc}861c:	e24cb004 	sub	fp, ip, #48620:	e24dd018 	sub	sp, sp, #24
..........................................f2(a);8644:	e51b0020 	ldr	r0, [fp, #-32]8648:	ebffffe8 	bl	85f0 <f2>
}864c:	e59f3018 	ldr	r3, [pc, #24]	; 866c <f1+0x58>00008670 <main>:int main(int argc, char *argv[]) {8670:	e1a0c00d 	mov	ip, sp8674:	e92dd800 	push	{fp, ip, lr, pc}8678:	e24cb004 	sub	fp, ip, #4867c:	e24dd008 	sub	sp, sp, #88680:	e50b0010 	str	r0, [fp, #-16]8684:	e50b1014 	str	r1, [fp, #-20]printf("programe %s\n", argv[0]);8688:	e51b3014 	ldr	r3, [fp, #-20]868c:	e5933000 	ldr	r3, [r3]8690:	e59f001c 	ldr	r0, [pc, #28]	; 86b4 <main+0x44>8694:	e1a01003 	mov	r1, r38698:	ebffff3c 	bl	8390 <_init+0x20>f1(1);869c:	e3a00001 	mov	r0, #186a0:	ebffffdb 	bl	8614 <f1>return 0;86a4:	e3a03000 	mov	r3, #0
}

 上面是样例代码对应的汇编代码截取。在函数的最开头都存在如下代码

    8500:	e1a0c00d 	mov	ip, sp8504:	e92dd810 	push	{r4, fp, ip, lr, pc}8508:	e24cb004 	sub	fp, ip, #4

 就是文章最开始说的函数一开始都会将fp、sp、lr以及pc压栈。那这几个寄存器里面的内容是什么呢?

sp即栈顶指针,sp里面记录的是当前函数的栈顶位置;并且从汇编代码里面能看到先是将sp给ip,然后将ip入栈。因此栈中记录的sp位置是压栈之前的

lr用于保存函数的返回地址(若f2调用f3,那在样例代码中对应的位置就是这一行8558:    e89da800     ldm    sp, {fp, sp, pc}

pc指针,程序计数器,用于记录当前执行到哪条指令。但是由于ARM采用流水线机制。当正确读取PC时,该值为当前指令(正在执行的指令)地址+8个字节。即PC执行当前指令的下两条地址。所以这就解释了样例代码的打印是0000850c

void backtrace() {
    8500:    e1a0c00d     mov    ip, sp
    8504:    e92dd810     push    {r4, fp, ip, lr, pc}//执行到这里时,pc里面记录的是下面两条指令
    8508:    e24cb004     sub    fp, ip, #4
    850c:    e24dd00c     sub    sp, sp, #12
......................................

具体可以查看这篇文章

ARM体系结构相关杂记_这个我好像学过的博客-CSDN博客

fp:frame pointer:同样也是这段代码。sub    fp, ip, #4// fp = ip - 4。那fp其实保存的就是上一个函数的函数栈起始位置-4。这也是for循环里面下一个函数栈需要写为

for (;; frame = frame->fp - sizeof(struct stackframe) + sizeof(unsigned long))

即下一个函数栈是fp + 4 - 12

为什么是上一个函数栈呢?

我们看下面的代码f1调用f2。函数f2最开始压入的fp,这个fp寄存器里面记录的是什么值呢。它里面其实就是上一个函数里面的sub    fp, ip, #4得到的啊。ip里面又是上一个函数f1的函数栈开始位置。

000085f0 <f2>:
void f2(int b) {85f0:	e1a0c00d 	mov	ip, sp85f4:	e92dd800 	push	{fp, ip, lr, pc}85f8:	e24cb004 	sub	fp, ip, #485fc:	e24dd008 	sub	sp, sp, #88600:	e50b0010 	str	r0, [fp, #-16]f3(b);8604:	e51b0010 	ldr	r0, [fp, #-16]8608:	ebffffec 	bl	85c0 <f3>
}860c:	e24bd00c 	sub	sp, fp, #128610:	e89da800 	ldm	sp, {fp, sp, pc}00008614 <f1>:
void f1(int a) {8614:	e1a0c00d 	mov	ip, sp8618:	e92dd800 	push	{fp, ip, lr, pc}861c:	e24cb004 	sub	fp, ip, #48620:	e24dd018 	sub	sp, sp, #24
..........................................f2(a);8644:	e51b0020 	ldr	r0, [fp, #-32]8648:	ebffffe8 	bl	85f0 <f2>
}864c:	e59f3018 	ldr	r3, [pc, #24]	; 866c <f1+0x58>

因此最终的函数栈构成了下图所示。那我怎么感觉文章开始的那张图片是错的呢。。。。

 最后样例代码运行结果如下图。由于不知道怎么算回溯结束,所以程序报错了

另外程序打印出来的地址也会汇编代码吻合.具体可以看汇编信息

 

 另外用arm-linux-gnueabi-addr2line解析出来的行号也是准确的

相关文章:

arm 函数栈回溯

大概意思就是arm每个函数开始都会将PC、LR、SP以及FP四个寄存器入栈。 下面我们看一下这四个寄存器里面保存的是什么内存 arm-linux-gnueabi-gcc unwind.c -mapcs -w -g -o unwind&#xff08;需要加上-mapcs才会严格按照上面说的入栈&#xff09; #include <stdio.h> …...

30个前端开发中常用的JavaScript函数

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;啥技术都喜欢捣鼓捣鼓&#xff0c;喜欢分享技术、经验、生活。 &#x1f60e;人生感悟&#xff1a;尝尽人生百味&#xff0c;方知世间冷暖。 前言 在前端开发中通常会用到校验函数…...

基于量子同态加密的改进多方量子私有比较

摘要量子同态加密在隐私保护方面具有明显的优势。本文提出了一种改进的基于量子同态加密的多方量子私钥比较协议。首先&#xff0c;引入可信密钥中心&#xff0c;安全辅助加密密钥的分发和解密密钥的更新&#xff0c;同时防止恶意服务器发布虚假结果的攻击;在保证所有参与者得到…...

解决mysqld服务启动失败

原因如下&#xff1a; 1、进程占用 首先查看下mysql进程: ps -aux | grep mysql有进程号占用了&#xff0c;kill 这个进程号 再重启服务 2、所有者和所属组为mysql 查看/usr/local/MySQL/data/mysqld.pid所有者和所属组是否为mysql 原来是权限有问题&#xff0c…...

【前端知识】React 基础巩固(四十)——Navigate导航

React 基础巩固(四十)——Navigate导航 一、Navigate的基本使用 新建Login页面&#xff0c;在Login中引入Navigate&#xff0c;实现点击登陆按钮跳转至/home路径下&#xff1a; import React, { PureComponent } from "react"; import { Navigate } from "reac…...

文件IO练习

一、用read函数完成文件大小计算 #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main(int argc, const char *argv[]) {int fd open("./1.tx…...

初识FreeRTOS入门,对FreeRTOS简介、任务调度、内存管理、通信机制以及IO操作,控制两个led不同频率闪烁

当代嵌入式系统的开发越来越复杂&#xff0c;实时性要求也越来越高。为了满足这些需求&#xff0c;开发者需要使用实时操作系统&#xff08;RTOS&#xff09;&#xff0c;其中一个流行的选择是FreeRTOS&#xff08;Free Real-Time Operating System&#xff09;。本篇博客将详细…...

STM32CUBUMX配置FLASH(W25Q128)--保姆级教程

———————————————————————————————————— ⏩ 大家好哇&#xff01;我是小光&#xff0c;嵌入式爱好者&#xff0c;一个想要成为系统架构师的大三学生。 ⏩最近在开发一个STM32H723ZGT6的板子&#xff0c;使用STM32CUBEMX做了很多驱动&#x…...

【Golang 接口自动化04】 解析接口返回JSON串

目录 前言 解析到结构体 json数据与struct字段是如何相匹配的呢&#xff1f; 解析到interface Go类型和JSON类型 实例代码 simpleJson 总结 资料获取方法 前言 上一次我们一起学习了如何解析接口返回的XML数据&#xff0c;这一次我们一起来学习JSON的解析方法。 JSO…...

EPPlus与Microsoft.Office.Interop.Excel的使用区别

文章目录 代码的使用区别EPPlus的工作原理Microsoft.Office.Interop.Excel的使用原理代码的使用区别 static void ExportToExcel(List<(string, double, double)> list, string outputFilePath){//Microsoft.Office.Interop.Excel的使用 /* Excel.Application excelAp…...

ncrack工具使用说明

介绍 网络认证破解工具。 Ncrack是用于网络身份验证破解的开源工具。 它设计为使用可适应不同网络情况的动态引擎进行高速并行破解。 Ncrack还可以针对特殊情况进行广泛的微调,尽管默认参数的通用性足以覆盖几乎所有情况。 它建立在模块化架构上,可以轻松扩展以支持其他协议…...

第二章:进程管理(处理机/CPU管理)

文章目录 2.1 进程与线程1.进程(1)进程的概念、进程的组成、进程的组织(2)进程控制块PCB(3)进程的状态与转换:五状态模型(4)进程控制(5)进程间的通信①共享存储②消息传递③管道通信(6)父进程与子进程(7)进程的内存空间2.线程 Thread(1)线程的概念(2)线程的实现方式:用户级线…...

MySQL中锁的简介——表级锁-元数据锁、意向锁

1.元数据锁 查看元数据锁 select object_type,object_scheme,object_name,lock_type,lock_duration from perfomance_scheme.metadata_locks;2.意向锁 线程A开启事务后在执行update更新语句时候&#xff0c;会给数据加上行锁&#xff0c;加上行锁以后&#xff0c;会对整张表加…...

React几种避免子组件无效刷新的方案

您好&#xff0c;如果喜欢我的文章&#xff0c;可以关注我的公众号「量子前端」&#xff0c;将不定期关注推送前端好文~ 前言 一个很常见的场景&#xff0c;React中父组件和子组件在一起&#xff0c;子组件不依赖于父组件任何数据&#xff0c;但是会一起发生变化。 在探究原…...

分享亿款好用的PDF编辑工具

所周知&#xff0c;PDF文件是不能够像word/excel/ppt等文件一样&#xff0c;可以被随意编辑的&#xff0c;PDF文件往往只能够被查看&#xff0c;我们无法对它进行编辑&#xff0c;或者对上面的文字进行复制&#xff0c;也不能任意删除上面的页面。但是很多时候&#xff0c;我们…...

AI生成式视频技术来临:Runway Gen-2文本生成视频

Runway Gen-2的官方网站提供了一种文本生成视频的工具。以下是对该工具的介绍&#xff1a; 文本生成视频&#xff1a;Runway Gen-2是一个创新的在线工具&#xff0c;可以将文本转化为视频。用户只需输入文本描述或句子&#xff0c;Runway Gen-2就能自动生成相应的视频内容。这…...

react钩子函数

React组件的生命周期包括多个阶段和方法&#xff0c;用于在组件不同的生命周期时执行特定的操作。以下是React类组件中常见的生命周期方法&#xff1a; 挂载阶段&#xff08;Mounting Phase&#xff09;&#xff1a; constructor&#xff1a;组件实例化时调用&#xff0c;用于初…...

RISC-V公测平台发布 · 如何在SG2042上玩转k3s

前言 Kubernetes是一个开源的容器管理平台&#xff0c;通过Kubernetes的跨集群管理功能&#xff0c;用户可以方便地进行应用程序的复制、迁移和跨云平台的部署。 而k3s作为Kubernetes的轻量级发行版&#xff0c;相比传统的Kubernetes具有更小的二进制文件大小和更低的资源消耗…...

Linux系统常见小问题

1、新系统在输入命令时&#xff0c;不会自动提示&#xff0c;按上箭头&#xff08;↑&#xff09;和下向下箭头&#xff08;↓&#xff09;不会匹配之前的输入 以CentOS 为例&#xff0c;可以通过配置 ~/.bashrc 文件来实现按向上箭头显示最相近的命令。以下是具体的实现步骤 …...

WEB:mfw

背景知识 Git泄露 Githack使用 命令执行漏洞 题目 这里页面里有Git&#xff0c;猜测是Git泄露 先用dirsearch扫一下 确实存在.git目录&#xff0c;可以尝试访问一下 使用Githack来下载并恢复.git文件 这里记得使用的时候关闭杀毒软件 结果会自动保存 点进去先看一下flag这个…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...