開發環境:android studio 3.3
調試工具:IDA7.0
so代碼:
#include <jni.h>
#include <string>
#include <stdlib.h>
#include <stdio.h>
int GetSum(int a1,int a2) {
int sum = a1+a2;
return sum;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
char s[12];
memset(s,0, sizeof(s));
int sum = GetSum(2,5);
sprintf(s,"%d",sum);
return env->NewStringUTF(s);
}
arm彙編:
libnative_lib.so:AEE46872 LDR R4, [R4] ; __stack_chk_guard
libnative_lib.so:AEE46874 LDR.W R12, [R4]
libnative_lib.so:AEE46878 STR.W R12, [SP,#0x34]
libnative_lib.so:AEE4687C STR R0, [SP,#0x24]
libnative_lib.so:AEE4687E STR R1, [SP,#0x20]
libnative_lib.so:AEE46880 MOVS R0, #0
libnative_lib.so:AEE46882 STR R0, [SP,#0x2C]
libnative_lib.so:AEE46884 STR R0, [SP,#0x28]
libnative_lib.so:AEE46886 STR R0, [SP,#0x30]
//arm傳遞參數是使用固定寄存器r0-r3 超過使用堆棧方式傳入
//與x86彙編不一樣,x86使用的是push 傳遞參數。
libnative_lib.so:AEE46888 MOVS R0, #2 ////傳入參數1爲常量2
libnative_lib.so:AEE4688A MOVS R1, #5 //傳入參數2爲常量5
libnative_lib.so:AEE4688C STR R3, [SP,#0x18]
libnative_lib.so:AEE4688E STR R4, [SP,#0x14]
libnative_lib.so:AEE46890 STR R2, [SP,#0x10]
libnative_lib.so:AEE46892 BLX unk_AEE46764 //調用GetSum 方法
libnative_lib.so:AEE46896 STR R0, [SP,#0x1C] //R0返回值爲7
libnative_lib.so:AEE46898 LDR R2, [SP,#0x1C]
GetSum方法:
libnative_lib.so:AEE46848 ; =============== S U B R O U T I N E =======================================
libnative_lib.so:AEE46848
libnative_lib.so:AEE46848
libnative_lib.so:AEE46848 _Z6GetSumii
libnative_lib.so:AEE46848
libnative_lib.so:AEE46848 var_14= -0x14
libnative_lib.so:AEE46848 var_10= -0x10
libnative_lib.so:AEE46848 var_C= -0xC
libnative_lib.so:AEE46848 var_8= -8
libnative_lib.so:AEE46848 var_4= -4
libnative_lib.so:AEE46848
libnative_lib.so:AEE46848 SUB SP, SP, #0x14 ; CODE XREF: sub_AEE46764+8↑j
libnative_lib.so:AEE46848 libnative_lib.so:off_AEE49FD0↓o
libnative_lib.so:AEE4684A MOV R2, R1
libnative_lib.so:AEE4684C MOV R3, R0
libnative_lib.so:AEE4684E STR R0, [SP,#0x14+var_4] //參數1值存入[SP,#0x14+var_4]中
libnative_lib.so:AEE46850 STR R1, [SP,#0x14+var_8]//參數2值存入[SP,#0x14+var_8]中
libnative_lib.so:AEE46852 LDR R0, [SP,#0x14+var_4]//[SP,#0x14+var_4]的值載入到寄存器R0中 值爲2
libnative_lib.so:AEE46854 LDR R1, [SP,#0x14+var_8]//[SP,#0x14+var_8]的值載入到寄存器R1中 值爲5
libnative_lib.so:AEE46856 ADD R0, R1 //R0+R1 = 7
libnative_lib.so:AEE46858 STR R0, [SP,#0x14+var_C]
libnative_lib.so:AEE4685A LDR R0, [SP,#0x14+var_C] //作爲返回值存入R0中
libnative_lib.so:AEE4685C STR R2, [SP,#0x14+var_10]
libnative_lib.so:AEE4685E STR R3, [SP,#0x14+var_14]
libnative_lib.so:AEE46860 ADD SP, SP, #0x14
libnative_lib.so:AEE46862 BX LR
libnative_lib.so:AEE46862 ; End of function _Z6GetSumii
指令解釋
R0-R3:用於函數參數及返回值的傳遞
R4-R6, R8, R10-R11: 普通的通用寄存器
R7:棧幀指針(Frame Pointer).指向前一個保存的棧幀(stack frame)和鏈接寄存器(link register, lr)在棧上的地址。
R9:操作系統保留
R12:IP(intra-procedure scratch )
R13:SP(stack pointer),是棧頂指針
R14:LR(link register),存放函數的返回地址。
R15:PC(program counter),指向當前指令地址
IDA動態調試 ,單步跟蹤的時候,右邊的能看到每個寄存器的值。
ADD 加指令
SUB 減指令
STR 把寄存器內容存到棧上去
LDR 把棧上內容載入一寄存器中
BL 執行函數調用,並把使lr指向調用者(caller)的下一條指令,即函數的返回地址
BLX 同上,但是在ARM和thumb指令集間切換。
CMP 指令進行比較兩個操作數的大小
LDR R0, [SP,#0x14+var_4] //在例子中sp的地址值是BE9A3894 =
R0= [BE9A3894 +0x14-4]= BE9A38A4 = 2