Article count:1086 Read by:1552441

Account Entry

How does the stack change when a C language function is called in ARM?

Latest update time:2020-02-22
    Reads:


Why write an article about stack changes? When doing system analysis, you must have encountered some tricky problems such as crashes and oops. Generally, everyone will use tools such as gdb, objdump or addr2line to analyze the PC position to locate the error. However, the essential principles behind these analysis tools may not be deeply understood, and sometimes you are confused when facing a series of backtraces or stack logs.


Today, let’s take a look at how to use the stack to analyze the causes and consequences of changes in crash logs.


Introduction to Arm instruction set

We advocate a simple and rough introduction method. Let's directly look at the general usage of each register. The detailed usage can be found on Baidu, no, Google.
1. r0-r3 are used as parameters for incoming functions and return values ​​for outgoing functions. Between subroutine calls, r0-r3 can be used for any purpose. The called function does not have to restore r0-r3 before returning. ---If the calling function needs to use the contents of r0-r3 again, it must preserve them.
2. r4-r11 are used to store the local variables of the function. If the called function uses these registers, it must restore the values ​​of these registers before returning. r11 is the stack frame pointer fp .
3. r12 is the intra-call temporary register ip . It is used for this role in procedure link veneers (e.g., interoperation veneers). Between procedure calls, it can be used for any purpose. The called function does not have to restore r12 before returning.
4. Register r13 is the stack pointer sp . It cannot be used for any other purpose. The value stored in sp must be the same when exiting the called function as when entering.
5. Register r14 is the link register lr . If you save the return address, you can use r14 for other purposes between calls and restore it when the program returns.
6. Register r15 is the program counter pc . It cannot be used for any other purpose.

Demo Code

If you have mastered the use of arm instructions, it doesn't matter if you haven't mastered it yet. "You can always look back when you need it." Here is a simple C language example:
#include <stdio.h>
int m = 8;int fun(int a,int b){ int c = 0; c = a + b; return c;}int main(){ int i = 4; int j = 5; m = fun(i, j); return 0;}

Compile and then disassemble:

$ arm-linux-gnueabi-gcc main.c -o main
$ arm-linux-gnueabi-objdump -D -D main
00010400 <fun>:   10400:       e52db004        push    {fp}            ; (str fp, [sp, #-4]!)   10404:       e28db000        add     fp, sp, #0   10408:       e24dd014        sub     sp, sp, #20   1040c:       e50b0010        str     r0, [fp, #-16]   10410:       e50b1014        str     r1, [fp, #-20]  ; 0xffffffec   10414:       e3a03000        mov     r3, #0   10418:       e50b3008        str     r3, [fp, #-8]   1041c:       e51b2010        ldr     r2, [fp, #-16]   10420:       e51b3014        ldr     r3, [fp, #-20]  ; 0xffffffec   10424:       e0823003        add     r3, r2, r3   10428:       e50b3008        str     r3, [fp, #-8]   1042c:       e51b3008        ldr     r3, [fp, #-8]   10430:       e1a00003        mov     r0, r3   10434:       e24bd000        sub     sp, fp, #0   10438:       e49db004        pop     {fp}            ; (ldr fp, [sp], #4)   1043c:       e12fff1e        bx      lr
00010440 <main>: 10440: e92d4800 push {fp, lr} 10444: e28db004 add fp, sp, #4 10448: e24dd008 sub sp, sp, #8 1044c: e3a03004 mov r3, #4 10450: e50b300c str r3, [fp, #-12] 10454: e3a03005 mov r3, #5 10458: e50b3008 str r3, [fp, #-8] 1045c: e51b1008 ldr r1, [fp, #-8] 10460: e51b000c ldr r0, [fp, #-12] 10464: ebffffe5 bl 10400 <fun> 10468: e1a02000 mov r2, r0 1046c: e59f3010 ldr r3, [pc, #16] ; 10484 <main+0x44> 10470: e5832000 str r2, [r3] 10474: e3a03000 mov r3, #0 10478: e1a00003 mov r0, r3 1047c: e24bd004 sub sp, fp, #4 10480: e8bd8800 pop {fp, pc} 10484: 00021024 andeq r1, r2, r4, lsr #32


The changing process of the diagram stack

How can readers absorb faster? I always think that in terms of learning efficiency, the order should be video, pictures, and text. Anyway, I prefer video teaching. Here I will draw a picture of the stack change process. The picture here is drawn in combination with the above code, I hope it will help readers understand.

1. Program distribution area in memory




2. Assignment of global variable m



3. Save the bottom of the stack before entering main, and the current function stack is between fp-sp




4. The stack of function main is ready



5. i is pushed into the stack



6.j pushes into the stack




7. Prepare to call the function fun, push the parameters in reverse order, and push parameter b first



8. Parameter a is pushed onto the stack



9. Leave an address blank as the return value of fun and fill it in later when it returns



10. The return address of fun is pushed onto the stack, usually the next address of the current pc pointer of the main function



11. The bottom address of the main function is pushed onto the stack



12. PC pointer jumps to fun code



13.c Push to stack



14. You can see that the data parameters a and b of the function fun are in the stack of the previous function. Some are on their own stack. This step takes the value to the adder for addition and then assigns it to c.



15.c is assigned to the return value and fills in the blank position above



16. Restore the previous layer from the bottom of the stack



17. lr is assigned to pc, realizing the jump



18. The return value is assigned to the global variable m



19. The parameters of the previous function call are no longer useful, roll back sp



20. Function returns, clean up main's stack space



Summarize

Are you confused by so many pictures? I believe you have understood the ins and outs behind the stack. In the next article, we will analyze the possibility of errors based on actual stack error cases.



Add Geek Assistant WeChat and join the technical exchange group

Long press, scan the code, and follow the official account

 
EEWorld WeChat Subscription

 
EEWorld WeChat Service Number

 
AutoDevelopers

About Us Customer Service Contact Information Datasheet Sitemap LatestNews

Room 1530, Zhongguancun MOOC Times Building,Block B, 18 Zhongguancun Street, Haidian District,Beijing, China Tel:(010)82350740 Postcode:100190

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号