函数返回值:arm64 规定了整数型返回值放在 x0 寄存器里

sp(栈空间)字节对齐:该临时变量占用 4字节空间;又因为 arm64 下对于使用 sp 作为地址基址寻址的时候,必须要 16byte-alignment(对齐),所以申请了 16字节空间作为临时变量使用。具体参见 这里

指令模式

Thumbe 或 Arm32 或 Arm64

在一段代码的开头有 .CODE16 CODE32 CODE64

IDA 中按 ALT+G 选择 T (T是虚拟寄存器,当值手动赋值为1表示是 Thumbe 指令解析模式, 0 则是 ARM指令解析模式)

svc 0 和 swi 0 指令

分析 __bionic_clone.S ,在 libc.so 中

arm32:

源码

/bionic/libc/arch-arm/bionic/__bionic_clone.S

    # Make the system call.
ldr r7, =__NR_clone
swi #

/bionic/libc/kernel/uapi/asm-arm/asm/unistd.h

#define __NR_SYSCALL_BASE
#define __NR_clone (__NR_SYSCALL_BASE + ) //=0x78

指令

/system/lib/libc.so

.text:0001712C LDR R7, =0x78    //0x78=__NR_clone
.text: SVC

svc 指令机器码(小端):00 00 00 EF

‭1110 1111 0000 0000 0000000000000000‬

根据最后的附录的表的倒数第二个

swi 指令的 0~31位 中的 4~7位为 1111,从机器码角度可以看到  SWI 指令 就是 SVC指令

源码 swi > svc

R7 向内核传递系统调用号

arm64:

源码:

/bionic/libc/arch-arm64/bionic/__bionic_clone.S

    # Make the system call.
mov x8, __NR_clone
svc #

/bionic/libc/kernel/uapi/asm-arm64/asm/unistd.h

#include <asm-generic/unistd.h>

转去看

/bionic/libc/kernel/uapi/asm-generic/unistd.h

#define __NR_clone      //=0xDC

指令

/system/lib64/libc.so

.text:000000000001B9A4 MOV X8, #0xDC          //0xDC = __NR_clone
.text:000000000001B9A8 SVC 

svc 指令机器码(小端):01 00 00 D4

网上没有找到ARM64 的 二进制机器码 格式表格所以,而ARM64的二进制机器码发生了改变。。。。

所以看起来是同一个指令

源码 svc -> svc

x8 用于向内核传递系统调用号

svc的 thumb,arm32,arm64 的格式都不太一样

svc指令官方手册:

Supervisor call to allow application code to call the OS. It generates an exception targeting exception level 1 (EL1). (生成一个异常级别1 的异常)

Supervisor Call causes an exception to be taken to EL1.

Arm®v8架构定义了四个异常级别,从EL0到EL3,其中EL3是最高的异常级别,具有最多的执行特权。在接受异常时,异常级别可以增加或保持不变,而从异常返回时,异常级别可以减少或保持不变。

EL0  Applications. 应用

EL1  OS kernels and associated functions that are typically described as privileged. 系统内核

