Linux Kernel(4.9) Hacks

rousalome.egloos.com

포토로그 Kernel Crash




[라즈베리파이] 인터럽트 핸들러에서 스택 덤프 저장 라즈베리_리눅스커널_인터럽트

아래 패치를 적용하면 해당 프로세스의 스택 메모리 덤프를 stack_dump 배열에 저장합니다.
인터럽트 처리가 마무리 된 후 프로세스 레벨에서 stack_dump 배열에 저장된 메모리 덤프를 커널 로그로 출력하면,
인터럽트 벡터 심볼 __irq_svc과 스택에 푸쉬한 레지스터 정보를 모두 볼 수 있습니다.
diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c
index 612293c..2623e0d 100644
--- a/drivers/video/fbdev/bcm2708_fb.c
+++ b/drivers/video/fbdev/bcm2708_fb.c
@@ -713,9 +713,28 @@ static void bcm2708_fb_imageblit(struct fb_info *info,
        cfb_imageblit(info, image);
 }
 
+#define _DEBUG_ARM_STACK_SIZE 0x2000
+static unsigned int stack_dump[_DEBUG_ARM_STACK_SIZE];
+
+#define _DEBUG_ADDRESS_OFFSET 4
+
 static irqreturn_t bcm2708_fb_dma_irq(int irq, void *cxt)
 {
        struct bcm2708_fb *fb = cxt;
+       
+       register unsigned long current_sp asm ("sp");
+       unsigned long temp_stack_addr = 0x0;
+       unsigned int stack_bottom_addr = 0x0;
+       int proc_times = 0;
+       
+       stack_bottom_addr = (unsigned int)current->stack + _DEBUG_ARM_STACK_SIZE;  //<<--[1]
+
+       temp_stack_addr = current_sp;  //<<--[2]
+       for (proc_times = 0; temp_stack_addr < stack_bottom_addr; proc_times++)
+       {
+               stack_dump[temp_stack_addr] = *((unsigned long*)(temp_stack_addr));  //<<--[3] 
+               temp_stack_addr += _DEBUG_ADDRESS_OFFSET; 
+       }
 
        /* FIXME: should read status register to check if this is
         * actually interrupting us or not, in case this interrupt

[1]: 현재 구동 중인 프로세스의 태스크 디스크립터는 current란 매크로로 가져옵니다.
   struct task_struct->stack 멤버로 스택 Bottom 주소를 가져와서 프로세스 스택 사이즈를 더해 스택 Top 주소를 구합니다

[2]: "register unsigned long current_sp asm ("sp");" 명령어로 현재 실행 중인 코드의 스택 주소를 current_sp 변수에 저장했습니다.
     이 값을 temp_stack_addr 로컬 변수에 저장합니다.

[3]: temp_stack_addr 현재 스택 주소에서 4바이트 씩 계속 더하면서 스택 Top 주소까지 스택 메모리 덤프를 stack_dump 배열에 저장합니다.

스택 덤프를 어떤 방식으로 표현할 지 고민 중입니다.

덧글

댓글 입력 영역