• 关于ARM中的adrp与adr指令


    adrp指令

    一般adrp指令使用来取变量的,经常和add或者ldr指令配合使用。
    下面这条指令一般用于将变量地址存入寄存器中

    • adrp指令计算过程:4就是对应变量所在的页面相对于当前页面的页偏移(1页是4kb),当前页基地址=PC地址低12位置0,所以对应变量所在页的基地址为=当前页基地址 + 页偏移*0x1000 = 0x10002000+0x4000 = 0x10006000
    • add指令得到对应变量的偏移地址 = adrp获取的变量页面基地址+ 对应变量的页内偏移= 0x10006000+0xF87 = 0x10006F87
    0x10002345 adrp x8,#0x4
    0x10002349 add  x8,x8,0xF87
    
    

    下面的代码是ndk实现的一个JNI接口函数,定义一个全局变量num,JNI接口函数会访问此全局变量。

    jint num = 1;
    extern "C" JNIEXPORT jstring JNICALL
    stringFromJNI(JNIEnv* env, jobject /* this */) {
    
        num = 2;
        std::string hello = "Hello from C++";
        return env->NewStringUTF(hello.c_str());
    }
    

    将编译生成的so文件拖进IDA里查看,这里的代码实际是IDA为了自动分析处理过的。#0x34000就是对应变量所在页面基地址(IDA自动分析的,算法和上面我们的算法一致)。
    adrp x8,#0x34000实际对应的原始指令应该为adrp x8,#0x25。为什么呢?因为adrp处的PC地址为0x0000F15C, 所以当前页面的基地址为0x0000F000(低12位置0)。(变量页面基地址 - 当前页面基地址)/0x1000 = (0x34000 - 0xF000)/0x1000 = 对应的页偏移 =0x25

    实际IDA会进一步优化将其直接显示为如下形式。

    我们进一步分析,变量页面基地址为0x34000, 页内偏移为0xFD8,所以对应的变量地址为 0x34FD8.
    IDA中查看Section发现其在got表中,而got表此0x34FD8存放的是真实num全局变量的地址,会在链接器加载程序时重定位修复。

    我们进一步在so加载到内存中看一下,发现IDA同样会自动分析。
    我们再来计算一下,原始指令为adrp x8,#0x25,0x25就是对应变量所在的页面相对于当前页面的页偏移(1页是4kb),当前页基地址=PC地址低12位置0,所以对应变量所在页的基地址为=当前页基地址 + 页偏移*0x1000 = 0x0000007694A90000+0x25000 = 0x0x0000007694Ab5000也就是IDA自动分析出来的那个。

    adr和adrl指令

    adr是小范围的地址读取指令,adrl是中等范围的地址读取指令。都是将基于当前PC的相对偏移地址值读取到目标寄存器中。
    下面这条指令就是将相对与当前PC:0x10002000地址偏移0x432的地址 = 0x10002432这个地址放入x1寄存器中。

    0x10002000 adr x1,0x432
    

    一般在IDA中其都会自动分析成对应的地址,例如下面的这个实际指令应该是adrl x1,#0x1923F

  • 相关阅读:
    【Maven】项目打包-war包-Jar包[IDEA将项目打成war包]
    intellij idea 配置web 项目
    centos7启动iptables时报Job for iptables.service failed because the control process exited with error cod
    shell-运算符
    shell-流程控制
    shell-流程控制
    shell-变量,字符串,数组,注释,参数传递
    shell-变量,字符串,数组,注释,参数传递
    json解析
    json解析
  • 原文地址:https://www.cnblogs.com/revercc/p/16173503.html
Copyright © 2020-2023  润新知