SVCを使用してコードを修正する
40207 ワード
#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; 0x20004926: 0x2000 MOVS R0, #0 0x20004928: 0x0004 MOVS R4, R0 a1 = 1; 0x2000492a: 0x2001 MOVS R0, #1 0x2000492c: 0x0005 MOVS R5, R0 a2 = 2; 0x2000492e: 0x2002 MOVS R0, #2 0x20004930: 0x0006 MOVS R6, R0 a3 = 3; 0x20004932: 0x2003 MOVS R0, #3 0x20004934: 0x0007 MOVS R7, R0 a4 = 4; 0x20004936: 0x2004 MOVS R0, #4 0x20004938: 0x4680 MOV R8, R0 a5 = 5; 0x2000493a: 0x2005 MOVS R0, #5 0x2000493c: 0x4681 MOV R9, R0
asm("SVC #0");
0x2000493e: 0xdf00 SVC #0x0
Dummy0(); // <---- PC, skipped
0x20004940: 0xf7ff 0xffca BL Dummy0 ; 0x200048d8
Dummy1();
0x20004944: 0xf7ff 0xffc9 BL Dummy1 ; 0x200048da
asm("SVC #1");
0x20004948: 0xdf01 SVC #0x1
Dummy0(); // <---- PC, skipped
0x2000494a: 0xf7ff 0xffc5 BL Dummy0 ; 0x200048d8
Dummy1(); // <-------- skipped
0x2000494e: 0xf7ff 0xffc4 BL Dummy1 ; 0x200048da
Dummy2(a0, a1, a2, a3, a4, a5);
0x20004952: 0xf8cd 0x9004 STR.W R9, [SP, #0x4] ; a5
0x20004956: 0xf8cd 0x8000 STR.W R8, [SP] ; a4
0x2000495a: 0x003b MOVS R3, R7 ; a3
0x2000495c: 0x0032 MOVS R2, R6 ; a2
0x2000495e: 0x0029 MOVS R1, R5 ; a1
0x20004960: 0x0020 MOVS R0, R4 ; a0
0x20004962: 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(); |
0x2000496a: 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() ----------------+
0x2000490e: 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
0x20004910: 0x1808 ADDS R0, R1, R0 ; skipped
0x20004912: 0x1810 ADDS R0, R2, R0
0x20004914: 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");
0x200048b8: 0xbf0c ITE EQ
asm("MRSEQ R0, MSP");
0x200048ba: 0xf3ef 0x8008 MRSEQ R0, MSP
asm("MRSNE R0, PSP");
0x200048be: 0xf3ef 0x8009 MRSNE R0, PSP
asm("B SVC_Handler_main");
0x200048c2: 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
0x20004974: 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 )
0x20004976: 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;
0x20004990: 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;
0x20004998: 0xe003 B.N ??SVC_Handler_main_3
Dummy2_Handler( svc_args );
??SVC_Handler_main_1: 0x2000499a: 0x0020 MOVS R0, R4 ; R0 = 0x2000A3A0 : ( svc_args )
0x2000499c: 0xf7ff 0xff9e BL Dummy2_Handler ; 0x200048dc
break;
0x200049a0: 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) -------------------------------------------|
0x200048dc: 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
0x200048de: 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
0x200048e0: 0x6842 LDR R2, [R0, #0x4] ; svc_args[1] : R1
unsigned int a2 = svc_args[2]; ; svc_args[8] : a4
0x200048e2: 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 -------+
0x200048e4: 0x68c4 LDR R4, [R0, #0xc] ; |
unsigned int a4 = svc_args[8]; ; 0x2000490E : SVC #2 |
0x200048e6: 0x6a05 LDR R5, [R0, #0x20] ; svc_args[6] : PC : 0x20004910 : XXXXXX |
unsigned int a5 = svc_args[9]; ; svc_args[6] = svc_args[5]-1 -----------------------+
0x200048e8: 0x6a46 LDR R6, [R0, #0x24] ;
svc_args[0] = ( a0 + a1 + a2 ) * ( a3 + a4 + a5 ); ; svc_args[0] = result
0x200048ea: 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
0x200048fc: 0x6947 LDR R7, [R0, #0x14] ; return to Caller of Dummy2() after exit SVC_Handler_main()
0x200048fe: 0x1e7f SUBS R7, R7, #1 ;
0x20004900: 0x6187 STR R7, [R0, #0x18] ;
}
0x20004902: 0xbcf0 POP {R4-R7} ;
0x20004904: 0x4770 BX LR ; return to SVC_Handler_main()|
0x20004906: 0x0000 MOVS R0, R0 ; |
0x2000499c: 0xf7ff 0xff9e BL Dummy2_Handler ; 0x200048dc |
break; ; |
0x200049a0: 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
0x200049a2: 0xbd31 POP {R0, R4, R5, PC} ; return to Caller of Dummy2()|
; PC <-- 0xFFFFFFF9 |
0x20004962: 0xf7ff 0xffd1 BL Dummy2 ; |
Dummy0(); ; |
0x20004966: 0xf7ff 0xffb7 BL Dummy0 ; 0x200048d8 <----------------+
Dummy1(); ;
0x2000496a: 0xf7ff 0xffb6 BL Dummy1 ; 0x200048da
}
0x2000496e: 0xe8bd 0x83f7 POP.W {R0-R2, R4-R9, PC} ; return to caller of SVC_Demo()