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

ARM64架构栈帧回溯

文章目录

  • 前言
  • 一、栈帧简介
  • 二、demo演示

前言

请参考:ARM64架构栈帧以及帧指针FP

一、栈帧简介

假设下列函数调用:

funb()
{func()
}funa()
{funb()
}main()
{funa()
}

main函数,funa函数,funb函数都不是叶子函数,其栈布局如下所示:
在这里插入图片描述
LR 和FP寄存器保存在每个函数栈帧的栈顶:
FP = SP + 0
LR = SP + 8
根据这两个寄存器就可以反推出所有函数的调用栈。

FP栈帧指针(X29)指向保存在栈上的上一个栈帧的帧指针。在它之后存储了保存的LR(X30)。链中的最后一个帧指针应设置为0。

知道FP寄存器就能得到每个函数的栈帧基地址。而知道每个函数的栈帧基地址的条件下,可通过当前函数栈帧保存的LR获得当前函数的Entry地址和函数名。
通过FP还可以知道上一级的FP(栈帧基地址)。

在ARM64体系结构中,函数调用栈以单链表形式组织,其中每个栈帧都包含两个地址,用于构建这个链表。这种链表通常被称为调用链或链式栈。

在链式栈中,每个栈帧都有两个64位宽的地址:
(1)低地址(栈顶)存放了指向上一个栈帧的基地址,通常使用FP(Frame Pointer)寄存器来保存。类似于链表中的prev指针,它指向上一个栈帧的基地址,以便在函数返回时回到调用者的上下文。

(2)高地址存放了LR(Link Register)寄存器的值,它保存了当前函数的返回地址。LR寄存器中的值指向了调用当前函数的下一条指令的地址。当函数执行完毕时,该地址将被用于恢复程序控制流,并返回到调用者的位置。

通过这种方式,每个栈帧都可以通过链表中的prev指针链接在一起,形成一个完整的函数调用链。当函数返回时,可以使用prev指针获取上一个栈帧的基地址,并利用LR寄存器中的返回地址将控制流传递给调用者。

ARM64栈回溯:
在AAPC64中,栈指针(SP)指向当前栈帧的顶部,其中包含了上一级函数的LR和FP寄存器现场。通过查看SP所指向的地址,可以找到保存的上一级函数的LR和FP寄存器值。

对于LR寄存器,根据(LR-4)可以找到上一级函数所在的地址,减去4是因为ARM64指令集中的跳转指令(例如BL)会将要跳转到的地址加上4。因此,在栈上保存的LR值实际上是要跳转到的下一条指令的地址,而不是当前指令的地址。所以,为了找到上一级函数所在的地址,需要减去4。

上一级函数的FP寄存器实际上等于上一级函数使用的栈顶地址。通过保存上一级FP寄存器现场的位置,可以在栈上找到上一级函数的栈帧。同样,该栈帧中也会保存更上一级函数的LR和FP寄存器现场,以此类推,形成函数调用链。

通过链式保存的方式,可以回溯整个函数的调用流程,从当前函数一直追溯到最外层的调用者。这种方式使得在函数返回时可以按照相反的顺序恢复各个函数的现场,并正确返回到调用者的位置。

二、demo演示

C语言示例:

int fund(int g, int h)
{return g + h;
}int func(int e, int f)
{int ret = e + f;ret = fund(e, ret);return ret;
}int funb(int c, int d)
{int ret = c + d;ret = func(c, ret);return ret;}int funa(int a, int b)
{int ret = a + b ;ret = funb(a, ret);return ret;
}int main(void)
{int i = 1, j = 2;int ret = funa(i,j);return 0;
}
(gdb) b main
(gdb) b funa
(gdb) b funb
(gdb) b func
(gdb) r

(1)
main:

