Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

1048
469
422440


ARM64 - Exception 시 Stack Push Armv7: Calling Convention

유저 공간에서 시스템 콜을 호출할 때 유저 공간에서 돌던 레지스터를 커널 공간 스택 Bottom Address 근처에 Push하거든요. 이번에는 Exception(Data abort)이 발생했을 때 스택에 어떤 값들을 Push하는 지 점검해 볼께요.

아래는 ch_pop_remote_rx_intent() 함수에서 exception이 발생한 콜스택인데요. Trace32로 잡았어요. 이 때 Stack 정보 좀 살펴볼께요.
-000|do_mem_abort()
-001|el1_da(asm)
 -->|exception
-002|ch_pop_remote_rx_intent()
-003|glink_tx_common()
-004|glink_txv()
-005|ipc_router_glink_xprt_write()
-006|msm_ipc_router_write_pkt(inline)
-006|msm_ipc_router_send_to()
-007|msm_ipc_router_sendmsg()
-008|sock_sendmsg_nosec(inline)
-008|sock_sendmsg()
-009|SYSC_sendto(inline)
-009|sys_sendto()
-010|el0_svc_naked(asm)
.
[1]: data abort에 실행되는 el1_da exception vector 심볼이 보이네요.
[2]: Exception이 발생하는 순간, ARM Processor는 x0부터 PC(Program Counter)까지 레지스터를 스택에 바로 Push해요 
[3]: FFFFFFE4DE6A79C8 메모리 주소에 스택 주소가 저장되어 있는데 스택 주소를 보여주고 있어요.
_____________address|_data____________________|value_________________|symbol
NSD:FFFFFFE4DE6A77C0| 50 71 84 9A 9F FF FF FF  0xFFFFFF9F9A847150     \\vmlinux\fault\fault_info+0xA8
NSD:FFFFFFE4DE6A77C8| 25 00 00 00 00 00 00 00  0x25
NSD:FFFFFFE4DE6A77D0| 01 00 00 00 00 00 00 00  0x1
NSD:FFFFFFE4DE6A77D8| 48 7B 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7B48
NSD:FFFFFFE4DE6A77E0| 00 00 00 00 00 00 00 00  0x0
NSD:FFFFFFE4DE6A77E8| 00 40 6A DE E4 FF FF FF  0xFFFFFFE4DE6A4000
NSD:FFFFFFE4DE6A77F0| 00 F0 8C AF 7B 00 00 00  0x7BAF8CF000
NSD:FFFFFFE4DE6A77F8| E0 EB 0C 59 E5 FF FF FF  0xFFFFFFE5590CEBE0
NSD:FFFFFFE4DE6A7800| 00 7A 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7A00
NSD:FFFFFFE4DE6A7808| FC 26 68 99 9F FF FF FF  0xFFFFFF9F996826FC     \\vmlinux\Global\el1_da+0x24  //<<-- [1]
NSD:FFFFFFE4DE6A7810| 68 D3 5E 77 E5 FF FF FF  0xFFFFFFE5775ED368
NSD:FFFFFFE4DE6A7818| 00 00 00 00 80 00 00 00  0x8000000000
NSD:FFFFFFE4DE6A7820| 00 30 BA 82 00 00 00 00  0x82BA3000
NSD:FFFFFFE4DE6A7828| 50 E4 B0 99 9F FF FF FF  0xFFFFFF9F99B0E450     \\vmlinux\glink\ch_pop_remote_rx_intent+0xF4
NSD:FFFFFFE4DE6A7830| C5 01 40 80 00 00 00 00  0x804001C5
NSD:FFFFFFE4DE6A7838| 70 F9 13 71 E5 FF FF FF  0xFFFFFFE57113F970
NSD:FFFFFFE4DE6A7840| 00 00 00 00 00 00 00 00  0x0
NSD:FFFFFFE4DE6A7848| 00 00 00 00 00 00 00 00  0x0
NSD:FFFFFFE4DE6A7850| 88 43 F2 F1 E4 FF FF FF  0xFFFFFFE4F1F24388
NSD:FFFFFFE4DE6A7858| 00 60 AF 9B 9F FF FF FF  0xFFFFFF9F9BAF6000     \\vmlinux\Global\nf_conntrack_locks+0xA00
NSD:FFFFFFE4DE6A7860| 01 00 00 00 00 00 00 00  0x1
NSD:FFFFFFE4DE6A7868| 06 00 00 00 00 00 00 00  0x6
NSD:FFFFFFE4DE6A7870| 80 7A 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7A80
NSD:FFFFFFE4DE6A7878| B0 6C AF 9B 9F FF FF FF  0xFFFFFF9F9BAF6CB0     \\vmlinux\Global\cpusets_enabled_key
NSD:FFFFFFE4DE6A7880| 00 70 AF 9B 9F FF FF FF  0xFFFFFF9F9BAF7000     \\vmlinux\trace/ftrace\ftrace_func_hash+0x278
NSD:FFFFFFE4DE6A7888| 00 00 16 71 E5 FF FF FF  0xFFFFFFE571160000
NSD:FFFFFFE4DE6A7890| A0 78 6A DE E4 FF FF FF  0xFFFFFFE4DE6A78A0
NSD:FFFFFFE4DE6A7898| 00 C3 D5 9B 9F FF FF FF  0xFFFFFF9F9BD5C300     \\vmlinux\Global\contig_page_data+0x1800
NSD:FFFFFFE4DE6A78A0| 50 79 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7950
NSD:FFFFFFE4DE6A78A8| 20 09 92 99 9F FF FF FF  0xFFFFFF9F99920920     \\vmlinux\services\security_compute_av+0x128
NSD:FFFFFFE4DE6A78B0| E0 78 6A DE E4 FF FF FF  0xFFFFFFE4DE6A78E0
NSD:FFFFFFE4DE6A78B8| DC CC 79 99 9F FF FF FF  0xFFFFFF9F9979CCDC     \\vmlinux\swap\lru_cache_add_active_or_unevictable+0x4C
NSD:FFFFFFE4DE6A78C0| C0 96 44 55 BE FF FF FF  0xFFFFFFBE554496C0
NSD:FFFFFFE4DE6A78C8| 3C 6B 77 2B 46 76 A8 C2  0xC2A876462B776B3C
NSD:FFFFFFE4DE6A78D0| 00 B6 19 E8 E4 FF FF FF  0xFFFFFFE4E819B600  // x0 //<<-- [2]
NSD:FFFFFFE4DE6A78D8| 40 01 00 00 00 00 00 00  0x140                  // x1
NSD:FFFFFFE4DE6A78E0| 00 00 20 13 80 FF FF FF  0xFFFFFF8013200000    // x2
NSD:FFFFFFE4DE6A78E8| 00 02 00 00 00 00 00 00  0x200                     // x3
NSD:FFFFFFE4DE6A78F0| 28 7B 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7B28  // x4
NSD:FFFFFFE4DE6A78F8| B0 FF 1F 13 80 FF FF FF  0xFFFFFF80131FFFB0   // x5
NSD:FFFFFFE4DE6A7900| 10 00 20 13 80 FF FF FF  0xFFFFFF8013200010   // x6
NSD:FFFFFFE4DE6A7908| 00 00 00 00 00 00 00 00  0x0             // x7
NSD:FFFFFFE4DE6A7910| 00 07 C6 4F E5 FF FF FF  0xFFFFFFE54FC60700  // x8
NSD:FFFFFFE4DE6A7918| 00 00 00 00 00 00 00 00  0x0                        // x9 
NSD:FFFFFFE4DE6A7920| 00 00 00 00 00 00 00 00  0x0                        // x10
NSD:FFFFFFE4DE6A7928| 00 00 00 00 00 00 00 00  0x0                        // x11
NSD:FFFFFFE4DE6A7930| 00 00 00 00 00 00 00 00  0x0                        // x12
NSD:FFFFFFE4DE6A7938| 00 00 00 00 00 00 00 00  0x0                        // x13
NSD:FFFFFFE4DE6A7940| 00 00 00 00 00 00 00 00  0x0                        // x14 
NSD:FFFFFFE4DE6A7948| AB AA AA AA AA AA AA AA  0xAAAAAAAAAAAAAAAB  // x15
NSD:FFFFFFE4DE6A7950| 04 BA 5E 9A 9F FF FF FF  0xFFFFFF9F9A5EBA04     \\vmlinux\socket\sys_sendto // x16
NSD:FFFFFFE4DE6A7958| 14 B3 AB B2 7B 00 00 00  0x7BB2ABB314        // x17
NSD:FFFFFFE4DE6A7960| D6 00 00 00 00 00 00 00  0xD6                     // x18
NSD:FFFFFFE4DE6A7968| 68 D3 5E 77 E5 FF FF FF  0xFFFFFFE5775ED368 // x19
NSD:FFFFFFE4DE6A7970| 28 00 00 00 00 00 00 00  0x28                      // x20
NSD:FFFFFFE4DE6A7978| 60 D3 5E 77 E5 FF FF FF  0xFFFFFFE5775ED360  // x21
NSD:FFFFFFE4DE6A7980| 28 7B 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7B28 // x22
NSD:FFFFFFE4DE6A7988| 20 7B 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7B20 // x23
NSD:FFFFFFE4DE6A7990| 1C 7B 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7B1C // x24
NSD:FFFFFFE4DE6A7998| 01 00 00 00 00 00 00 00  0x1                        // x25
NSD:FFFFFFE4DE6A79A0| 48 7B 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7B48 // x26
NSD:FFFFFFE4DE6A79A8| 00 00 00 00 00 00 00 00  0x0                        // x27
NSD:FFFFFFE4DE6A79B0| 00 D2 5E 77 E5 FF FF FF  0xFFFFFFE5775ED200  // x28
NSD:FFFFFFE4DE6A79B8| 00 7A 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7A00 // x29
NSD:FFFFFFE4DE6A79C0| 08 E4 B0 99 9F FF FF FF  0xFFFFFF9F99B0E408     \\vmlinux\glink\ch_pop_remote_rx_intent+0xAC // x30
NSD:FFFFFFE4DE6A79C8| 00 7A 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7A00  // SP
NSD:FFFFFFE4DE6A79D0| 50 E4 B0 99 9F FF FF FF  0xFFFFFF9F99B0E450     \\vmlinux\glink\ch_pop_remote_rx_intent+0xF4 // PC
NSD:FFFFFFE4DE6A79D8| C5 01 40 80 00 00 00 00  0x804001C5             // CPSR
NSD:FFFFFFE4DE6A79E0| 00 7A 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7A00
NSD:FFFFFFE4DE6A79E8| 08 E4 B0 99 9F FF FF FF  0xFFFFFF9F99B0E408     \\vmlinux\glink\ch_pop_remote_rx_intent+0xAC
NSD:FFFFFFE4DE6A79F0| 00 00 00 00 80 00 00 00  0x8000000000
NSD:FFFFFFE4DE6A79F8| 0C D2 5E 77 E5 FF FF FF  0xFFFFFFE5775ED20C
NSD:FFFFFFE4DE6A7A00| 60 7A 6A DE E4 FF FF FF  0xFFFFFFE4DE6A7A60  //<<-- [3]
NSD:FFFFFFE4DE6A7A08| 0C 15 B1 99 9F FF FF FF  0xFFFFFF9F99B1150C     \\vmlinux\glink\glink_tx_common+0x228
NSD:FFFFFFE4DE6A7A10| 00 06 C6 4F E5 FF FF FF  0xFFFFFFE54FC60600
NSD:FFFFFFE4DE6A7A18| 0C D2 5E 77 E5 FF FF FF  0xFFFFFFE5775ED20C

이렇게 스택에 Push된 레지스터를 확인하는 이유는 Exception으로 발생한 커널 패닉이 왜 발생했는지 정확히 점검할 수 있기 때문이에요.

그리고 가끔 Stack Corruption으로 커널 패닉이 발생하는 경우도 있거든요. 이럴 때 스택에 있는 값들을 하나 하나 씩 점검해서 어떻게 Stack이 Push되었는지 점검할 필요가 있어요.



덧글

댓글 입력 영역