Arm64/aarch64 stack overflow栈溢出Debug 总结

文章通过无限递归的C语言代码示例解释了栈溢出的情况,并指出在AARCH64架构中,x18寄存器通常作为栈限制地址指示器。当SP超过x18时,发生栈溢出。文章强调了使用addr2line工具进行调试的局限性,并推荐使用GDB进行更深入的分析。此外,还介绍了ARM64的32个通用寄存器及其用途,特别是与栈管理相关的寄存器如SP、FP和x18。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一,无限递归demo

二,大道至简

附加arm64 32个寄存器介绍


闲来无事,扣个指甲。

通常情况下,正常的工程里很难遇到栈溢出的案例。栈溢出情况可能有多种,这里列举无限递归的demo。

一,无限递归demo

#include <pthread.h> 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define STACK_SIZE 64

void *thread_func(void *arg) {
  static int i = 0;
  i++;
  printf("thread recursion level: %d\n", i);

  thread_func(NULL);

  return NULL;
}

int main() {
  pthread_attr_t attr;
  pthread_t tid;

  pthread_attr_init(&attr);
  pthread_attr_setstacksize(&attr, STACK_SIZE);
  pthread_create(&tid, &attr, thread_func, NULL);
  pthread_join(tid, NULL);

  return 0;
}

运行会有著名的segment fault:

 结果显示在递归到261902次的时候,发生了栈溢出。

如果万一你的工程里遇到了,该怎么去分析呢?addr2line ?能解决?addr2line 最多带你到11行的代码,然后呢?

二,大道至简

看似复杂实则非常的简单。

跳到第0栈,即事故现场帧,注意这里的 sp 和 x18 即可:

x29            0xffffbed4c010
sp             0xffffbed4c010
x18            0xffffbed4c6d2

 明显能看到sp < x18. 妥妥的栈溢出。

这里核心点在于,x18 一般是特殊寄存器,保存的是栈限制地址。

上学的时候就知道,栈的地址是向下生长的,如下(盗图)。

这里sp 已经增长超过了栈限制地址了,即:栈溢出。

其他情况,差不多也是如此,比如访问变量地址超出了栈空间。重点关注X29,SP 和X18.

再举第2个例子:

#include <stdio.h>

void function() {
  int arr[10] = {0,1,2,3,4,5,6,7,8,9};
  printf("%s,stackoverflow,arr[14]:%p\n",__func__,arr+14);
  arr[14] = 0; 
}

int main() {

  function();

  return 0;
}

这里是栈上变量溢出,也是数组越界。

 数组地址破了fp:

-exec  info regis x18 x29 sp
x18            0xffffffffee0c
x29            0xffffffffef50
sp             0xffffffffef50
-exec  p /x &arr
$1 = 0xffffffffef60
-exec  p /x &arr[14]
$2 = 0xffffffffef98

终端显示:

function,stackoverflow,arr[14]:0xffffffffef98
Segmentation fault

大道至简,3个关键点:

1,aarch64/arm64 x18 栈限制寄存器

2,栈的生长方向是递减的

3,fp,sp 寄存器

备注下:Arm, 即32位的寄存器行为和用途有些许不一样.

附加arm64 32个寄存器介绍

引用自(原地址)

ARM64提供了32个通用寄存器,其用途如下表:

x0~x7:传递子程序的参数和返回值,使用时不需要保存,多余的参数用堆栈传递,64位的返回结果保存在x0中。
x8:用于保存子程序的返回地址,使用时不需要保存。
x9~x15:临时寄存器,也叫可变寄存器,子程序使用时不需要保存。
x16~x17:子程序内部调用寄存器(IPx),使用时不需要保存,尽量不要使用。
x18:平台寄存器,它的使用与平台相关,尽量不要使用。
x19~x28:临时寄存器,子程序使用时必须保存。
x29:帧指针寄存器(FP),用于连接栈帧,使用时必须保存。[这里需要修正,不完全这样]
x30:链接寄存器(LR),用于保存子程序的返回地址。
x31:堆栈指针寄存器(SP),用于指向每个函数的栈顶。

编译工具:极力推荐GDB 调试。VSCode只是看起来好看,实际上没有gdb 方便。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值