riscv 栈空间静态分析

分析riscv架构的裸机代码中最大栈空间

riscv的基本过程调用标准

1.函数前8个参数用a0~a7传输

2.超过8个的参数使用栈传递

3.函数返回参数到a0,a1寄存器中,返回值保存在ra寄存器中

4.如果子函数有使用s0-s11寄存器,那么在使用前需要将这些寄存器的内容入栈,使用完后再出栈

5.栈向下增长,即向低地址增长

6.如果gcc打开了“-fno-omit-frame-pointer”选项,将使用s0寄存器作为栈帧指针FP

7.栈中保存临时变量,如局部变量等

静态程序栈分析工具

checkstack.pl来自linux源码中用来对栈空间做静态检查的工具,目前也是支持riscv架构的,我们的编译器也是riscv64-linux-gcc,也拿来用了下 ,可以正常输出,关于checkstack.pl的使用方法以及相关描述可以参考如下链接文章

Kernel Small Stacks - eLinux.orgicon-default.png?t=N7T8https://elinux.org/Kernel_Small_Stacks

栈空间静态分析原理

查看checkstack.pl的源代码能够了解对栈空间使用情况分析的原理,如果对perl语法理解有问题,可以借助文心一言,让他帮忙分析。

my (@stack, $re, $dre, $sub, $x, $xs, $funcre, $min_stack);
{my $arch = shift;if ($arch eq "") {$arch = `uname -m`;chomp($arch);}$min_stack = shift;if ($min_stack eq "" || $min_stack !~ /^\d+$/) {$min_stack = 100;}$x	= "[0-9a-f]";	# hex character$xs	= "[0-9a-f ]";	# hex character or space$funcre = qr/^$x* <(.*)>:$/;if ($arch =~ '^(aarch|arm)64$') {#ffffffc0006325cc:       a9bb7bfd        stp     x29, x30, [sp, #-80]!#a110:       d11643ff        sub     sp, sp, #0x590$re = qr/^.*stp.*sp, \#-([0-9]{1,8})\]\!/o;$dre = qr/^.*sub.*sp, sp, #(0x$x{1,8})/o;} elsif ($arch =~ /^riscv(64)?$/) {#ffffffff8036e868:	c2010113          	addi	sp,sp,-992$re = qr/.*addi.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o;} else {print("wrong or unknown architecture \"$arch\"\n");exit}
}

其中$funcre = qr/^$x* <(.*)>:$/;

        $funcre = qr/..../是用于定义一个正则表达式的匹配的语法

        $x* 匹配16进制字符

        <(.*)> 匹配 <xx>尖括号

其中$re = qr/.*addi.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o;

        $re = qr/..../o是用于定义一个正则表达式的匹配的语法

        sp,sp 匹配字符串"sp,sp",表示源和目标操作数都是栈指针(sp)

        addi 汇编指令是RISC-V架构中用于整数加法的指令。

        (([0-9]{2}|[3-9])[0-9]{2}) 这是一个捕获组,用于匹配两位或三位数的立即数,这个数表示栈指针减少的量。

由如上代码可以推测静态分析的原理,例如如下汇编

$funcre匹配汇编中的函数名,$re匹配sp指针调整的指令

函数一开始的时候会先跳到自己的栈帧addi  sp,sp,-16 意思为将sp-16的值保存存到sp中

如上的perl函数记录每个函数占用的栈空间

my ($func, $file, $lastslash, $total_size, $addr, $intro);$total_size = 0;while (my $line = <STDIN>) {if ($line =~ m/$funcre/) {$func = $1;next if $line !~ m/^($xs*)/;if ($total_size > $min_stack) {push @stack, "$intro$total_size\n";}$addr = $1;$addr =~ s/ /0/g;$addr = "0x$addr";$intro = "$addr $func [$file]:";my $padlen = 56 - length($intro);while ($padlen > 0) {$intro .= '	';$padlen -= 8;}$total_size = 0;}elsif ($line =~ m/$re/) {my $size = $1;$size = hex($size) if ($size =~ /^0x/);if ($size > 0xf0000000) {$size = - $size;$size += 0x80000000;$size += 0x80000000;}next if ($size > 0x10000000);$total_size += $size;}
}
if ($total_size > $min_stack) {push @stack, "$intro$total_size\n";
}# Sort output by size (last field)
print sort { ($b =~ /:\t*(\d+)$/)[0] <=> ($a =~ /:\t*(\d+)$/)[0] } @stack;