(gdb) disassemble
Dump of assembler code for function main:......0x0000005555555810 <+32>:    bl      0x55555557b4 <funa>0x0000005555555814 <+36>:    str     w0, [sp, #28]......
x29            0x7ffffff400
x30            0x7ff7e5c110

(2)
funa:

(gdb) c
(gdb) disassemble
Dump of assembler code for function funa:......0x00000055555557dc <+40>:    bl      0x5555555778 <funb>0x00000055555557e0 <+44>:    str     w0, [sp, #44]......
(gdb) info registers
x29            0x7ffffff3d0
x30            0x5555555814

可以看到x30寄存器的值就是main函数 bl funa 下一条指令的地址。

根据x29寄存器得到funa栈帧基地址:

0x7ffffff3d0

读取该地址的值(x29寄存器FP存放了指向上一个栈帧的基地址):

(gdb) x/1xg 0x7ffffff3d0
0x7ffffff3d0:   0x0000007ffffff400

那么可以得到main函数的栈帧基地址:0x0000007ffffff400
这个值就等于执行main函数时,x29寄存器的值。

将main函数的栈帧基地址+8然后读取获取main的返回地址:
这里 + 8 的原因:LR = FP + 8

0x0000007ffffff400 + 8 = 0x0000007ffffff408
(gdb) x/1xg 0x0000007ffffff408
0x7ffffff408:   0x0000007ff7e5c110

main的返回地址:0x0000007ff7e5c110

将main的返回地址 - 4 就可以获取 BL main这条函数跳转指令的地址:
这里 - 4 的原因:执行BL指令时,将下一条指令的地址(即返回地址)写入X30寄存器中,这里我们已经获取到了返回地址,那么 -4 就获取到了 BL 指令的地址。

0x0000007ff7e5c110 - 4 = 0x0000007ff7e5c10c

那么其上一条调用main的指令地址就是0x0000007ff7e5c10c:

(gdb) x/i 0x0000007ff7e5c10c0x7ff7e5c10c <__libc_start_main+228>:        blr     x3
(gdb) x/2i 0x0000007ff7e5c10c0x7ff7e5c10c <__libc_start_main+228>:        blr     x30x7ff7e5c110 <__libc_start_main+232>:        bl      0x7ff7e71a40 <exit>

可以看到是__libc_start_main函数调用 main 函数。

(3)
funb:

(gdb) disassemble
Dump of assembler code for function funb:......0x00000055555557a0 <+40>:    bl      0x555555573c <func>0x00000055555557a4 <+44>:    str     w0, [sp, #44]......
(gdb) info registers
x29            0x7ffffff3a0
x30            0x55555557e0

可以看到x30寄存器的值就是 funa bl funb下一条指令的地址。

根据x29寄存器得到funb栈帧基地址:

0x7ffffff3a0

读取该地址的值(x29寄存器FP存放了指向上一个栈帧funa的基地址):

(gdb) x/1xg 0x7ffffff3a0
0x7ffffff3a0:   0x0000007ffffff3d0

这个值就等于执行funa函数时,x29寄存器的值。

将funa函数的栈帧基地址+8然后读取获取funa的返回地址:

0x0000007ffffff3d0 + 8 = 0x0000007ffffff3d8
(gdb) x/1xg 0x0000007ffffff3d8
0x7ffffff3d8:   0x0000005555555814

funa的返回地址:0x0000005555555814

将funa的返回地址 - 4 就可以获取 main BL funa这条函数跳转指令的地址:

0x0000005555555814- 4 = 0x0000005555555810

那么其上一条调用funa的指令地址就是0x0000005555555810:

(gdb) x/i 0x00000055555558100x5555555810 <main+32>:      bl      0x55555557b4 <funa>
(gdb) x/2i 0x00000055555558100x5555555810 <main+32>:      bl      0x55555557b4 <funa>0x5555555814 <main+36>:      str     w0, [sp, #28]

可以看到是main函数调用 funa 函数。

(4)
func:

(gdb) disassemble
Dump of assembler code for function func:......0x0000005555555764 <+40>:    bl      0x555555571c <fund>0x0000005555555768 <+44>:    str     w0, [sp, #44]......
(gdb) info registers
x29            0x7ffffff370
x30            0x55555557a4

可以看到x30寄存器的值就是 funb bl func下一条指令的地址。

根据x29寄存器得到func栈帧基地址:

0x7ffffff370

读取该地址的值(x29寄存器FP存放了指向上一个栈帧funb的基地址):

(gdb) x/1xg 0x7ffffff370
0x7ffffff370:   0x0000007ffffff3a0

这个值就等于执行funb函数时,x29寄存器的值。

将funb函数的栈帧基地址+8然后读取获取funb的返回地址:

0x0000007ffffff3a0 + 8 = 0x0000007ffffff3a8
(gdb) x/1xg 0x0000007ffffff3a8
0x7ffffff3a8:   0x00000055555557e0

funb的返回地址:0x00000055555557e0

将funb的返回地址 - 4 就可以获取 funaBL funb这条函数跳转指令的地址:

0x00000055555557e0 - 4 = 0x00000055555557dc

那么其上一条调用funb的指令地址就是0x00000055555557dc:

(gdb) x/i 0x00000055555557dc0x55555557dc <funa+40>:      bl      0x5555555778 <funb>
(gdb) x/2i 0x00000055555557dc0x55555557dc <funa+40>:      bl      0x5555555778 <funb>0x55555557e0 <funa+44>:      str     w0, [sp, #44]

可以看到是funa函数调用 funb 函数。

相关文章:

ARM64架构栈帧回溯

文章目录 前言一、栈帧简介二、demo演示 前言 请参考&#xff1a;ARM64架构栈帧以及帧指针FP 一、栈帧简介 假设下列函数调用&#xff1a; funb() {func() }funa() {funb() }main() {funa() }main函数&#xff0c;funa函数&#xff0c;funb函数都不是叶子函数&#xff0c;其…...

LangChain:大型语言模型(LLMs)-- 基础知识

1、LangChain的调用大型语言模型模块的介绍 LangChain是一个强大的框架&#xff0c;旨在通过调用大型语言模型&#xff08;LLM&#xff09;来开发各种语言驱动的应用程序。在LangChain中&#xff0c;LLM不仅仅是一个简单的模型调用&#xff0c;而是一个复杂链条中的关键部分。…...

总分410+专业130+国防科技大学831信号与系统考研经验国防科大电子信息与通信工程,真题,大纲,参考书。

好几个学弟催着&#xff0c;总结一下我自己的复习经历&#xff0c;希望大家复习少走弯路&#xff0c;投入的复习正比换回分数。我专业课831信号与系统130&#xff08;感觉比估分要低&#xff0c;后面找Jenny老师讨论了自己拿不准的地方也没有错误&#xff0c;心里最近也这经常回…...

chatgpt Team 4.0共享合租账号的新方式

为了更好地满足工作需求&#xff0c;我订阅了GPT PLUS会员&#xff0c;但我发现&#xff0c;4.0每三小时问答40次经常吃灰&#xff0c;而且每月近200元的费用让我感到有点肉痛。 于是&#xff0c;我开始寻找有没有什么替代品。在逛某论坛的时候&#xff0c;发现了一个共享Team…...

类和对象二

一、运算符重载 为了使自定义类型可以使用加减等运算符&#xff0c;CPP提供了一个功能叫运算符重载。 关键字&#xff1a;operator操作符 运算符重载最好定义在类对象里&#xff0c;这也可以避免访问不到私有成员的问题。 代码演示&#xff1a; 在类里定义之后&#xff0c;…...

GD32 HID键盘矩阵键盘发送数据时,一直发送数据问题处理

这个问题找了两三天,开始并不认为是示例程序的问题,只是感觉是自己代码问题。 这个解决流程大概是: 先调好矩阵键盘=> 调用发送函数。 就是因为调用时,一直发送数据,我也在按键抬起做了操作,始终不行。 最后,发现时示例代码中有个 空闲中断 引起的。 udev->reg…...

小程序地理位置权限申请+uniapp调用uni.getLocation

文章目录 一、小程序地理位置权限申请二、uniapp调用uni.getLocation 一、小程序地理位置权限申请 需要确保小程序类目已经填写 点击左侧导航栏找到最后的“设置”——“基本设置”——“前往填写” 在开发管理——接口设置——地理位置中可以看到&#xff1a; 即可点击想要申…...

后台权限控制及动态路由

需求 后台系统需要能实现不同的用户权限可以看到不同的功能。 用户只能使用他的权限所允许使用的功能。 功能设计 之前在我的SpringSecurity的课程中就介绍过RBAC权限模型。没有学习过的可以去看下 RBAC权限模型 。这里我们就是在RBAC权限模型的基础上去实现这个功能。 表分…...

云计算:Linux 部署 OVS 集群(控制端)实现OpenFlow

目录 一、实验 1.环境 2.Linux 部署 OVS 集群&#xff08;控制端&#xff09; 3.控制端对接服务端OVS网元 4.服务端OVS添加流表 5.服务端删除OVS 二、问题 1. ODL如何查找已安装插件 2.查看流表显示不全 3.如何删除OVS流表 一、实验 1.环境 (1) 主机 表1 宿主机 主…...

使用/api/put保存数据到OpenTSDB,报204错误

错误信息 HttpResponseProxy{HTTP/1.1 204 No Content [Content-Type: application/json; charsetUTF-8, Content-Length: 0]} 错误原因 在OpenTSDB中&#xff0c;使用/api/put保执行写入操作&#xff0c;得到204响应&#xff0c;表示已经成功写入数据库。...

Open3D kmeans聚类(马氏距离,Python版本)

文章目录 一、简介二、算法步骤三、代码实现四、实现效果参考资料一、简介 在诸多的聚类方法中,K-Means聚类方法是属于“基于原型的聚类”(也称为原型聚类)的方法,此类方法均是假设聚类结构能通过一组原型刻画,在现实聚类中极为常用。通常情况下,该类算法会先对原型进行初始…...

python抠图程序

import cv2 import numpy as np def color_threshold(image, lower, upper): hsv_image cv2.cvtColor(image, cv2.COLOR_BGR2HSV) mask cv2.inRange(hsv_image, lower, upper) result cv2.bitwise_and(image, image, maskmask) return result # 读取图片…...

Android13 CameraServer启动流程

代码入口 frameworks/av/camera/cameraserver 里面包含了四个文件 我们先来看看Android.bp的内容 package {// See: http://go/android-license-faq// A large-scale-change added default_applicable_licenses to import// all of the license_kinds from "frameworks_a…...

如何升级node.js版本

升级Node.js可以通过多种方式来完成&#xff0c;以下是四种常见的方法&#xff1a; 方法一&#xff1a;使用Node.js官方安装程序 访问Node.js的官方网站&#xff0c;下载对应你操作系统的最新版本安装程序。通常&#xff0c;你可以 https://nodejs.org/en/download 找到你需…...

Excel---一个工作簿中的多个sheet合并成一个PDF

0 Preface/Foreword 1 操作方法 1.1 方法一 文件》 导出 》创建PDF/XPS 》 选项 》发布内容 》“整个工作簿” 1.2 方法二 文件》 打印》 打印机选项中&#xff0c;选择一种PDF阅读器 》设置选项中&#xff0c;选择打印整个工作簿。...

结合文本的目标检测:Open-GroundingDino训练自己的数据集

1、简单介绍 Open-GroundingDino是GroundingDino的第三方实现训练流程的代码&#xff0c;因为官方GroundingDino没有提供训练代码&#xff0c;只提供了demo推理代码。 关于GroundingDino的介绍可以看论文&#xff1a;https://arxiv.org/pdf/2303.05499.pdf GroundingDino的G…...

分布式锁-redission锁的MutiLock原理

5.5 分布式锁-redission锁的MutiLock原理 为了提高redis的可用性&#xff0c;我们会搭建集群或者主从&#xff0c;现在以主从为例 此时我们去写命令&#xff0c;写在主机上&#xff0c; 主机会将数据同步给从机&#xff0c;但是假设在主机还没有来得及把数据写入到从机去的时…...

MySQL索引、B+树相关知识汇总

MySQL索引、B树相关知识汇总 一、有一个查询需求&#xff0c;MySQL中有两个表&#xff0c;一个表1000W数据&#xff0c;另一个表只有几千数据&#xff0c;要做一个关联查询&#xff0c;如何优化&#xff1f;1、为关联字段建立索引二、小表驱动大表 二、b树和b树的区别1、更高的…...

相机模型浅析

相机模型 文章目录 相机模型四个坐标系针孔相机模型世界坐标系到相机坐标系相机坐标系到图像坐标系图像坐标到像素坐标 四个坐标系 ①世界坐标系&#xff1a;是客观三维世界的绝对坐标系&#xff0c;也称客观坐标系。因为数码相机安放在三维空间中&#xff0c;我们需要世界坐标…...

国芯科技(C*Core)双芯片汽车安全气囊解决方案

汽车安全气囊是20世纪汽车上的十大发明之一&#xff0c;是目前汽车的法定标准配置&#xff0c;成为汽车驾乘人员生命安全的保护神。随着人们对汽车安全性要求的进一步提高&#xff0c;已形成前排驾驶员气囊、前排副驾驶员气囊、前排侧气囊、后排侧气囊、膝部气囊、安全气帘等等…...

牛客周赛 Round 39(A,B,C,D,E,F,G)

比赛链接 官方题解&#xff08;视频&#xff09; B题是个贪心。CD用同余最短路&#xff0c;预处理的完全背包&#xff0c;多重背包都能做&#xff0c;比较典型。E是个诈骗&#xff0c;暴力就完事了。F是个线段树。G是个分类大讨论&#xff0c;出题人钦定的本年度最佳最粪 题目…...

解锁区块链技术的潜力:实现智能合约与DApps

在数字时代&#xff0c;区块链技术正迅速成为重塑多个行业的革命性力量。从金融服务到供应链管理&#xff0c;再到数字身份验证&#xff0c;区块链提供了一种去中心化、安全和透明的数据处理方式。在本文中&#xff0c;我们将深入探讨区块链技术&#xff0c;特别是智能合约和去…...

MAC OS关闭SIP(navicat 无法保存密码)

最近安装navicat&#xff08;16.3.7&#xff09;时,安装后无法保存密码,保存密码会报错如下&#xff1a; 因为用的破解版&#xff0c;一开始是打不开的&#xff0c;用自带的修复软件修复后就可以打开了&#xff0c;但是保存密码就会报错&#xff0c;按照网上的一些操作 1、卸载…...

阿里云服务器带宽价格全解析,附报价单

阿里云服务器公网带宽怎么收费&#xff1f;北京地域服务器按固定带宽计费一个月23元/M&#xff0c;按使用流量计费0.8元/GB&#xff0c;云服务器地域不同实际带宽价格也不同&#xff0c;阿里云服务器网aliyunfuwuqi.com分享不同带宽计费模式下带宽收费价格表&#xff1a; 公网…...

Day36|贪心算法part05:435. 无重叠区间、763.划分字母区间、56. 合并区间

435. 无重叠区间 有了上题射气球的因子&#xff0c;这题也就有思路了&#xff0c;反正无脑排序就行了&#xff1a; 首先将所有区间按照end的大小从小到大排序&#xff1b;选取最早end为起始x_end遍历所有区间&#xff0c;如果该区间的start比end大&#xff08;可重叠&#xf…...

棋牌室计时吧台计费收费灯控管理系统软件操作流程

棋牌室计时吧台计费收费灯控管理系统软件操作流程 一、前言 以下软件操作教程以&#xff0c;佳易王棋牌桌球计时计费管理系统软件灯控版V17.87为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 该计时计费软件可以是棋牌和桌球混合同时计时计费 …...

【实践篇】RabbitMQ实现队列延迟功能汇总

前言 记录下RabbitMQ实现延迟队列功能的所有实践内容。 前期准备&#xff0c;需要安装好docker、docker-compose的运行环境。 一、安装RabbitMQ 开启RabbitMQ的WEB管理功能。-CSDN博客 二、实现延迟队列的两种方式 RabbitMQ实现延迟队列的两种方式。-CSDN博客 三、实践文…...

EditPlus来啦(免费使用!)

hello&#xff0c;我是小索奇 今天推荐一款编辑器&#xff0c;是索奇学习JavaSE时入手滴&#xff0c;非常好用哈&#xff0c;小索奇还是通过老杜-杜老师入手滴&#xff0c;相信很多人也是通过老杜认识嘞&#xff0c;来寻找破解版或者准备入手这个间接使用的编辑器~ EditPlus是…...

蓝桥杯22年第十三届省赛-数组切分|线性DP

题目链接&#xff1a; 蓝桥杯2022年第十三届省赛真题-数组切分 - C语言网 (dotcpp.com) 1.数组切分 - 蓝桥云课 (lanqiao.cn) 这道题C语言网数据会强一些。 说明&#xff1a; 对于一个切分的子数组&#xff0c;由于数组是1-N的一个排列&#xff0c;所以每个数唯一 可以用子…...

小米汽车:搅动市场的鲶鱼or价格战砧板上的鱼肉?

3月28日晚&#xff0c;备受关注的小米汽车上市发布会召开&#xff0c;小米集团董事长雷军宣布小米SU7正式发布。小米汽车在带飞股价的同时&#xff0c;二轮订购迅速售尽。 图一&#xff1a;小米集团股价 雷军口中“小米汽车迈出的第一步&#xff0c;也是人生最后一战的开篇”&a…...

网站对公司的重要性/搜索引擎关键词广告

Python提供了一些内建函数用于基本对象类型&#xff1a;cmp&#xff08;&#xff09;&#xff0c;repr()&#xff0c;str&#xff08;&#xff09;&#xff0c;type&#xff08;&#xff09;和等同于repr()的&#xff08; &#xff09;操作符 &#xff08;1&#xff09;type&am…...

物流业网站建设方案实验总结/品牌服务推广

非官方板卡应用非官方板卡也需要在官方提供的历程上进行修改&#xff0c;这样节省时间&#xff0c;而且AD936X的IP也需要参考官方的IP。下载并编译Xilinx u-boot源码选用的U-boot的网站为https://github.com/Xilinx/u-boot-xlnx直接命令git clone https://github.com/Xilinx/u-…...

网络营销平台搭建方案网站/网页广告调词平台多少钱

1. 概述 最近开始学习自定义View&#xff0c;看到现在公司项目上的一个动画效果&#xff0c;顿时想到其实可以自己画&#xff0c;于是就开始着手优&#xff08;zhuang&#xff09;化&#xff08;bi&#xff09;这个动画。 动画如下&#xff1a; 其实很简单对不对&#xff0c;但…...

wordpress写代码插件/优化大师windows

Parkster这个项目正在从单体应用转化到微服务的过程中&#xff0c;已经使用Kubernetes有一段时间了&#xff0c;尚未被移动到Kubernetes应用程序的就是单体应用剩下的部分。将单体应用完全分裂成微服务是一个愿景&#xff0c;在这个过程中&#xff0c;我们从kubernetes提供的调…...

优秀的国外网站/西安抖音seo

需求&#xff1a;客户端界面需要一个软键盘进行操作 做了一个简易的例子进行展示。 html代码&#xff1a; <div id"container"> <div class"print-right"><div id"right-top" class"right-top"><div class&quo…...

广州手机建设网站/郑州网站优化

我的计算机在域中1、通过以下方法打开 Microsoft 管理控制台&#xff1a;选择“开始”按钮 &#xff0c;在搜索框中键入“mmc”&#xff0c;然后按 Enter。如果系统提示你输入管理员密码或进行确认&#xff0c;请键入该密码或进行确认。2、在 Microsoft 管理控制台的左侧窗格中…...