编译器如何处理函数的调用

共 2445字,需浏览 5分钟

 ·

2024-05-22 07:33


        


概要

网上对函数调用未做系统化分析,本文主要根据汇编,寄存器,堆栈,map,内存4个角度进行分析,在函数进行调用的时候,编译器做什么工作进行举例分析;

环境介绍

函数流程如下:
1)串口输入指令;
2)中断调用接口uint16_t getUartData(void);
3)getUartData 中调用了shell_cmd_parse接口;从开始调用shell_cmd_parse进行讲解,即下图断电位置;

步骤

断点位置(2800行),寄存器分析如下:

1)寄存器

由于示例采用的是多进程方式,调用getUartData前的接口可能是任何一个函数,故【R0-R12】寄存器的值不确定,上图【R0-R12】值无特别意义;

SP为当前堆栈地址0x20008948

LR为调用getUartData前地址,查询.map文件可知,getUartData运行完成返回parseIni接口

PC为当前程序运行地址0x801B3BC,查看.map文件可知为当前函数getUartData里面某个位置(图1中打印断电的地方)

观察Diassembly窗口,程序即将运行的两步

MOV r1,r4 r4getUartData函数中存放局部变量debug_rcv_len=0x8E)赋值给r1


LDR r0,[PC,#116]    PC+116地址中的值给到r0,其中最终结果为0x801B434,对应PC=0x801B3C0,比指令LDR r0,[PC,#116]PC2,原因时流水线的问题(3级流水线导致,取值和运行同时进行会导致计算的时候PC已经+2);

    注:地址0x801B343存的就是全局变量debugUartRcvData的值,查询.map可知,该值在代码中RO数据段;查询Memory1可知其具体的值为0x20017EE0

单步Step(F11)进入函数shell_cmd_parse,进入后如下图所示

变化的值有四个[R0][R1][LR][PC]

[R0]:变为函数shell_cmd_parse(unsigned char *puc_buf, uint16_t us_len)形参puc_buf(=0x20017EE0);

[R1]:形参us_len=0x8E

[LR]:执行完shell_cmd_parse后需要返回的地址,为图1断点处地址(0x801B3BC+8=0x801B3C5

[PC]:0x08029A18,查询.map可知,在函数shell_cmd_parse开头

3)查看Disassembly窗口,如下图所示

1、现场保护:

保护LR,即将函数执行完的后需要返回的地址0x801B3C5,如下图,即代码执行完shell_cmd_parse后下一行代码memset(debugUartRcvData,0,sizeof(debugUartRcvData))位置;

保护R4-R11寄存器中的值,这些值为调用shell_cmd_parse的函数getUartData需要保护的值,譬如R4存放了getUartData局部变量debug_rcv_len的值;

2、堆栈向下偏移由0x20008948-偏移4*r4-r11lr9=0x2008924


查询堆栈数据,Memory1

0x20008948-0x20008924依次存放LR=0x0801B3C5R11=0xA5A5A5A5, R10=0xA5A5A5A5, R9=0xA5A5A5A5, R8=0xA5A5A5A5, R7=0xA5A5A5A5, R6=0xA5A5A5A5, R5=0x00000000, R4=0x0000008E,

3、将r0,r1(函数shell_cmd_parse的形参,puc_buf,us_len的值共2)保存到寄存器r7r8中。

4、为shell_cmd_parse分配堆栈大小

5、查看分配后堆栈,一次性分配好0xA4=164=40*4+4,分配了40char*[](即指针数组,共40char*指针)+一个地址的空间(endstart存放在了r4寄存器里面,剩下的放到堆栈里面);

6、局部变量及堆栈使用情况如下图

7、堆栈溢出底层原理,当指令输出长度过长,pac_argv发生越界访问时,可通过查询堆栈发现,数据对原本保护的数据,譬如LR指针发生变化,导致出现hard fault程序跑飞现象;



春招已经开始啦,大家如果不做好充足准备的话,春招很难找到好工作。


送大家一份就业大礼包,大家可以突击一下春招,找个好工作!


浏览 62
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报