while 循环的处理每一行汇编代码如果是匹配上$funcre则记录为一个新函数,匹配上$re则累加到当前函数的栈大小$total_size

看起来这个脚本并不统计总使用的的栈的空间最大值,只是当前函数的栈空间

想要统计系统使用的栈的最大空间怎么看

avstack.pl

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

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

相关文章

python并发编程:阻塞IO

阻塞IO&#xff08;blocking IO&#xff09; 在Linux中&#xff0c;默认情况下所有的socket都是blocking&#xff0c;一个典型的读操作流程大概是这样&#xff1a; 当用户进程调用了recvfrom这个系统调用&#xff0c;kernel就开始了IO的第一个阶段&#xff1a;准备数据。对于…

在多文件编译时,如果模板类的成员函数的定义和模板类不在一个文件下会怎么样?

编译器将找不到成员函数的定义&#xff0c;哪怕你将存放成员函数定义的test.cpp一块编译&#xff0c;编译器也无法找到该模板类的成员函数的定义。 正确的做法是&#xff1a; 将模板类的声明和成员函数定义都定义在.h文件下

如何在Linux中安装ARM交叉环境编译链

安装ARM交叉环境编译链过程如下&#xff1a; 首先创建一个文件夹如下&#xff1a; mkdir -p Linux_ALPHA/toolcahin然后将arm交叉编译工具链安装包拖到Linux中如下&#xff1a; 先输入mv 拖入的安装包即可 mv /var/run/vmblock-fuse/blockdir/pXeysK/gcc-4.6.4.tar.xz .直接…

linux命令行或桌面 显卡压力测试

windows下的压力测试非常简单&#xff0c;有很多图形化的测试工具 在github上找到一个项目&#xff1a;github链接 1.下载工具 cd /usr/localgit clone https://github.com/wilicc/gpu-burn如果没有安装git&#xff0c;则先安装 apt-get install git2.安装 cd /usr/local/…

1. Gin框架入门

文章目录 一、Gin框架介绍二、RESTful API三、Gin渲染1. HTML渲染2. 自定义模板函数3. 静态文件处理4. 使用模板继承5. 补充文件路径处理6. JSON渲染7. XML渲染8. YMAL渲染9. protobuf渲染 四、Gin获取各种方式传递过来的参数1、获取querystring参数2、获取form参数3、获取path…

网络学习:Vlan基础知识、划分思路及其优越性

目录 一、VLAN基础知识 二、VLAN的划分方法 1. 基于端口划分的VLAN 2. 基于MAC地址划分VLAN 3. 基于网络层协议划分VLAN 4. 根据IP组播划分VLAN 5. 按策略划分VLAN 6. 按用户定义、非用户授权划分VLAN 三、VLAN的优越性 1. 增加了网络连接的灵活性 2. 控制网络上的广…

老杜Mybatis笔记

https://www.yuque.com/zuihoudewu/java_note/mt2812?singleDoc#《老杜MyBatis--原版》

redis缓存更新策略

更新缓存策略&#xff1a; 对于低一致性需求的业务&#xff1a;使用redis自带的内存淘汰机制就行了&#xff0c;自动失效&#xff0c;等查询时再更新。 对于高一致性需求的业务&#xff1a;推荐主动更新&#xff0c;由缓存的调用者更新数据库的同时更新缓存(删除缓存)。 这里的…

K倍区间 刷题笔记

法一 前缀和暴力搜索 &#xff08;数据大会超时&#xff09; #include<iostream> #include<cstring> #include<algorithm> #include<cstdio> using namespace std; const int N100010; int a[N],s[N]; int n,k; int main(){ cin>>n>>…

Python算法题集_搜索插入位置

Python算法题集_搜索插入位置 题51&#xff1a;搜索插入位置1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【二分法查找】2) 改进版一【二分法查找终止条件判断】3) 改进版二【第三方模块】 4. 最优算法5. 相关资源 本文为Python算法题集之一的…

【海贼王的数据航海:利用数据结构成为数据海洋的霸主】栈和队列

目录 1 -> 栈 1.1 -> 栈的概念及结构 1.2 -> 栈的实现 1.2.1 -> Stack.h 1.2.2 -> Stack.c 1.2.3 -> Test.c 2 -> 队列 2.1 -> 队列的概念及结构 2.2 -> 队列的实现 2.2.1 -> Queue.h 2.2.2 -> Queue.c 1 -> 栈 1.1 -> 栈的…

HTML5+CSS3+JS小实例:灵动的流边开关切换效果

实例:灵动的流边开关切换效果 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, in…