Stack을 뒤져 보고, Back tracing도 해보기
( Thumb mode의 Full Descending Stack )
N _ R0 FFFE R8 0
Z Z R1 0 R9 0
C C R2 5074 R10 0
V _ R3 1E6C1A35 R11 0
I _ R4 0 R12 0
F _ R5 0 R13 1F6E92C8
T T R6 FFFF R14 1E6C1A1D
J _ R7 1F6E943C PC 1E6C19BC
usr SPSR CPSR 60000030
Q _
A _ USR: FIQ:
E _ R8 0 R8 0
R9 0 R9 C5400100
0 _ R10 0 R10 1F62C9F0
1 _ R11 0 R11 F00898F0
2 _ R12 0 R12 DD
3 _ R13 1F6E92C8 R13 1
R14 1E6C1A1D R14 F0008BFC
SPSR 10
SVC: IRQ:
R13 E000A880 R13 F008CD00
R14 F0000000 R14 1DB55BF8
SPSR 60000010 SPSR 60000010
UND: ABT:
R13 60000010 R13 00100000
R14 1DB55BF8 R14 1EFCE4BE
SPSR 60000010 SPSR 20000030
CPSR > User Mode
Thumb mode // CPSR의 T 비트 확인
0x6000 0030 == 0110 0000 0000 0000 0000 0011 0000
T 비트 : CPSR[5] // 1 :thumb mode
IRQ, FIQ는 enable // 0 : enable
I 비트 (Interrupt Disable): CPSR[7]
F 비트 (Fast Interrupt Disable): CPSR[6]
현재 PC값 : 0x1E6C19BC
addr/line__|code_____|label____|mnemonic________________|comment________
|
|word b_funct(word arg, word param)
3958|{
ST:1E6C19B8|B570 b_funct: push {r4-r6,r14}
ST:1E6C19BA|B0B2 sub sp,#0xC8
| int loop;
3960| word ret = 0;
ST:1E6C19BC|2400 mov r4,#0x0
| word array[100];
|
3963| for (loop=0; loop < 100; loop++)
ST:1E6C19BE|2200 mov r2,#0x0
ST:1E6C19C0|466E cpy r6,r13
| {
3965| if (loop%2)
ST:1E6C19C2|07D3 lsl r3,r2,#0x1F ; r3,loop,#31
ST:1E6C19C4|D002 beq 0x1E6C19CC
3966| array[loop] = arg;
word b_funct (word arg, word param) 이라는 함수를 실행하던 중..
> 그러면, 이 함수를 부른 녀석은?
> Register값들을 Stack에 Push했는지 확인 후 R13 (Stack Pointer)확인
ST:1E6C19B8|B570 b_funct: push {r4-r6,r14}
ST:1E6C19BA|B0B2 sub sp,#0xC8
b_funct()에 진입> r4~r6, r14 push
sub sp-0xc8 를 한 이유??
( local variable을 stack에 넣음 )
b_funct()함수
local variable로 word array[100]을 잡아 놓음
// word : 4byte > 400byte 크기
> stack에 이 array를 임시로 잡기 위해 > 0xc8 (십진수로 200)을 예약
stack pointer : r4~r6, r14를 push > 200개의 자리를 더 잡아 놓음
stack pointer : r4~r6, r14를 push > 200개의 자리를 더 잡아 놓음 > 더 작은 주소로 Stack이 자라남
> stack pointer의 주소를 빼면,, 400 - 200 == 200 만큼의 공간 더 생김 (낮은 주소로 향하는)
SP값 : (r13) + 200을 해주면 찾을 수 있음
0x1F6E92C8 + 0xC8의 메모리 상태..
d.dump 0x1F6E92C8+0xC8 = 0x1F6E9390 (r14의 값)
___address__|________0________4________8________C_0123456789ABCDEF
SD:1F6E9390|>00000000 00000000 0000FFFF 1E6C1A1D ..............l.
SD:1F6E93A0| 00000000 1E6C1A59 00005074 1C87DE49 ....Y.l.tP..I...
SD:1F6E93B0| 1F6E93C8 1F42F291 00000000 00000000 ..n...B.........
"
"
SD:1F6E94F0| 1F6E9370 1F6E936C 00000001 1F6E9410 p.n.l.n.......n.
SD:1F6E9500| 1F6E939C 1F6E9368 00000000 00000001 ..n.h.n.........
___address__|________0________4________8________C_0123456789ABCDEF
SD:1F6E9390|>00000000 00000000 0000FFFF 1E6C1A1D ..............l.
r4 r5 r6 r14
요렇게 되겠네요. 0x1E6C1A1D : r14 의 값
// sp : 1F6E9390 주소에 R14가 담겨있는데 그 값은 1E6C1A1D ( 라는 주소 가 담겨있음 )
// stack pointer : 현재 위치의 주소를 담고있는 포인터 레지스터
// push {r4-r6,r14} : 4*4 만큼의 sp 이동
> 0x2000 > 0x1FF0
N _ R0 FFFE R8 0
Z Z R1 0 R9 0
C C R2 5074 R10 0
V _ R3 1E6C1A35 R11 0
I _ R4 0 R12 0
F _ R5 0 R13 1F6E92C8
T T R6 FFFF R14 1E6C1A1D
J _ R7 1F6E943C PC 1E6C19BC
usr SPSR CPSR 60000030
b_fucnt()함수를 부른 놈 : 0x1E6C1A1D 근방
정확히 말해 b_funct()함수를 처리하고 돌아가서 계속 진행할 주소 : 0x1E6C1A1D > 한 line위
주의) Thumb mode이니까 0x1E6C1A1D-1 = 0x1E6C1A1C로 돌아가야함
addr/line__|code_____|label____|mnemonic________________|comment______________________________________________________|
|word a_funct(word arg, word param)
3985|{
ST:1E6C1A10|B510 a_funct: push {r4,r14}
| int localone, localtwo;
| word ret;
|
3989| localone = (int)(arg<<1);
ST:1E6C1A12|0040 lsl r0,r0,#0x1 ; arg,arg,#1
3990| localtwo = (int)(param>>1);
ST:1E6C1A14|0849 lsr r1,r1,#0x1 ; param,param,#1
|
3992| ret = b_funct ((word)localone, (word)localtwo);
ST:1E6C1A16|B280 uxth r0,r0 ; localone,localone
ST:1E6C1A18|FFCEF7FF bl 0x1E6C19B8 ; b // 여기
ST:1E6C1A1C|4604 cpy r4,r0
|
3994| if (ret>100)
ST:1E6C1A1E|2C64 cmp r4,#0x64 ; ret,#100
ST:1E6C1A20|D903 bls 0x1E6C1A2A
3995| message ("too big");
ST:1E6C1A22|A078 add r0,pc,#0x1E0
ST:1E6C1A24|ED62F0AE blx 0x1E7704EC
ST:1E6C1A28|E002 b 0x1E6C1A30
| else
3997| message ("appropriate");
ST:1E6C1A2A|A078 add r0,pc,#0x1E0
ST:1E6C1A2C|ED5EF0AE blx 0x1E7704EC
|
3999| return ret;
ST:1E6C1A30|4620 cpy r0,r4 ; r0,ret
4000|}
ST:1E6C1A32|BD10 pop {r4,pc}
|
b_funct함수를 부르는 함수 : a_funct함수
bl 0x1E6C19B8 > r14 : PC +4 = 1E6C1A18
> 이동 : 0x1E6C19B8
a_funct함수를 부른 놈 찾기
___address__|________0________4________8________C_0123456789ABCDEF
SD:1F6E9390|>00000000 00000000 0000FFFF 1E6C1A1D ..............l. // r14
SD:1F6E93A0| 00000000 1E6C1A59 00005074 1C87DE49 ....Y.l.tP..I... // b_funct()
SD:1F6E93B0| 1F6E93C8 1F42F291 00000000 00000000 ..n...B.........
SD:1F6E93C0| 00000000 00000000 1F6E943C 1F3FB721 ........
그럼, b_funct()가 불렸을 때 SP : 0x1F6E93A0 // a_fuct()의 sp를 넣음
a_funct()함수가 불렸을 때 Stack..
addr/line__|code_____|label____|mnemonic________________|comment______________________________________________________|
|word a_funct(word arg, word param)
3985|{
ST:1E6C1A10|B510 a_funct: push {r4,r14}
| int localone, localtwo;
> r4,r14를 push 그러면
SD:1F6E93A0| 00000000 1E6C1A59 00005074 1C87DE49
r4 r14
r14-1 (= 0x1E6C1A58)의 주소 > a_funct()함수를 부르고 다음 실행할 주소
_addr/line__|code_____|label____|mnemonic________________|comment
4032| arg_ex = Index;
ST:1E6C1A50|4630 cpy r0,r6 ; r0,Index
|
4034| ret2 = a_funct(arg_ex, (word)data);
ST:1E6C1A52|2101 mov r1,#0x1
ST:1E6C1A54|FFDCF7FF bl 0x1E6C1A10 ; a
ST:1E6C1A58|9003 str r0,[r13,#0x0C] ; arg_ex,[r13,#12]
0x1E6CA58 바로 한 칸 위를 보면 a_funct() 함수를 호출한 곳 0x1E6C1A10
R13에 엮여 있는 주소에 뭔가를 push하고, pop
> R13에 주소를 넣기만 하면 그 주소부터 push/pop하면서 장난 친다는 사실!
왜 Local 변수가 없어질 수 밖에 없는가?
> 일반 Symbol과는 달리 Stack에 저장 > 되니까 개인 Address가 없음
> 쓰고 나면 없어짐!
'임베디드 > 임베디드 레시피' 카테고리의 다른 글
함수 포인터와 실행 주소 변경 (0) | 2024.12.08 |
---|---|
Stack의 Size (0) | 2024.12.07 |
stack : 함수를 불렀을때 (1) | 2024.12.06 |
stack initialization (0) | 2024.12.05 |
Stack , Heap (0) | 2024.12.05 |