zoukankan      html  css  js  c++  java
  • 杂项记录 arm64 的一些特性

    函数返回值: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

    48    # Make the system call.
    49    ldr     r7, =__NR_clone
    50    swi     #0

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

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

    指令

    /system/lib/libc.so

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

    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

    37    # Make the system call.
    38    mov     x8, __NR_clone
    39    svc     #0

    /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 220     //220=0xDC

    指令

    /system/lib64/libc.so

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

    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: 1135 ARM( swi SYS_ERROR0 )
    1136 THUMB( svc #0 ) //一个表项32位,一条thumb指令16位,所以第一个表项 用了2个 thumb沾满了32位,第一个指令是 svc 0 ,第二个是 nop,用于cpu复位后调用 1137 THUMB( nop ) 1138 W(b) vector_und + stubs_offset 1139 W(ldr) pc, .LCvswi + stubs_offset //这里是我们关注的 swi 的中断向量跳转 指令 = ldr pc, .LCvswi + stubs_offset 1140 W(b) vector_pabt + stubs_offset 1141 W(b) vector_dabt + stubs_offset 1142 W(b) vector_addrexcptn + stubs_offset 1143 W(b) vector_irq + stubs_offset 1144 W(b) vector_fiq + stubs_offset
    1145 1146 .globl __vectors_end 1147__vectors_end:
    ...
    1125.LCvswi:
    1126    .word    vector_swi

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

    353ENTRY(vector_swi)
    354    sub    sp, sp, #S_FRAME_SIZE
    355    stmia    sp, {r0 - r12}            @ Calling r0 - r12
    356 ARM(    add    r8, sp, #S_PC        )
    357 ARM(    stmdb    r8, {sp, lr}^        )    @ Calling sp, lr
    358 THUMB(    mov    r8, sp            )
    359 THUMB(    store_user_sp_lr r8, r10, S_SP    )    @ calling sp, lr
    360    mrs    r8, spsr            @ called from non-FIQ mode, so ok.
    361    str    lr, [sp, #S_PC]            @ Save calling PC
    362    str    r8, [sp, #S_PSR]        @ Save CPSR
    363    str    r0, [sp, #S_OLD_R0]        @ Save OLD_R0
    364    zero_fp
    365
    366    /*
    367     * Get the system call number.      获取系统调用号
    368     */
    369
    370#if defined(CONFIG_OABI_COMPAT)
    371
    372    /*
    373     * If we have CONFIG_OABI_COMPAT then we need to look at the swi
    374     * value to determine if it is an EABI or an old ABI call.
    375     */
    376#ifdef CONFIG_ARM_THUMB
    377    tst    r8, #PSR_T_BIT
    378    movne    r10, #0                @ no thumb OABI emulation
    379    ldreq    r10, [lr, #-4]            @ get SWI instruction
    380#else
    381    ldr    r10, [lr, #-4]            @ get SWI instruction
    382  A710(    and    ip, r10, #0x0f000000        @ check for SWI        )
    383  A710(    teq    ip, #0x0f000000                        )
    384  A710(    bne    .Larm710bug                        )
    385#endif
    386#ifdef CONFIG_CPU_ENDIAN_BE8
    387    rev    r10, r10            @ little endian instruction
    388#endif
    389
    390#elif defined(CONFIG_AEABI)
    391
    392    /*
    393     * Pure EABI user space always put syscall number into scno (r7).
    394     */
    395  A710(    ldr    ip, [lr, #-4]            @ get SWI instruction    )
    396  A710(    and    ip, ip, #0x0f000000        @ check for SWI        )
    397  A710(    teq    ip, #0x0f000000                        )
    398  A710(    bne    .Larm710bug                        )
    399
    400#elif defined(CONFIG_ARM_THUMB)
    401
    402    /* Legacy ABI only, possibly thumb mode. */
    403    tst    r8, #PSR_T_BIT            @ this is SPSR from save_user_regs
    404    addne    scno, r7, #__NR_SYSCALL_BASE    @ put OS number in
    405    ldreq    scno, [lr, #-4]
    406
    407#else
    408
    409    /* Legacy ABI only. */
    410    ldr    scno, [lr, #-4]            @ get SWI instruction
    411  A710(    and    ip, scno, #0x0f000000        @ check for SWI        )
    412  A710(    teq    ip, #0x0f000000                        )
    413  A710(    bne    .Larm710bug                        )
    414
    415#endif
    416
    417#ifdef CONFIG_ALIGNMENT_TRAP
    418    ldr    ip, __cr_alignment
    419    ldr    ip, [ip]
    420    mcr    p15, 0, ip, c1, c0        @ update control register
    421#endif
    422    enable_irq
    423
    424    get_thread_info tsk
    425    adr    tbl, sys_call_table        @ load syscall table pointer
    426
    427#if defined(CONFIG_OABI_COMPAT)
    428    /*
    429     * If the swi argument is zero, this is an EABI call and we do nothing.
    430     *
    431     * If this is an old ABI call, get the syscall number into scno and
    432     * get the old ABI syscall table address.
    433     */
    434    bics    r10, r10, #0xff000000
    435    eorne    scno, r10, #__NR_OABI_SYSCALL_BASE
    436    ldrne    tbl, =sys_oabi_call_table
    437#elif !defined(CONFIG_AEABI)
    438    bic    scno, scno, #0xff000000        @ mask off SWI op-code
    439    eor    scno, scno, #__NR_SYSCALL_BASE    @ check OS number
    440#endif
    441
    442    ldr    r10, [tsk, #TI_FLAGS]        @ check for syscall tracing
    443    stmdb    sp!, {r4, r5}            @ push fifth and sixth args
    444
    445#ifdef CONFIG_SECCOMP
    446    tst    r10, #_TIF_SECCOMP
    447    beq    1f
    448    mov    r0, scno
    449    bl    __secure_computing
    450    add    r0, sp, #S_R0 + S_OFF        @ pointer to regs
    451    ldmia    r0, {r0 - r3}            @ have to reload r0 - r3
    4521:
    453#endif
    454
    455    tst    r10, #_TIF_SYSCALL_WORK        @ are we tracing syscalls?
    456    bne    __sys_trace
    457
    458    cmp    scno, #NR_syscalls        @ check upper syscall limit
    459    adr    lr, BSYM(ret_fast_syscall)    @ return address
    460    ldrcc    pc, [tbl, scno, lsl #2]        @ call sys_* routine
    461
    462    add    r1, sp, #S_OFF
    4632:    mov    why, #0                @ no longer a real syscall
    464    cmp    scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
    465    eor    r0, scno, #__NR_SYSCALL_BASE    @ put OS number back
    466    bcs    arm_syscall
    467    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

    166/*
    167 * These are the registers used in the syscall handler, and allow us to
    168 * have in theory up to 7 arguments to a function - r0 to r6.    允许携带7个参数给方法  r0~r6
    169 *
    170 * r7 is reserved for the system call number for thumb mode.      r7 是在thumb模式下的保留的系统调用号寄存器
    171 *
    。。。175 */
    176scno    .req    r7        @ syscall number
    177tbl    .req    r8        @ syscall table pointer
    178why    .req    r8        @ Linux syscall (!= 0)
    179tsk    .req    r9        @ current thread_info
     
  • 相关阅读:
    项目分析时找不到函数调用只有16进制数
    firebase消息推送配置
    布局错乱到原点的问题
    人脸识别部分文章地址笔记
    查看奔溃分析
    iOS App 后台任务的坑(奔溃原因分析)
    轨迹优化
    X SqlServer 事务日志传输 【将备份目录设置到辅助服务器】
    X sql server2014 发布与订阅的配置方法介绍包括【推送订阅】与【请求订阅】
    X SQL SERVER 使用订阅发布同步数据库 【推送订阅】
  • 原文地址:https://www.cnblogs.com/cyy12/p/11601224.html
Copyright © 2011-2022 走看看