#define SVC_0 0
#define SVC_1 1
#define SVC_2 2
void SVC_Handler(
void )
{
asm("TST LR, #4");
asm("ITE EQ");
asm("MRSEQ R0, MSP");
asm("MRSNE R0, PSP");
asm("B SVC_Handler_main");
}
void Dummy0_Handler( unsigned
int *
svc_args )
{
svc_args[6] +=
4;
// skip Dummy0()
}
void Dummy1_Handler( unsigned
int *
svc_args )
{
svc_args[6] +=
8;
// skip Dummy0(), Dummy1()
}
void Dummy0(
void )
{
}
void Dummy1(
void )
{
}
//
void Dummy2_Handler( unsigned
int *
svc_args )
{
unsigned int a0 = svc_args[
0];
unsigned int a1 = svc_args[
1];
unsigned int a2 = svc_args[
2];
unsigned int a3 = svc_args[
3];
unsigned int a4 = svc_args[
8];
unsigned int a5 = svc_args[
9];
svc_args[0] = ( a0 + a1 + a2 ) * ( a3 + a4 + a5 );
// retValue
svc_args[6] = svc_args[5] - 1; // return to Caller of Dummy2()
}
unsigned int Dummy2( unsigned
int a0, unsigned
int a1, unsigned
int a2,
unsigned int a3, unsigned
int a4, unsigned
int a5 )
{
asm("SVC #2"); // <--- modify first instruct
return ( a0 + a1 + a2 ) * ( a3 + a4 +
a5 );
}
void SVC_Demo(
void )
{
unsigned int a0, a1, a2, a3, a4, a5;
a0 =
0;
a1 =
1;
a2 =
2;
a3 =
3;
a4 =
4;
a5 =
5;
asm("SVC #0"); // Dummy0_handler() : svc_args[6] += 4 Bytes : modifyed PC ( return address )
Dummy0(); // <---- PC, skipped : 0xF7FF 0xFFCA : BL Dummy0
Dummy1();
asm("SVC #1"); // Dummy1_handler() : svc_args[6] += 8 bytes
Dummy0(); // <---- PC, skipped : 0xF7FF 0xFFCA 0xF7FF 0xFFC4
Dummy1();
// <-------- skipped
Dummy2(a0, a1, a2, a3, a4, a5); // Dummy2() : SVC #2 : FIRST INSTRUCTION be patched // Dummy2_Handler() : svc_args[6] = svc_args[5] - 1 : return after caller of dummy2() :: Execute Dummy0()
Dummy0();
Dummy1();
}
//
// a0 a1 a2 a3 | a4 a5
// xSP : R0 R1 R2 R3 R12 R14 PC xPSR | XX XX XX XX XX XX XX XX
// xSP : R0 R1 R2 R3 R12 R14 PC xPSR |
// |svc_args[0] |svc_args[6] --> instruction after SVC XX
// |
// 00 DF|XX XX XX XX <-- instruction will be executed after reti
// -2 -1|0 1 2 3
// |
void SVC_Handler_main( unsigned
int * svc_args )
// R0 = ( PSP or MSP )
{
/*
* Stack contains:
* r0, r1, r2, r3, r12, r14, the return address and xPSR
* First argument (r0) is svc_args[0]
*/
unsigned int svc_number;
svc_number = ((
char *)svc_args[
6])[-
2];
// ( SVC #0 ) 00 DF : XX XX XX XX <-- code will be executed after reti
// ( SVC #1 ) 01 DF : \______________ PC : (char *)svc_args[6])
switch(svc_number)
{
case SVC_0:
Dummy0_Handler( svc_args );
break;
case SVC_1:
Dummy1_Handler( svc_args );
break;
case SVC_2:
Dummy2_Handler( svc_args );
break;
default:
break;
}
}
void SVC_Demo( void )
{
SVC_Demo:
0x20004920: 0xe92d 0x43f0
PUSH.W {R4-R9, LR}
0x20004924: 0xb083
SUB SP, SP, #0xc
a0 = 0;
0
x20004926: 0x2000 MOVS R0, #
0
0x20004928: 0x0004 MOVS R4, R0
a1 = 1;
0
x2000492a: 0x2001 MOVS R0, #
1
0x2000492c: 0x0005 MOVS R5, R0
a2 = 2;
0
x2000492e: 0x2002 MOVS R0, #
2
0x20004930: 0x0006 MOVS R6, R0
a3 = 3;
0
x20004932: 0x2003 MOVS R0, #
3
0x20004934: 0x0007 MOVS R7, R0
a4 = 4;
0
x20004936: 0x2004 MOVS R0, #
4
0x20004938: 0x4680
MOV R8, R0
a5 = 5;
0
x2000493a: 0x2005 MOVS R0, #
5
0x2000493c: 0x4681
MOV R9, R0
asm("SVC #0")
;
0
x2000493e: 0xdf00 SVC #0x0
Dummy0(); // <---- PC, skipped
0
x20004940: 0xf7ff 0xffca BL Dummy0
; 0x200048d8
Dummy1()
;
0
x20004944: 0xf7ff 0xffc9 BL Dummy1
; 0x200048da
asm(
"SVC #1")
;
0
x20004948: 0xdf01 SVC #0x1
Dummy0(); // <---- PC, skipped
0
x2000494a: 0xf7ff 0xffc5 BL Dummy0
; 0x200048d8
Dummy1()
; // <-------- skipped
0
x2000494e: 0xf7ff 0xffc4 BL Dummy1
; 0x200048da
Dummy2(a0, a1, a2, a3, a4, a5)
;
0
x20004952: 0xf8cd 0x9004
STR.W R9, [SP, #0x4]
; a5
0
x20004956: 0xf8cd 0x8000
STR.W R8, [SP]
; a4
0
x2000495a: 0x003b MOVS R3, R7
; a3
0
x2000495c: 0x0032 MOVS R2, R6
; a2
0
x2000495e: 0x0029 MOVS R1, R5
; a1
0
x20004960: 0x0020 MOVS R0, R4
; a0
0
x20004962: 0xf7ff 0xffd1
BL Dummy2 ; 0x20004908 -----------LR=0x20004966+1-----------------------------------------------+
Dummy0()
; ; BL : Branch and Link : LR ---> 0x20004966+1 : BL Dummy0 |
0x20004966: 0xf7ff 0xffb7 BL Dummy0
; 0x200048d8 -------------------------------------------------------------------------+
Dummy1()
; |
0
x2000496a: 0xf7ff 0xffb6 BL Dummy1
; 0x200048da |
} |
0x2000496e: 0xe8bd 0x83f7
POP.W {R0-R2, R4-R9, PC} |
unsigned int Dymmy2( unsigned int a0, unsigned int a1, unsigned int a2, |
unsigned int a3, unsigned int a4, unsigned int a5 ) ; modify first instruction : SVC #2 |
{ |
Dummy2: |
0x20004908: 0xb430 PUSH {R4, R5} ; SP = 0x2000A3C0 : a4 a5 |
0x2000490a: 0x9c02 LDR R4, [SP, #0x8] ; a4 : SP = 0x2000A3B8 + 8 = 0x2000A3C0 |
0x2000490c: 0x9d03 LDR R5, [SP, #0xc] ; a5 : SP = 0x2000A3B8 + C = 0x2000A3C4 |
asm(
"SVC #2")
; ; <--- modify first instruct 0x20004908 to execute Dummy2_Handler() ----------------+
0
x2000490e: 0xdf02
SVC #0x2 ; Force Execute this instruction <TEST> svc_args[6] = svc_args[5] - 1; ; PC = LR - 1 : Dummy2_Handler() last instruction : LR = 0x20004966+1 else execute 0x2000490a after exit SVC_Handler_main() ; because svc_args[6] = 0x2000490a when execute SVC #0x02 old function : first instruction : SVC xx --> execute new function() new function : last insturction : svc_args[6] = svc_args[5] - 1 : return to instruction after BL OLD_FUNCTION
return ( a0 + a1 + a2 ) * ( a3 + a4 + a5 )
; ; SP = 0x2000A3A0 : R0 R1 R2 R3 R12 R14 PC xPSR a4 a5
0
x20004910: 0x1808 ADDS R0, R1, R0 ; skipped
0
x20004912: 0x1810 ADDS R0, R2, R0
0
x20004914: 0x18e1 ADDS R1, R4, R3
0x20004916: 0x1869 ADDS R1, R5, R1
0x20004918: 0x4348 MULS R0, R1, R0
0x2000491a: 0xbc30
POP {R4, R5}
0x2000491c: 0x4770 BX LR
0x2000491e: 0x0000 MOVS R0, R0 ; skipped
SVC_Handler:
0x200048b4: 0xf01e 0x0f04 TST.W LR, #
4 ; SP = 0x2000A3A0 : R0 R1 R2 R3 R12 R14 PC xPSR a4 a5
asm(
"ITE EQ")
;
0
x200048b8: 0xbf0c ITE EQ
asm("MRSEQ R0, MSP")
;
0
x200048ba: 0xf3ef 0x8008 MRSEQ R0, MSP
asm("MRSNE R0, PSP")
;
0
x200048be: 0xf3ef 0x8009 MRSNE R0, PSP
asm("B SVC_Handler_main")
;
0
x200048c2: 0xf000 0xb856 B.W SVC_Handler_main
}
void SVC_Handler_main( unsigned int * svc_args ) // R0 = ( PSP
or MSP )
{
SVC_Handler_main:
0x20004972: 0xb538
PUSH {R3-R5, LR}
; SP = 0x2000A3A0 : R0 R1 R2 R3 R12 R14 PC xPSR a4 a5
0
x20004974: 0x0004 MOVS R4, R0
; SP = 0x2000A390 : R3 R4 R5 LR : R0 R1 R2 R3 R12 R14 PC xPSR a4 a5
svc_number = ((char *)svc_args[
6])[-
2]
; ; R0 = 0x2000A3A0 : ( svc_args )
0
x20004976: 0x69a0 LDR R0, [R4, #0x18]
0x20004978: 0xf810 0x0c02 LDRB.W R0, [R0, #-0x2]
0x2000497c: 0x0005 MOVS R5, R0
switch(svc_number)
0x2000497e: 0x2d00
CMP R5, #
0
0x20004980: 0xd003 BEQ.N ??SVC_Handler_main_0
0x20004982: 0x2d02
CMP R5, #
2
0x20004984: 0xd009 BEQ.N ??SVC_Handler_main_1
0x20004986: 0xd304 BCC.N ??SVC_Handler_main_2
0x20004988: 0xe00b B.N ??SVC_Handler_main_3
SVC_0_Handler( svc_args );
??
SVC_Handler_main_0:
0x2000498a: 0x0020 MOVS R0, R4
0x2000498c: 0xf7ff 0xff9c BL SVC_0_Handler
break;
0
x20004990: 0xe007 B.N ??SVC_Handler_main_3
SVC_1_Handler( svc_args );
??
SVC_Handler_main_2:
0x20004992: 0x0020 MOVS R0, R4
0x20004994: 0xf7ff 0xff9c BL SVC_1_Handler
break;
0
x20004998: 0xe003 B.N ??SVC_Handler_main_3
Dummy2_Handler( svc_args );
??
SVC_Handler_main_1:
0x2000499a: 0x0020 MOVS R0, R4
; R0 = 0x2000A3A0 : ( svc_args )
0
x2000499c: 0xf7ff 0xff9e BL Dummy2_Handler
; 0x200048dc
break
;
0
x200049a0: 0xe7ff B.N ??SVC_Handler_main_3
; 0x200049a2
}
??SVC_Handler_main_3:
??SVC_Handler_main_4:
0x200049a2: 0xbd31
POP {R0, R4, R5, PC}
; PC <-- 0xFFFFFFF9, ( R0 : dont care ), Reti : restore registers
; R0 R1 R2 R3 R12 R14 PC xPSR : restore from stack
void Dummy2_Handler( unsigned
int * svc_args )
; PC be modified : svc_args[6] = svc_args[5]-1
{
Dummy2_Handler: ; SP(Dummy2.Entry) -------------------------------------------|
0
x200048dc: 0xb4f0
PUSH {R4-R7}
; R0 = 0x2000A3A0 ----------------| |
unsigned
int a0 = svc_args[
0]
; ; SP = 0x2000A390 : R3 R4 R5 LR : R0 R1 R2 R3 R12 R14 PC xPSR a4 a5
0
x200048de: 0x6801 LDR R1, [R0]
; SP = 0x2000A380 : R4 R5 R6 R7 : R3 R4 R5 LR : R0 R1 R2 R3 R12 R14 PC xPSR a4 a5
unsigned
int a1 = svc_args[
1]
; ; svc_args[0] : R0
0
x200048e0: 0x6842 LDR R2, [R0, #0x4]
; svc_args[1] : R1
unsigned
int a2 = svc_args[
2]
; ; svc_args[8] : a4
0
x200048e2: 0x6883 LDR R3, [R0, #0x8]
; svc_args[9] : a5 0x20004962 : BL Dummy2
unsigned
int a3 = svc_args[
3]
; ; svc_args[5] : LR : 0x20004966+1 : BL Dummy0 -------+
0
x200048e4: 0x68c4 LDR R4, [R0, #0xc]
; |
unsigned
int a4 = svc_args[
8]
; ; 0x2000490E : SVC #2 |
0
x200048e6: 0x6a05 LDR R5, [R0, #0x20]
; svc_args[6] : PC : 0x20004910 : XXXXXX |
unsigned
int a5 = svc_args[
9]
; ; svc_args[6] = svc_args[5]-1 -----------------------+
0
x200048e8: 0x6a46 LDR R6, [R0, #0x24]
;
svc_args[
0] = ( a0 + a1 + a2 ) * ( a3 + a4 + a5 )
; ; svc_args[0] = result
0
x200048ea: 0x1857 ADDS R7, R2, R1
0x200048ec: 0x19df ADDS R7, R3, R7
0x200048ee: 0xeb15 0x0c04 ADDS.W R12, R5, R4
0x200048f2: 0xeb16 0x0c0c ADDS.W R12, R6, R12
0x200048f6: 0xfb0c 0xf707
MUL R7, R12, R7
0x200048fa: 0x6007
STR R7, [R0]
svc_args[6] = svc_args[
5] -
1; ; svc_args[6] = svc_args[5]-1
0
x200048fc: 0x6947 LDR R7, [R0, #0x14]
; return to Caller of Dummy2() after exit SVC_Handler_main()
0
x200048fe: 0x1e7f SUBS R7, R7, #
1 ;
0
x20004900: 0x6187
STR R7, [R0, #0x18]
;
}
0x20004902: 0xbcf0
POP {R4-R7}
;
0
x20004904: 0x4770
BX LR ; return to SVC_Handler_main()|
0
x20004906: 0x0000 MOVS R0, R0
; |
0
x2000499c: 0xf7ff 0xff9e BL Dummy2_Handler
; 0x200048dc |
break
; ; |
0
x200049a0: 0xe7ff B.N ??SVC_Handler_main_3
; 0x200049a2 <----------------+
}
??SVC_Handler_main_3:
??SVC_Handler_main_4: ; PC be modified : svc_args[6] = svc_args[5]-1
0
x200049a2: 0xbd31
POP {R0, R4, R5, PC}
; return to Caller of Dummy2()|
; PC <-- 0xFFFFFFF9 |
0
x20004962: 0xf7ff 0xffd1 BL Dummy2
; |
Dummy0()
; ; |
0
x20004966: 0xf7ff 0xffb7 BL Dummy0
; 0x200048d8 <----------------+
Dummy1()
; ;
0
x2000496a: 0xf7ff 0xffb6 BL Dummy1
; 0x200048da
}
0x2000496e: 0xe8bd 0x83f7
POP.W {R0-R2, R4-R9, PC}
; return to caller of SVC_Demo()
转载于:https://www.cnblogs.com/shangdawei/archive/2013/05/01/3052696.html
相关资源:SVC的开源代码JSVM