1. Please install utility to run crash-utility  

$ sudo apt-get install git build-essential bison zlib1g-dev libncurses5-dev libncursesw5-dev  pkg-config flex swig -y

2. Pull crash-utility source code with below command.

$ git clone https://github.com/crash-utility/crash.git

3. Build crash-utility Source code 

$ cd crash
$ make target=ARM64 -j3

(Warninig)

You may see error messages compiling crash-utility due to 'j' option.
In this case, please build crash-utility without 'j' option

$ cd crash
$ make target=ARM64 

After crash-utility is sucessfully compiled, 'crash' is generated.

4. Place the vmcore and vmlinux in the same directory. And copy 'crash' to the same directory where vmcore and vmlinux are placed.

$ ls
$ crash vmcore vmlinux
$ chmod 777 crash 
(Warning)

Please make sure that vmcore is matched to vmlinux. And then you need to use the below
command to start crash utility

5. Run crash-utility using below command

$ ./crash vmcore vmlinux

When compiling crash utility in the Raspbian with Aarch32,
do not use 'j' option like (make -j5).

apt update
apt-get install git build-essential bison zlib1g-dev libncurses5-dev libncursesw5-dev  pkg-config flex swig -y
apt-get install -y texinfo
cd crash
make target=ARM

 

# good command to start 'crash utility'

 

1. 1st verified command 


./crash dump1@0x80000000,dump2@0x880000000 -p 4096 -m vabits_actual=39 -m kimage_voffset=0xffffffbf70000000 --no_panic --smp $1

 

2. Under progress

 

./crash1 -d -6 SYS_COREDUMP -m --kaslr=0x1d43c00000 -m vabits_actual=39 -m kimage_voffset=0xffffffa611c00000 -m --smp vmlinux

diff --git a/arm64.c b/arm64.c
index bdb2a0a..7c3a8ea 100644
--- a/arm64.c
+++ b/arm64.c
@@ -361,6 +361,19 @@ arm64_init(int when)
        /* use machdep parameters */
        arm64_calc_phys_offset();
     
