部分gcc预定义宏和函数栈帧的内存分布
创始人
2024-02-20 19:24:44

本文简单基于树莓派8,linux4.4.50版本,32位arm cpu
尝试了解函数调用栈的内存分布的形态。使用gcc内置的宏 __builtin_frame_address 来打印栈帧内存上的信息,以及了解一下常用的gcc 内置的宏的输出。
针对 __builtin_frame_address 在gcc官网上可以看到更多的说明:
https://gcc.gnu.org/onlinedocs/gcc/extensions-to-the-c-language-family/getting-the-return-or-frame-address-of-a-function.html

1 预定义宏的输出

#include int call_func1(){printf("\n %s \n",__func__);printf("__func__ %s\n",__func__);printf("__LINE__ %d\n",__LINE__);printf("__FILE__ %s\n",__FILE__);printf("__DATE__ %s\n",__DATE__);printf("__time__ %s\n",__TIME__);printf("__func__ %s __builtin_frame_address %p\n",__func__,__builtin_frame_address(0));printf("__func__ %s,__builtin_return_address %p\n",__func__,__builtin_return_address(0));
}int main(){call_func1();return 0;
}

上述源文件的输出如下:

call_func1
__func__ call_func1 //函数名
__LINE__ 51         //行号
__FILE__ main.c     //源文件名
__DATE__ Nov 27 2022    //编译日期
__time__ 17:58:17           //编译时间
__func__ call_func1 __builtin_frame_address 0x7ec541a4
__func__ call_func1,__builtin_return_address 0x10794

__builtin_frame_address 表示函数的栈帧地址,__builtin_return_address表示函数的返回地址。

2 栈帧的内存打印

以如下形式的程序调用为例

#include int call_func2(int parm, int parm2){int i = 10;int j = 0;void * offset = NULL;printf("\n %s \n",__func__);/*打印从函数的栈帧开始 10个cpu地址(32位)的地址和值*/for (j = 0 ; j < i; j++){offset = __builtin_frame_address(0)- j*sizeof(int*);printf("__builtin_frame_address %p value [%x]\n",offset,*(int*)offset);}/*打印函数的返回地址 ,3个变量的地址,两个入参的地址*/printf("__builtin_return_address %p\n",__builtin_return_address(0));printf("first variable i  %p\n",&i);printf("second variable j  %p\n",&j);printf("third variable j  %p\n",&offset);printf("first parm parm   %p\n",&parm);printf("second parm parm   %p\n",&parm2);return 0;
}int call_func1(){printf("__func__ %s __builtin_frame_address %p\n",__func__,__builtin_frame_address(0));printf("__func__ %s,__builtin_return_address %p\n",__func__,__builtin_return_address(0));call_func2();return 0;
}int main(){call_func1();return 0;
}

上述的程序的调用流程是 main->call_func1->call_func2 。其中call_func1打印了函数的栈帧地址和返回地址,call_func2先后打印了其以帧地址为开始之后10个4字节内存的地址和内容,然后打印了函数的返回地址 ,3个变量的内存地址,两个入参的内存地址
其输出结果如下:

__func__ call_func1 __builtin_frame_address 0x7e8041a4
__func__ call_func1,__builtin_return_address 0x10810call_func2
__builtin_frame_address 0x7e985194 value [0x107cc]
__builtin_frame_address 0x7e985190 value [0x7e9851a4]
__builtin_frame_address 0x7e98518c value [0x10810]
__builtin_frame_address 0x7e985188 value [0x10a4c]
__builtin_frame_address 0x7e985184 value [0xa]
__builtin_frame_address 0x7e985180 value [0x5]
__builtin_frame_address 0x7e98517c value [0x7e98517c]
__builtin_frame_address 0x7e985178 value [0x76ffa000]
__builtin_frame_address 0x7e985174 value [0x4]
__builtin_frame_address 0x7e985170 value [0x1]
__builtin_return_address 0x107cc
first variable i  0x7e804184
second variable j  0x7e804180
third variable j  0x7e80417c
first parm parm   0x7e804174
second parm parm   0x7e804170

以内存地址的形式呈现,可以得到如下图:

在这里插入图片描述

栈帧的开始位置,其内容是是 0x107cc ,是函数的返回地址。即__builtin_return_address(0),下一个32位的内容是0x7e8041a4 ,根据其返回函数的打印,是返回后函数的栈帧开始位置。可以印证 栈是向下增长的,返回地址的栈在更高的地址。再下一个32位的内容是,0x10810,是其返回函数的返回地址。

再接下来一个32位的内容为空,或是任意值,该值可能为预留,使用gdb也未寻找到符号位置。

接下来三个32位均为栈上的变量的地址,i j 和offset。

再下一个值的内容为随机,其含义也不明。该32位可能也为预留值。

接下来两个地址为函数调用的局部变量的地址,parm和parm2

如果有更多的入参调用,会发现预留给参数变量的栈帧大小大约是 4*32 ,如果超过该范围,就会预先先进行调用参数的内存分配,再执行函数的栈上内存分配。即地址会在0x7e985194 栈帧地址之前。
在这种情况下,如果形参进行了越界的修改,就会导致栈帧上的返回地址被破坏,导致出现崩溃。该点可后续继续实验。

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...