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()