﻿ 代码 or 指令，浅析ARM架构下的函数的调用过程_其他_开心洋葱网
• 欢迎访问开心洋葱网站，在线教程，推荐使用最新版火狐浏览器和Chrome浏览器访问本网站，欢迎加入开心洋葱` QQ群`
• 为方便开心洋葱网用户，开心洋葱官网已经开启复制功能！
• 欢迎访问开心洋葱网站，手机也能访问哦~欢迎加入开心洋葱多维思维学习平台` QQ群`
• 如果您觉得本站非常有看点，那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~！
• 由于近期流量激增，小站的ECS没能经的起亲们的访问，本站依然没有盈利，如果各位看如果觉着文字不错，还请看官给小站打个赏~~~~~~~~~~~~~！

# 代码 or 指令，浅析ARM架构下的函数的调用过程

2440次浏览

## 1、背景知识

### 2、STP指令详解（ARMV8手册）：

Pseudocode如下：

```Shared decode for all encodings
integer n = UInt(Rn);
integer t = UInt(Rt);
integer t2 = UInt(Rt2);
if L:opc<0> == '01' || opc == '11' then UNDEFINED;
integer scale = 2 + UInt(opc<1>);
integer datasize = 8 << scale;
bits(64) offset = LSL(SignExtend(imm7, 64), scale);
boolean tag_checked = wback || n != 31;
Operation for all encodings
bits(datasize) data1;
bits(datasize) data2;
constant integer dbytes = datasize DIV 8;
boolean rt_unknown = FALSE;
if HaveMTEExt() then
SetNotTagCheckedInstruction(!tag_checked);
if wback && (t == n || t2 == n) && n != 31 then
Constraint c = ConstrainUnpredictable();
assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
case c of
when Constraint_NONE rt_unknown = FALSE; // value stored is pre-writeback
when Constraint_UNKNOWN rt_unknown = TRUE; // value stored is UNKNOWN
when Constraint_UNDEF UNDEFINED;
when Constraint_NOP EndOfInstruction();
if n == 31 then
CheckSPAlignment();
else
if !postindex then
if rt_unknown && t == n then
data1 = bits(datasize) UNKNOWN;
else
data1 = X[t];
if rt_unknown && t2 == n then
data2 = bits(datasize) UNKNOWN;
else
data2 = X[t2];
if wback then
if postindex then
if n == 31 then
else

## 2、一个例子

C代码如下：

`main\f3\f4\strlen`

`main\f3\f4\strlen`

```(gdb) x/2i f3
0x400600 <f3>: stp   x29, x30, [sp,#-48]!
0x400604 <f3+4>:      mov x29, sp```

```(gdb) x/gx 0xfffffffff2c0+8
0xfffffffff2c8:    0x000000000040065c
(gdb) x/i 0x000000000040065c
0x40065c <f4+36>:    mov w0, #0x0                       // #0
frame2的函数为sp+8：0x000000000040065c -> <f4+36>```

```(gdb) x/2i f4
0x400638 <f4>: stp   x29, x30, [sp,#-48]!
0x40063c <f4+4>:      mov x29, sp```

```frame2的函数为0xfffffffff2c0 + 8：0x000000000040065c -> <f4+36>
(gdb) x/gx 0xfffffffff2f0+8
0xfffffffff2f8:    0x0000000000400684
(gdb) x/i 0x0000000000400684
0x400684 <main+28>:       mov w0, #0x0                       // #0```

• 当前的现场
• 熟悉cpu体系架构的开栈的方式

## 3、实战讲解

```(gdb) bt
#0  0x0000ffffaeb067bc in ?? () from /lib64/libc.so.6
Backtrace stopped: previous frame inner to this frame (corrupt stack?)```

pc代表当前执行的函数指令，如果当前指令未开栈，一般情况x30代表上一级的frame调用当前函数的下一条指令，查看汇编，可以反解为如下函数

```(gdb) x/i 0xaaaacd3de4fc
0xaaaacd3de4fc <PGXCNodeConnStr(char const*, int, char const*, char const*, char const*, char const*, int, char const*)+108>: mov x27, x0```

```(gdb) x/6i PGXCNodeConnStr
0xaaaacd3de490 <PGXCNodeConnStr(char const*, int, char const*, char const*, char const*, char const*, int, char const*)>: sub  sp, sp, #0xd0
0xaaaacd3de494 <PGXCNodeConnStr(char const*, int, char const*, char const*, char const*, char const*, int, char const*)+4>:      stp   x29, x30, [sp,#80]
0xaaaacd3de498 <PGXCNodeConnStr(char const*, int, char const*, char const*, char const*, char const*, int, char const*)+8>:      add  x29, sp, #0x50```

```(gdb) x/i 0x0000aaaacd414e08
0xaaaacd414e08 <build_node_conn_str(Oid, DatabasePool*)+224>:     mov x21, x0```

```(gdb) x/4i build_node_conn_str
0xaaaacd414d28 <build_node_conn_str(Oid, DatabasePool*)>:     stp   x29, x30, [sp,#-176]!
0xaaaacd414d2c <build_node_conn_str(Oid, DatabasePool*)+4>: mov x29, sp```

```(gdb) x/8i reload_database_pools
0xaaaacd4225e8 <reload_database_pools(PoolAgent*)>:       sub   sp, sp, #0x1c0
0xaaaacd422600 <reload_database_pools(PoolAgent*)+24>:         stp   x29, x30, [sp,#-96]!```

TIPS：arm架构下一般调用都会使用这种指令，

stp x29, x30, [sp,#immediate]! 有叹号或者无叹号