EL2  Hypervisor. (硬件辅助虚拟化。arm目前采用的是硬件辅助虚拟化的方式,即在处理器模式上增加了el2级别,将hypervisor运行在el2上。将hypervisor与VM kernel运行在不同的模式下,VM运行在一个受控模式,hypervisor可以配置哪些敏感指令是否触发异常。总的来说目的是为了捕获敏感指令以触发异常。  https://blog.csdn.net/zgy666/article/details/79238646

EL3  Secure monitor.

arm32指令机器码表格:

Thumb SVC 指令

 

系统调用号如何获取?用哪个寄存器?

官方文档:

问题:

为什么我们看到 arm32下,使用 svc 指令陷入内核调用 __NR_clone 的参数是用 R7 传递 而不是 R0~R3 ? arm官方推荐R0-R3 ,但Linux内核实现用的是R7 ,X8 ?对吗

从 swi 陷入内核看起,调用swi 指令后,cpu会产生一个中断信号,因为是swi指令产生的,所以会将pc赋值为 中断向量表基地址 + 0x8

此处有一条跳转指令

这张表定义在 /arch/arm/kernel/entry-armv.S

...
1131 .equ stubs_offset, __vectors_start + 0x200 - __stubs_start
1133 .globl __vectors_start
1134__vectors_start:
ARM( swi SYS_ERROR0 )
THUMB( svc # ) //一个表项32位,一条thumb指令16位,所以第一个表项 用了2个 thumb沾满了32位,第一个指令是 svc 0 ,第二个是 nop,用于cpu复位后调用
THUMB( nop )
W(b) vector_und + stubs_offset
W(ldr) pc, .LCvswi + stubs_offset //这里是我们关注的 swi 的中断向量跳转 指令 = ldr pc, .LCvswi + stubs_offset
W(b) vector_pabt + stubs_offset
W(b) vector_dabt + stubs_offset
W(b) vector_addrexcptn + stubs_offset
W(b) vector_irq + stubs_offset
W(b) vector_fiq + stubs_offset .globl __vectors_end
1147__vectors_end:
...
.LCvswi:
.word vector_swi

/arch/arm/kernel/entry-common.S

353ENTRY(vector_swi)
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Calling r0 - r12
ARM( add r8, sp, #S_PC )
ARM( stmdb r8, {sp, lr}^ ) @ Calling sp, lr
THUMB( mov r8, sp )
THUMB( store_user_sp_lr r8, r10, S_SP ) @ calling sp, lr
mrs r8, spsr @ called from non-FIQ mode, so ok.
str lr, [sp, #S_PC] @ Save calling PC
str r8, [sp, #S_PSR] @ Save CPSR
str r0, [sp, #S_OLD_R0] @ Save OLD_R0
zero_fp /*
* Get the system call number. 获取系统调用号
*/ #if defined(CONFIG_OABI_COMPAT) /*
* If we have CONFIG_OABI_COMPAT then we need to look at the swi
* value to determine if it is an EABI or an old ABI call.
*/
#ifdef CONFIG_ARM_THUMB
tst r8, #PSR_T_BIT
movne r10, # @ no thumb OABI emulation
ldreq r10, [lr, #-] @ get SWI instruction
#else
ldr r10, [lr, #-] @ get SWI instruction
A710( and ip, r10, #0x0f000000 @ check for SWI )
A710( teq ip, #0x0f000000 )
A710( bne .Larm710bug )
#endif
#ifdef CONFIG_CPU_ENDIAN_BE8
rev r10, r10 @ little endian instruction
#endif #elif defined(CONFIG_AEABI) /*
* Pure EABI user space always put syscall number into scno (r7).
*/
A710( ldr ip, [lr, #-] @ get SWI instruction )
A710( and ip, ip, #0x0f000000 @ check for SWI )
A710( teq ip, #0x0f000000 )
A710( bne .Larm710bug ) #elif defined(CONFIG_ARM_THUMB) /* Legacy ABI only, possibly thumb mode. */
tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in
ldreq scno, [lr, #-] #else /* Legacy ABI only. */
ldr scno, [lr, #-] @ get SWI instruction
A710( and ip, scno, #0x0f000000 @ check for SWI )
A710( teq ip, #0x0f000000 )
A710( bne .Larm710bug ) #endif #ifdef CONFIG_ALIGNMENT_TRAP
ldr ip, __cr_alignment
ldr ip, [ip]
mcr p15, , ip, c1, c0 @ update control register
#endif
enable_irq get_thread_info tsk
adr tbl, sys_call_table @ load syscall table pointer #if defined(CONFIG_OABI_COMPAT)
/*
* If the swi argument is zero, this is an EABI call and we do nothing.
*
* If this is an old ABI call, get the syscall number into scno and
* get the old ABI syscall table address.
*/
bics r10, r10, #0xff000000
eorne scno, r10, #__NR_OABI_SYSCALL_BASE
ldrne tbl, =sys_oabi_call_table
#elif !defined(CONFIG_AEABI)
bic scno, scno, #0xff000000 @ mask off SWI op-code
eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
#endif ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing
stmdb sp!, {r4, r5} @ push fifth and sixth args #ifdef CONFIG_SECCOMP
tst r10, #_TIF_SECCOMP
beq 1f
mov r0, scno
bl __secure_computing
add r0, sp, #S_R0 + S_OFF @ pointer to regs
ldmia r0, {r0 - r3} @ have to reload r0 - r3
:
#endif tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls?
bne __sys_trace cmp scno, #NR_syscalls @ check upper syscall limit
adr lr, BSYM(ret_fast_syscall) @ return address
ldrcc pc, [tbl, scno, lsl #] @ call sys_* routine add r1, sp, #S_OFF
: mov why, # @ no longer a real syscall
cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back
bcs arm_syscall
b sys_ni_syscall @ not private func
468ENDPROC(vector_swi)

if def 的嵌套:

//1.
//现场保护:保存寄存器到内存

//2.
//从swi 指令的立即数处获取系统调用号
#if defined(CONFIG_OABI_COMPAT)
    #ifdef CONFIG_ARM_THUMB
    #else
    #end

    #ifdef CONFIG_CPU_ENDIAN_BE8
    #end
#elif defined(CONFIG_AEABI)
#elif defined(CONFIG_ARM_THUMB)
#else
  //遗留ABI
#end

。。。

//3.

//获取系统调用表基地址 到 tbl(r8)

adr tbl, sys_call_table @ load syscall table pointer
。。。

//4.
//如果 swi 指令的立即数是0,那么表示是EABI调用。
//如果是旧ABI调用,则从scno 获取系统调用号,并获得旧ABI系统调用表的地址
//scno 是什么? r7寄存器别称,纯EABI用户空间总是将syscall号放入scno (r7)。 SystemCallNO
#if defined(CONFIG_OABI_COMPAT)
#elif !defined(CONFIG_AEABI)
#endif

。。。

//5.

ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
。。。

.type sys_call_table, #object
ENTRY(sys_call_table)
#include "calls.S"

tbl,scno 等定义在文件

/arch/arm/kernel/entry-header.S

/*
* These are the registers used in the syscall handler, and allow us to
* have in theory up to arguments to a function - r0 to r6. 允许携带7个参数给方法 r0~r6
*
* r7 is reserved for the system call number for thumb mode. r7 是在thumb模式下的保留的系统调用号寄存器
*
。。。 */
176scno .req r7 @ syscall number
177tbl .req r8 @ syscall table pointer
178why .req r8 @ Linux syscall (!= )
179tsk .req r9 @ current thread_info
 

杂项记录 arm64 的一些特性的更多相关文章

  1. JAVA记录-Spring两大特性

    1.IOC控制反转 Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象 ...

  2. android 启动流程 相关 杂项记录

    Android原生流程 Init进程 主要流程及分支梳理 ueventd_main()watchdogd_main()主要流程a) 公共部分 增加PATH 环境变量初始化内核日志,打开/dev/kms ...

  3. JAVA记录 Spring 两大特性

    1.IOC控制反转 Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象 ...

  4. Berkeley DB的数据存储结构——哈希表(Hash Table)、B树(BTree)、队列(Queue)、记录号(Recno)

    Berkeley DB的数据存储结构 BDB支持四种数据存储结构及相应算法,官方称为访问方法(Access Method),分别是哈希表(Hash Table).B树(BTree).队列(Queue) ...

  5. Python的一些高级特性以及反序列化漏洞

    0x01 简述 文章主要记录一下python高级特性以及安全相关的问题 python作为脚本语言,其作为高级语言是由c语言开发的,关于python的编译和链接可以看向这里https://github. ...

  6. 分布式监控系统Zabbix-3.0.3-完整安装记录(0)

    一.Linux下开源监控系统简单介绍1)cacti:存储数据能力强,报警性能差2)nagios:报警性能差,存储数据仅有简单的一段可以判断是否在合理范围内的数据长度,储存在内存中.比如,连续采样数据存 ...

  7. linux 备忘记录

    杂项记录 Ubuntu 通过/etc/network/interfaces修改IP,重启网络服务貌似也不会生效.可以重启电脑使其生效,或执行: ip addr flush dev ens33 & ...

  8. Java 14 有哪些新特性?

    记录为 Java 提供了一种正确实现数据类的能力,不再需要为实现数据类而编写冗长的代码.下面就来看看 Java 14 中的记录有哪些新特性. 作者 | Nathan Esquenazi 译者 | 弯月 ...

  9. Phoenix踩坑填坑记录

    Phoenix踩坑填坑记录 Phoenix建表语句 如何添加二级索引 判断某表是否存在 判断索引是否存在 Date类型日期,条件判断 杂项 记录Phoenix开发过程中的填坑记录. 部分原文地址:ph ...

随机推荐

  1. selenium时间等待方法

    在UI自动化测试中,必然会遇到环境不稳定.网络慢等情况.当你觉得定位没有问题,但程序却直接报了元素不可见时,那你就需要思考是否因为程序运行太快或者页面加载太慢而造成了元素不可见,必须要再等待直至元素可 ...

  2. Linux-3.14.12内存管理笔记【建立内核页表(1)】

    前面已经分析过了Intel的内存映射和linux的基本使用情况,已知head_32.S仅是建立临时页表,内核还是要建立内核页表,做到全面映射的.下面就基于RAM大于896MB,而小于4GB ,切CON ...

  3. 算法问题实战策略 CHILDRENDAY

    地址 https://algospot.com/judge/problem/read/CHILDRENDAY 题解 ac代码 #include <iostream> #include &l ...

  4. for(var i in items) 和 for(var i;i<items.length;i++) 区别

    前者循环的是属性,后者循环的才是数组. 若项目中对数组属性进行了扩展,那切记不能使用前者,否则在循环数组时扩展的函数体也会被当做数据返回. var data = { p1:1, p2:"b& ...

  5. 基础知识 Asp.Net MVC EF各版本区别

    原文:https://www.cnblogs.com/liangxiaofeng/p/5840754.html 2009年發行ASP.NET MVC 1.0版 2010年發行ASP.NET MVC 2 ...

  6. golang+vscode开发环境的搭建

    一.windows下安装golang开发环境 (1)配置GOROOT变量,在系统变量中点击新建,变量值是golang安装文件夹目录 (2)配置Path变量,选中Path点编辑即可,在变量值后面追加;% ...

  7. DFS(四):剪枝策略

    顾名思义,剪枝就是通过一些判断,剪掉搜索树上不必要的子树.在采用DFS算法搜索时,有时候我们会发现某个结点对应的子树的状态都不是我们要的结果,这时候我们没必要对这个分支进行搜索,砍掉这个子树,就是剪枝 ...

  8. Eclipse引入自定义XML约束文件(DTD,SCHEMA)问题

    Eclipse引入自定义XML约束文件(DTD,SCHEMA)问题 1:说明 使用Eclipse 编写xml文件的约束文件的,包括DTD约束文件,Schema约束文件的时候, 我们也需要接受eclip ...

  9. Python中字符的编码与解码

    1 文本和字节序列 我们都知道字符串,就是由一些字符组成的序列构成串,那么字符又是什么呢?计算机只能识别二进制的东西,那么计算机又为什么会显示我们的汉字,或者是某个字母呢? 由于最早发明使用计算机是美 ...

  10. python爬取昵称并保存为csv

    代码: import sys import io import re sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030') ...