+       error(INFO, "[+][%s][%d] at %s\n", __func__, __LINE__, __FILE__);
+       error(INFO, "kimage_voffset: %lx phys_offset: %lx \n",
+                               machdep->machspec->kimage_voffset, machdep->machspec->phys_offset);
+
+        error(INFO, "CONFIG_ARM64_VA_BITS: %ld\n", ms->CONFIG_ARM64_VA_BITS);
+        error(INFO,  "     VA_BITS_ACTUAL: %ld\n", ms->VA_BITS_ACTUAL);
+        error(INFO, "(calculated) VA_BITS: %ld\n", ms->VA_BITS);
+        error(INFO, " PAGE_OFFSET: %lx\n", ARM64_PAGE_OFFSET_ACTUAL);
+        error(INFO, "    VA_START: %lx\n", ms->VA_START);
+        error(INFO, "     modules: %lx - %lx\n", ms->modules_vaddr, ms->modules_end);
+        error(INFO, "     vmalloc: %lx - %lx\n", ms->vmalloc_start_addr, ms->vmalloc_end);
+        error(INFO, "kernel image: %lx - %lx\n", ms->kimage_text, ms->kimage_end);
+        error(INFO, "     vmemmap: %lx - %lx\n\n", ms->vmemmap_vaddr, ms->vmemmap_end);
        if (CRASHDEBUG(1)) {
            if (machdep->flags & NEW_VMEMMAP)
                fprintf(fp, "kimage_voffset: %lx\n",
@@ -816,6 +829,11 @@ arm64_parse_cmdline_args(void)
                    "setting max_physmem_bits to: %ld\n\n",
                    machdep->max_physmem_bits);
                continue;
+           } else if (arm64_parse_machdep_arg_l(arglist[i], "kaddr_offset",
+               &machdep->machspec->kimage_addr_offset)) {
+               error(WARNING, "setting kimage_addr_offset to: 0x%lx\n\n",
+                                   machdep->machspec->kimage_addr_offset);
+               continue;
            }
  
            error(WARNING, "ignoring --machdep option: %s\n",
@@ -1011,6 +1029,12 @@ arm64_kdump_phys_base(ulong *phys_offset)
    if ((machdep->flags & NEW_VMEMMAP) &&
        machdep->machspec->kimage_voffset &&
        (sp = kernel_symbol_search("memstart_addr"))) {
+
+       physaddr_t kimage_offset_addr = machdep->machspec->kimage_addr_offset;
+
+       if (kimage_offset_addr) {
+           machdep->machspec->kimage_voffset -= kimage_offset_addr;
+       }
        paddr = sp->value - machdep->machspec->kimage_voffset;
        if (READMEM(-1, phys_offset, sizeof(*phys_offset),
            sp->value, paddr) > 0)
diff --git a/defs.h b/defs.h
index 42e381e..a377611 100644
--- a/defs.h
+++ b/defs.h
@@ -3259,6 +3259,7 @@ struct machine_specific {
    ulong VA_BITS_ACTUAL;
    ulong CONFIG_ARM64_VA_BITS;
    ulong VA_START;
+   ulong kimage_addr_offset;
 };
  
 struct arm64_stackframe {
diff --git a/main.c b/main.c
index 83ccd31..971486e 100644
--- a/main.c
+++ b/main.c
@@ -21,6 +21,13 @@
 #include <getopt.h>
 #include <sys/prctl.h>
  
+#define OCIMEM_OFFSET_ADDR             0x14680000
+#define RPI5_KASLR_ADDR_LOCATION     0x146bf6d0
+#define ADDR_READ_OFFSET           0x4
+
+#define RPI5_ADDR_FORMAT_SIZE    19
+#define RPI5_KASLR_ADDR_OFFSET  ( RPI5_KASLR_ADDR_LOCATION - OCIMEM_OFFSET_ADDR + ADDR_READ_OFFSET )
+
 static void setup_environment(int, char **);
 static int is_external_command(void);
 static int is_builtin_command(void);
@@ -80,6 +87,9 @@ main(int argc, char **argv)
 {
    int i, c, option_index;
    char *tmpname;
+   FILE *ocimem_file = NULL;
+   uint64_t c_64, kaslr_offset = 0;
+   char *optarg_backup;
  
    setup_environment(argc, argv);
  
@@ -226,6 +236,29 @@ main(int argc, char **argv)
                        optarg);
                }
            } else if (STREQ(long_options[option_index].name, "kaslr")) {
+               ocimem_file = fopen("./OCIMEM.BIN", "r");
+
+               if(!ocimem_file) {
+                   error(INFO, "Fail to open OCIMEM.BIN\n");
+                   goto OCIMEM_READ_EXIT;
+               }
+
+               fseek(ocimem_file, RPI5_KASLR_ADDR_OFFSET, SEEK_SET);
+
+               optarg_backup = optarg;
+               optarg = malloc(RPI5_ADDR_FORMAT_SIZE);
+
+               for(i=0;i<sizeof(uint64_t);i++) {
+                   c_64 = getc(ocimem_file);
+                   kaslr_offset |= (c_64 << (i*8));
+               }
+              
+               snprintf(optarg, RPI5_ADDR_FORMAT_SIZE, "0x%lx", kaslr_offset);
+               error(INFO, "kaslr_offset=%s\n", optarg);
+OCIMEM_READ_EXIT:
+               if(ocimem_file)
+                   fclose(ocimem_file);
+
                if (!machine_type("X86_64") &&
                    !machine_type("ARM64") && !machine_type("X86") &&
                    !machine_type("S390X"))

 

>>>

* bad dump

SECTIONS_PER_ROOT = 128
SECTION_ROOT_MASK = 0x7f
PAGES_PER_SECTION = 262144
<readmem: ffffffa653a30058, KVADDR, "mem_section", 8, (FOE), 7ffd4f76eb20>
<read_kdump: addr: ffffffa653a30058 paddr: 41e30058 cnt: 8>
read_netdump: addr: ffffffa653a30058 paddr: 41e30058 cnt: 8 offset: 1e34058
<readmem: 0, KVADDR, "memory section root table", 64, (FOE), 5625b4edac70>
crash1: invalid kernel virtual address: 0  type: "memory section root table"


        if (!(vt->mem_sec = (void *)malloc(mem_section_size)))
                error(FATAL, "cannot malloc mem_sec cache\n");
        if (!(vt->mem_section = (char *)malloc(SIZE(mem_section))))
                error(FATAL, "cannot malloc mem_section cache\n");

        if (mem_section_is_ptr)
                get_symbol_data("mem_section", sizeof(void *), &addr);
        else
                addr = symbol_value("mem_section");

        readmem(addr, KVADDR, vt->mem_sec, mem_section_size,
                "memory section root table", FAULT_ON_ERROR);

 * good dump 

crash64>  p &mem_section
p: per_cpu_symbol_search(&mem_section): NULL
GETBUF(344 -> 0)
$1 = (struct mem_section ***) 0xffffff9d4e1a0010 <mem_section>
FREEBUF(0)


 7135 <readmem: ffffffd3bf5eb880, KVADDR, "memory section root table", 32768, (FOE), 556a792d83e0>
 7136 <read_ramdump: addr: ffffffd3bf5eb880 paddr: 17f5eb880 cnt: 1920>
 7137 read_ramdump: addr: ffffffd3bf5eb880 paddr: 17f5eb880 cnt: 1920 offset: 3f5eb880
 7138 <read_ramdump: addr: ffffffd3bf5ec000 paddr: 17f5ec000 cnt: 4096>
 7139 read_ramdump: addr: ffffffd3bf5ec000 paddr: 17f5ec000 cnt: 4096 offset: 3f5ec000
 7140 <read_ramdump: addr: ffffffd3bf5ed000 paddr: 17f5ed000 cnt: 4096>

crash64> rd 0xffffff9d4e1a0010 100
<addr: ffffff9d4e1a0010 count: 100 flag: 490 (KVADDR)>
<readmem: ffffff9d4e1a0010, KVADDR, "64-bit KVADDR", 8, (FOE), 7ffea347dc28>
<read_ramdump: addr: ffffff9d4e1a0010 paddr: a25a0010 cnt: 8>
read_ramdump: addr: ffffff9d4e1a0010 paddr: a25a0010 cnt: 8 offset: 225a0010
ffffff9d4e1a0010:  ffffffd3bf5eb880 <readmem: ffffff9d4e1a0018, KVADDR, "64-bit KVADDR", 8, (FOE), 7ffea347dc28>


./crash64 --minimal SYS_COREDUMP vmlinux

./crash64 --minimal SYS_COREDUMP --kaslr=0x1d43c00000 vmlinux

gitlab link for 'awesome-trace32'

https://gitlab.com/lauterbach/awesome-trace32

;****************************************************************************
;**           do_save_current_register_arm64.cmm                                           
;**           This script is designed to save current a set of registers(Arm64).          
;**                        
;**
;**       
;** when        who      what, where, why
;** --------------   ------------     ------------------------------------------------------
;** 07/12/2023   austindh.kim@gmail.com     First version
;****************************************************************************

ENTRY &ramdump_dir &output_file

;specify the output directory of dump file
&dump_debug_file="&ramdump_dir"+"/&output_file.cmm"
;=====specify the output directory of dump file, end =====

open #1 &dump_debug_file /create

&pstate=0x0
&r0=0x0
&r1=0x0
&r2=0x0
&r3=0x0
&r4=0x0
&r5=0x0
&r6=0x0
&r7=0x0
&r8=0x0
&r9=0x0
&r10=0x0
&r11=0x0
&r12=0x0
&r13=0x0
&r14=0x0
&r15=0x0
&r16=0x0
&r17=0x0
&r18=0x0
&r19=0x0
&r20=0x0
&r21=0x0
&r22=0x0
&r23=0x0
&r24=0x0
&r25=0x0
&r26=0x0
&r27=0x0
&r28=0x0
&r29=0x0
&r30=0x0
&pc=0x0
&sp=0x0

gosub ConfigureRegister64Bit 

close #1

enddo

; *************************************************************************
; ConfigureRegister64Bit
;
;   Read current Register and save it.
;
; *************************************************************************
ConfigureRegister64Bit:
  LOCAL &temp
  
  &pstate=r(cpsr)
  &r0=r(x0)
  &r1=r(x1)
  &r2=r(x2)
  &r3=r(x3)
  &r4=r(x4)
  &r5=r(x5)
  &r6=r(x6)
  &r7=r(x7)
  &r8=r(x8)
  &r9=r(x9)
  &r10=r(x10)
  &r11=r(x11)
  &r12=r(x12)
  &r13=r(x13) 
  &r14=r(x14)
  &r15=r(x15)
  &r16=r(x16)
  &r17=r(x17)
  &r18=r(x18)
  &r19=r(x19) 
  &r20=r(x20)
  &r21=r(x21)
  &r22=r(x22)
  &r23=r(x23) 
  &r24=r(x24)
  &r25=r(x25)
  &r26=r(x26)
  &r27=r(x27)
  &r28=r(x28)
  &r29=r(x29)    
  &r30=r(x30)    
  &sp=r(sp)
  &pc=r(pc)
  
  write #1 "r.s cpsr 0x" &pstate
  write #1 "r.s x0 0x" &r0
  write #1 "r.s x1 0x" &r1
  write #1 "r.s x2 0x" &r2
  write #1 "r.s x3 0x" &r3 
  write #1 "r.s x4 0x" &r4
  write #1 "r.s x5 0x" &r5
  write #1 "r.s x6 0x" &r6
  write #1 "r.s x7 0x" &r7
  write #1 "r.s x8 0x" &r8
  write #1 "r.s x9 0x" &r9
  write #1 "r.s x10 0x" &r10
  write #1 "r.s x11 0x" &r11
  write #1 "r.s x12 0x" &r12
  write #1 "r.s x13 0x" &r13
  write #1 "r.s x14 0x" &r14
  write #1 "r.s x15 0x" &r15
  write #1 "r.s x16 0x" &r16
  write #1 "r.s x17 0x" &r17
  write #1 "r.s x18 0x" &r18 
  write #1 "r.s x19 0x" &r19
  write #1 "r.s x20 0x" &r20
  write #1 "r.s x21 0x" &r21
  write #1 "r.s x22 0x" &r22
  write #1 "r.s x23 0x" &r23
  write #1 "r.s x24 0x" &r24
  write #1 "r.s x25 0x" &r25
  write #1 "r.s x26 0x" &r26
  write #1 "r.s x27 0x" &r27
  write #1 "r.s x28 0x" &r28
  write #1 "r.s x29 0x" &r29 
  write #1 "r.s x30 0x" &r30    
  write #1 "r.s pc 0x" &pc
  write #1 "r.s sp 0x" &sp 
  
RETURN



< 환경: 라즈베리 파이(aarch32) >
 
'crash-utility' 소스를 빌드하면 아래와 같은 에러를 만난다.
 
gcc -c -g -DARM -D_FILE_OFFSET_BITS=64 -DGDB_10_2 -g -O2 build_data.c
gcc -c -g -DARM -D_FILE_OFFSET_BITS=64 -DGDB_10_2 -g -O2 main.c
main.c:20:10: fatal error: curses.h: No such file or directory
 #include <curses.h>
          ^~~~~~~~~~
compilation terminated.
make[5]: *** [Makefile:336: main.o] Error 1
 
curses 라이브러리가 설치되지 않았을 때 이런 에러가 발생한다.
다음 커맨드를 사용해 curses 라이브러리를 설치하면 컴파일 에러가 발생하지 않는다.
 
root@raspberrypi:/home/pi/osc_work/src_crash/crash# apt-get install libncurses5-dev libncursesw5-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  gconf-service gconf2-common libexiv2-14 libgconf-2-4 libgfortran3 libgmime-2.6-0 libncurses5 libssl1.0.2 uuid-dev vlc-l10n vlc-plugin-notify
  vlc-plugin-samba vlc-plugin-video-splitter vlc-plugin-visualization
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
  libncurses-dev
Suggested packages:
  ncurses-doc
The following NEW packages will be installed:
  libncurses-dev libncurses5-dev libncursesw5-dev
0 upgraded, 3 newly installed, 0 to remove and 23 not upgraded.
Need to get 280 kB of archives.
After this operation, 1,730 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y
리눅스 커널 동네에서 전 세계적으로 쓰고 있는 디버깅 툴을 소개하고자 합니다.
 
레드헷의 앤더슨이란 형님이 만든 오픈 소스로 배포한 리눅스 크래시(커널 패닉)을 분석할 수 있는 툴인데요, 
리눅스 커널 커뮤니티에서도 이 툴을 활발히 쓰고 있죠.
 
소스를 좀 받아 볼까요? 리눅스 머신에서 아래 커맨드로 소스를 땡겨옵니다.
 
소스를 받고 나서 아래 명령어로 빌드를 해요.
ARM machine인 경우
make target=ARM
make target=ARM extensions
 
X86인 경우
make target=X86_64
make target=X86_64 extensions
 
이제 trace command란 오픈소스 툴을 가져올 차례입니다. 이 툴로 ftrace 각 event를 파싱할 수 있어요.
 
빌드 명령어는 초간단, 그냥 make 만 때리면 되요.
 
자자, 이제 좀 정리해볼까요?
 
crash tool을 빌드한 결과물은 crash, trace command을 빌드한 이미지는 trace-cmd 거거든요.
 
/bin/CrashTool 폴더에 각각 결과물을 복사하구요. 
"make target=ARM extensions" 빌드하면 생성되는 extensions 폴더도 잊지 마세요.
austin.kim@Linux:~/bin/CrashTool$ ls -l
total 52400
-rwxrwxrwx 1 austin.kim home001  8536852 Jul 13 11:30 crash
drwxrwxrwx 4 austin.kim home001     4096 May  4 19:20 extensions
-rwxrwxrwx 1 austin.kim home001   868663 Feb 15 09:23 trace-cmd
 
crash_load.sh란 파일을 아래와 같이 만들고, "./crash_load.sh vmlinux" 명령어를 입력하면 실행 끝이죠.
#!/bin/sh
export CRASH_EXTENSIONS=/home001/austin.kim/bin/CrashTool/extensions
export TRACE_CMD=/home001/austin.kim/bin/CrashTool/trace-cmd 
/home001/austin.kim/bin/CrashTool/crash coredump0.BIN@0x0,coredump1.BIN@0xc0000000 -p 4096 -m phys_base=0x80000000 --no_panic --smp $1
 
실행 결과 화면입니다. 참 쉽죠.
      KERNEL: vmlinux
   DUMPFILES: /var/tmp/ramdump_elf_1X1HKt [temporary ELF header]
              DDRCS0.BIN
              DDRCS1.BIN
        CPUS: 4
        DATE: Wed Nov 29 15:24:00 2017
      UPTIME: 00:35:30
LOAD AVERAGE: 6.66, 7.02, 5.86
       TASKS: 363
    NODENAME: localhost
     RELEASE: 3.18.66-g715eee2
     VERSION: #2 SMP PREEMPT Wed Nov 29 12:37:14 KST 2017
     MACHINE: armv7l  (unknown Mhz)
      MEMORY: 2 GB
       PANIC: "kernel BUG at /src/3.18_kernel_ver/kernel/lib/list_debug.c:40!"
         PID: 0
     COMMAND: "swapper/0"
        TASK: c1917578  (1 of 4)  [THREAD_INFO: c1900000]
         CPU: 0
       STATE: TASK_RUNNING
     WARNING: reported panic task e6357840 not found
 
crash>
 
#Reference
 
 
# Reference: For more information on 'Linux Kernel';
 
디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1
 
디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2
 
 
 
 
 
 
디버깅 옵션(-d 6)을 적용해 crash-utilty를 실행하면 vmcore를 로딩하면서 다양한 디버깅 정보를 출력합니다.
 
$ ./crash vmcore vmlinux -d 6
 
crash 7.3.0++
Copyright (C) 2002-2021  Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
Copyright (C) 1999-2006  Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011, 2020-2021  NEC Corporation
Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions.  Enter "help copying" to see the conditions.
This program has absolutely no warranty.  Enter "help warranty" for details.
 
NOTE: setting kimage_voffset to: 0xffffffbf70000000
 
NOTE: setting vabits_actual to: 39
 
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=aarch64-elf-linux"...
 
WARNING: could not find MAGIC_START!
raw_crash64: cannot determine base kernel version
raw_crash64: vmlinux and /var/tmp/ramdump_elf_74SLyJ do not match!
 
Usage:
 
  crash [OPTION]... NAMELIST MEMORY-IMAGE[@ADDRESS]     (dumpfile form)
  crash [OPTION]... [NAMELIST]                          (live system form)
 
...
 
creating temporary ELF header: /var/tmp/ramdump_elf_BGK8hx
 
vmcore_data:
                  flags: c0 (KDUMP_LOCAL|KDUMP_ELF64)
                   ndfd: 16
                    ofp: 7f2e25cad620
            header_size: 848
   num_pt_load_segments: 13
     pt_load_segment[0]:
            file_offset: 350
             phys_start: 80000000
               phys_end: c0000000
              zero_fill: 0
     pt_load_segment[1]:
            file_offset: 40000350
             phys_start: 880000000
               phys_end: 8c0000000
              zero_fill: 0

 

< '시스템 소프트웨어 개발을 위한 Arm 아키텍처의 구조와 원리' 저자>

 
 
크래시 유틸리티를 디버깅할 수 있는 유용한 디버깅 패치다.
100% 내가 만든 것이다.
 
diff --git a/arm64.c b/arm64.c
--- a/arm64.c
+++ b/arm64.c
@@ -361,6 +361,19 @@ arm64_init(int when)
        /* use machdep parameters */
        arm64_calc_phys_offset();
     
+       error(INFO, "[+][%s][%d] at %s\n", __func__, __LINE__, __FILE__);
+       error(INFO, "kimage_voffset: %lx phys_offset: %lx \n",
+                               machdep->machspec->kimage_voffset, machdep->machspec->phys_offset);
+
+        error(INFO, "CONFIG_ARM64_VA_BITS: %ld\n", ms->CONFIG_ARM64_VA_BITS);
+        error(INFO,  "     VA_BITS_ACTUAL: %ld\n", ms->VA_BITS_ACTUAL);
+        error(INFO, "(calculated) VA_BITS: %ld\n", ms->VA_BITS);
+        error(INFO, " PAGE_OFFSET: %lx\n", ARM64_PAGE_OFFSET_ACTUAL);
+        error(INFO, "    VA_START: %lx\n", ms->VA_START);
+        error(INFO, "     modules: %lx - %lx\n", ms->modules_vaddr, ms->modules_end);
+        error(INFO, "     vmalloc: %lx - %lx\n", ms->vmalloc_start_addr, ms->vmalloc_end);
+        error(INFO, "kernel image: %lx - %lx\n", ms->kimage_text, ms->kimage_end);
+        error(INFO, "     vmemmap: %lx - %lx\n\n", ms->vmemmap_vaddr, ms->vmemmap_end);
        if (CRASHDEBUG(1)) {
            if (machdep->flags & NEW_VMEMMAP)
                fprintf(fp, "kimage_voffset: %lx\n",
@@ -816,6 +829,11 @@ arm64_parse_cmdline_args(void)
                    "setting max_physmem_bits to: %ld\n\n",
                    machdep->max_physmem_bits);
                continue;
+           } else if (arm64_parse_machdep_arg_l(arglist[i], "kaddr_offset",
+               &machdep->machspec->kimage_addr_offset)) {
+               error(WARNING, "setting kimage_addr_offset to: 0x%lx\n\n",
+                                   machdep->machspec->kimage_addr_offset);
+               continue;
            }
  
             error(WARNING, "ignoring --machdep option: %s\n",
@@ -1011,6 +1029,12 @@ arm64_kdump_phys_base(ulong *phys_offset)
    if ((machdep->flags & NEW_VMEMMAP) &&
        machdep->machspec->kimage_voffset &&
        (sp = kernel_symbol_search("memstart_addr"))) {
+
+       physaddr_t kimage_offset_addr = machdep->machspec->kimage_addr_offset;
+
+       if (kimage_offset_addr) {
+           machdep->machspec->kimage_voffset -= kimage_offset_addr;
+       }
        paddr = sp->value - machdep->machspec->kimage_voffset;
        if (READMEM(-1, phys_offset, sizeof(*phys_offset),
            sp->value, paddr) > 0) 
 

< '시스템 소프트웨어 개발을 위한 Arm 아키텍처의 구조와 원리' 저자>

 
 
리눅스 커널 코드를 분석하다 보면 아래 container_of 매크로를 자주 볼수 있어요.
void t21142_media_task(struct work_struct *work)
{
struct tulip_private *tp =
container_of(work, struct tulip_private, media_work);

 

struct net_device *dev = tp->dev;
 
그럼 T32으로 코어 덤프를 분석 할 때 위 매크로를 그대로 가져다 쓸 수 있는 방법을 소개하고자 합니다. 아주 간단해요. T32로 아래 명령어를 치면 되죠.
sYmbol.NEW.MACRO offsetof(type,member) ((int)(&((type*)0)->member))
sYmbol.NEW.MACRO container_of(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member)))
 
 
예를 들어, 아래와 같이 mutex lock 변수가 있다고 가정해 보면. 
struct mutex.wait_list는 mutex lock을 기다리는 다른 mutex lock의 struct mutex.wait_list 주소를 가르키고 있습니다. 
(꼴을 보아하니 mutex deadlock같아 보이네요. "kworker/4:5" 란 프로세스가 mutex lock을 잠그고 잠들어 버린 것 같네요.)
  ( struct mutex *)0xFFFFFF981BC24540 = 0xFFFFFF981BC24540 -> (
    count = (counter = -1),
    wait_lock = (rlock = (raw_lock = (owner = 1445, next = 1445), magic = 3735899821, owner_cpu = 42
    wait_list = (
      next = 0xFFFFFFD388F4BB78 -> (
        next = 0xFFFFFF981BC24560 -> (
          next = 0xFFFFFFD388F4BB78,
//...
    owner = 0xFFFFFFD3F3085BC0, //<<--"kworker/4:5"
    magic = 0xFFFFFF981BC24540)
 
 
그럼 이 때 어떻게 디버깅을 할 수 있을까요? 이 경우, struct mutex 구조체에서 wait_list 멤버 오프셋 계산을 해야 해요. 이 값은 0x20이네요.
 
crash64> struct -o mutex
struct mutex {
   [0x0] atomic_t count;
   [0x8] spinlock_t wait_lock;
  [0x20] struct list_head wait_list;
  [0x30] struct task_struct *owner;
 
그리고 아래와 같이 명령어를 치면 되죠.    
v.v %s %t (struct mutex *)(0xFFFFFFD388F4BB78-0x20)
 
그런데 이 방법이 효율적인 것 같지는 않네요. 왜냐하면, 리눅스 커널에는 모래와 같이 엄청난 개수의 데이터 구조체가 있는데, 디버깅할 때 마다 맨날 오프셋을 계산하면 디버깅 하다 김이 빠지죠.
이럴 때, 아래와 같이 명령어를 치면 손 쉽게 디버깅을 할 수 있습니다.
v.v %all container_of(0xFFFFFFD388F4BB78,struct mutex,wait_list)
  (struct mutex *) container_of(0xFFFFFFD388F4BB78,struct mutex,wait_list) = 0xFFFFFFD388F4BB58 -> (
    (atomic_t) count = ((int) counter = 0x0),
    (spinlock_t) wait_lock = ((struct raw_spinlock) rlock = ((arch_spinlock_t) raw_lock = ((u16) own
    (struct list_head) wait_list = ((struct list_head *) next = 0xFFFFFF981BC24560, (struct list_hea
    (struct task_struct *) owner = 0xFFFFFFD46F71AE00,  //<<-- "kworker/4:1" process
    (void *) magic = 0xFFFFFFD388F4BB78)
 
< '시스템 소프트웨어 개발을 위한 Arm 아키텍처의 구조와 원리' 저자>
 
 
 

 

리눅스 커널이 제공하는 매크로를 그대로 사용할 수 있어서 좋고, 효율적으로 관련 변수를 확인할 수 있어서 좋습니다.

+ Recent posts