간단하다. 로그 버퍼를 볼 수 있다.

log -m

crash> log -m
<6>[194643.799885 02-09 21:16:26.949] bt_hc_worker (32565): undefined instruction: pc=c032ae1c
....

<0>[194643.799977 02-09 21:16:26.949] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
<4>[194643.800007 02-09 21:16:26.949] Modules linked in:
<4>[194643.800038 02-09 21:16:26.949] CPU: 0    Tainted: G        W     (3.4.0-perf-g3d4c0e7-00001-g46f9c0a #1)
<4>[194643.800068 02-09 21:16:26.949] PC is at hs_start_rx_locked+0x2c/0x218
<4>[194643.800099 02-09 21:16:26.949] LR is at hs_start_rx_locked+0x2c/0x218
<4>[194643.800129 02-09 21:16:26.949] pc : c032ae1c    lr : c032ae1c    psr : 20000093

 

프로세서의 상태를 parent tree 포맷으로 나타내줌.

crash> ps -p

crash> ps -p
PID: 0      TASK: c0d4cbd8  CPU: 0   COMMAND: "swapper/0"
PID: 2      TASK: dc4403c0  CPU: 0   COMMAND: "kthreadd"
  PID: 75     TASK: eb66da40  CPU: 1   COMMAND: "smux_tx_wq"
 
PID: 0      TASK: c0d4cbd8  CPU: 0   COMMAND: "swapper/0"
PID: 2      TASK: dc4403c0  CPU: 0   COMMAND: "kthreadd"
  PID: 76     TASK: eb66de00  CPU: 1   COMMAND: "smux_rx_wq"

 

프로세서의상태를 다른 parent tree 포맷으로 나타내줌.

crash> ps -c

PID: 0      TASK: c0d4cbd8  CPU: 0   COMMAND: "swapper/0"
  PID: 0      TASK: c0d4cbd8  CPU: 0   COMMAND: "swapper/0"
  PID: 0      TASK: dc4421c0  CPU: 1   COMMAND: "swapper/1"
  PID: 1      TASK: dc440000  CPU: 0   COMMAND: "init"
  PID: 2      TASK: dc4403c0  CPU: 0   COMMAND: "kthreadd"
 
PID: 0      TASK: dc4421c0  CPU: 1   COMMAND: "swapper/1"
  (no children)
 
PID: 1      TASK: dc440000  CPU: 0   COMMAND: "init"
  PID: 142    TASK: eb5fe940  CPU: 0   COMMAND: "ueventd"
  PID: 321    TASK: eadd7c00  CPU: 0   COMMAND: "healthd"
  PID: 322    TASK: eadd5680  CPU: 1   COMMAND: "servicemanager"
  PID: 323    TASK: eadd52c0  CPU: 0   COMMAND: "vold"

 

process user space 상의 좀더 구체적인 정보를 보여줌

crash> ps -a

crash> ps -a
PID: 389    TASK: eb066940  CPU: 0   COMMAND: "sdcard"
ARG: /system/bin/sdcard -u 1023 -g 1023 -l /data/media /mnt/shell/emulated
ENV: VIBE_PIPE_PATH=/dev/pipes
     PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
     LD_LIBRARY_PATH=/vendor/lib:/system/lib
     ANDROID_BOOTLOGO=1
     ANDROID_ROOT=/system

 

process group 별로 process를 보여줌

crash> ps -g

crash> ps -g
PID: 330    TASK: eadd4b40  CPU: 0   COMMAND: "surfaceflinger"
  PID: 474    TASK: ea95c3c0  CPU: 1   COMMAND: "Binder_1"
  PID: 475    TASK: ea95fc00  CPU: 1   COMMAND: "DispSync"
  PID: 479    TASK: ea95e940  CPU: 0   COMMAND: "Binder_2"

 

아래명령어를 입력하면 process 당 동작 시간을 표시한다. 프로세스들의 stall 현상을 디버깅하기 유용하다.

crash> ps -t

PID: 32569  TASK: e04703c0  CPU: 0   COMMAND: "ContactsProvide"
    RUN TIME: 00:00:00
  START TIME: 194643
       UTIME: 1
       STIME: 0
 

 

커널쓰레드의 정보를 보여줌

crash> ps -k

crash> ps -k
   PID    PPID  CPU   TASK    ST  %MEM     VSZ    RSS  COMM
      0      0   0  c0d4cbd8  RU   0.0       0      0  [swapper/0]
      0      0   1  dc4421c0  RU   0.0       0      0  [swapper/1]
      2      0   0  dc4403c0  IN   0.0       0      0  [kthreadd]
      3      2   0  dc440780  IN   0.0       0      0  [ksoftirqd/0]
      6      2   0  dc4412c0  IN   0.0       0      0  [migration/0]

 

posix regular expression으로 process 정보를 보여줌

crash> ps 'msm*'

crash> ps 'msm*'
   PID    PPID  CPU   TASK    ST  %MEM     VSZ    RSS  COMM
     14      2   0  dc443480  IN   0.0       0      0  [irq/203-msmdata]
     18      2   0  dc6a83c0  IN   0.0       0      0  [msm_slim_ctrl_r]

 

특정프로세스(bt_hc_worker)에서 open하고 있는 파일의목록을 확인해보자.      

crash> files 32565

crash> files 32565
PID: 32565  TASK: c3ffb840  CPU: 0   COMMAND: "bt_hc_worker"
  3  eaef8780  eba79d80  ead3c8c0  CHR   /dev/log/main
  4  eae3de40  eba70780  ead3a190  CHR   /dev/log/radio
  5  ea7029c0  eba73780  ead3ad10  CHR   /dev/log/events
  6  ea74fc00  eba76d80  ead3bce0  CHR   /dev/log/system

 

프로세스의 backtrace(call stack)을 파악할 때 사용함.

crash> bt -tlf 107

crash> bt -tlf 107
PID: 107    TASK: eb66fc00  CPU: 0   COMMAND: "mmcqd/0"
      START: __schedule at c07f66d4
  [eb1a3d9c] handle_irq_event_percpu at c00dcba0
  [eb1a3da8] schedule_timeout at c07f4e20
  [eb1a3dcc] gic_eoi_irq at c001d500

 

디바이스에서사용하고 있는 character device의 목록을 확인할 수 있다.

커널패닉이 발생할 때 이외에 디바이스에 대해 첫 분석을 진행할 때 유용하게 사용할 수 있다.

crash> dev

crash> dev
CHRDEV    NAME              CDEV    OPERATIONS
   1      mem             eb33e2c0  memory_fops
   4      /dev/vc/0       c0f583a4  console_fops
   4      tty             dc668d88  tty_fops
   5      /dev/tty        c0f501ec  tty_fops
   5      /dev/console    c0f50228  console_fops
   5      /dev/ptmx       c0f50350  ptmx_fops
   7      vcs             eb341dc0  vcs_fops
  10      misc            dc67e340  misc_fops
  13      input           dc689c40  input_fops
  21      sg               (none)
  29      fb              dc67de00  fb_fops
  81      video4linux     eb0b0c80  v4l2_fops

 

struct나 주소의 아웃풋을 16진수로 표현하고 싶을 경우에 사용한다.

hex

crash> hex
output radix: 16 (hex)

 

sys 명령어로 현재 시스템의 상태를 파악할 수 있음.

아래와같이 빌드 시간/구동된 시간/메모리 사용량/패닉 reason을 알 수 있음.

crash> sys

crash> sys
      KERNEL: vmlinux
    DUMPFILE: rawdump
        CPUS: 2
        DATE: Sun Feb  9 21:16:26 2014
      UPTIME: 2 days, 06:04:03
LOAD AVERAGE: 8.65, 8.42, 7.68
       TASKS: 770
    NODENAME: localhost
     RELEASE: 3.4.0-perf-g3d4c0e7-00001-g46f9c0a
     VERSION: #1 SMP PREEMPT Tue Feb 4 11:21:16 KST 2014

 

아래명령어로 시스템 콜의 위치를 파악할 수 있음

crash> sys -c

 

설명할필요가 없다. Config 파일의 목록이다.

crash> sys config

crash> sys config
#
# Automatically generated file; DO NOT EDIT.
# Linux/arm 3.4.0 Kernel Configuration
#
CONFIG_ARM=y
CONFIG_ARM_HAS_SG_CHAIN=y

 

crash> struct -o task_struct | grep files

[0x2b8] struct files_struct *files;

 

심볼정보를 보고 싶은 경우 아래와 같은 명령어를 사용함

crash> whatis

crash> whatis linux_banner
const char linux_banner[];
crash> whatis init_task
struct task_struct init_task;

 

커널에서사용하고 있는 모든 타이머를 확인하고 싶은 경우

crash> timer

crash> timer
TVEC_BASES[0]: c0efa0c0
JIFFIES
19434365
EXPIRES  TIMER_LIST  FUNCTION
19434366   dc5838ac   c0403f34  <dhd_watchdog>
19434369   eb0a0c80   c009adc0  <delayed_work_timer_fn>
19434375   c0d4f8a8   c009adc0  <delayed_work_timer_fn>
19434376   eabe1434   c009adc0  <delayed_work_timer_fn>
19434377   d4295e88   c008eb44  <process_timeout>
19434380   c2d4a44c   c009adc0  <delayed_work_timer_fn>
19434385   eb6bf1f0   c009adc0  <delayed_work_timer_fn>
19434400   c0d77dc4   c03818bc  <pm_suspend_timer_fn>
19434400   c0d7ce94   c03818bc  <pm_suspend_timer_fn>
19434400   c2d4a204   c009adc0  <delayed_work_timer_fn>
19434400   eabe15d4   c009adc0  <delayed_work_timer_fn>

 

아래명령어로 심볼의 주소를 알아낼 수 있다.

crash> sym -l | grep start_kern

c07e53a4 (T) secondary_start_kernel
c0c004b0 (T) start_kernel

 

스케줄러의실행 queue를 출력함

crash> runq

crash> runq
CPU 0 RUNQUEUE: c2d4b700
  CURRENT: PID: 32565  TASK: c3ffb840  COMMAND: "bt_hc_worker"
  RT PRIO_ARRAY: c2d4b7d0
     [no tasks queued]
  CFS RB_ROOT: c2d4b770
     [120] PID: 32570  TASK: c3ffbc00  COMMAND: "BluetoothAdapte"
     [120] PID: 9961   TASK: e7aec000  COMMAND: "kworker/u:1"
     [120] PID: 107    TASK: eb66fc00  COMMAND: "mmcqd/0"
 
CPU 1 RUNQUEUE: c2d54700
  CURRENT: PID: 32315  TASK: c98c5a40  COMMAND: "Binder_2"
  RT PRIO_ARRAY: c2d547d0
     [no tasks queued]
  CFS RB_ROOT: c2d54770
     [120] PID: 32302  TASK: e30eb840  COMMAND: "ndroid.settings"
     [130] PID: 32280  TASK: cc63cf00  COMMAND: "Binder_4"

 

네트워크디바이스의 목록을 출력

crash> net

NET_DEVICE  NAME   IP ADDRESS(ES)
dc40b800   lo     127.0.0.1
dc40e000   dummy0

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

 
 

1. How to get .text section dump from vmcore?
Using vmlinux, I am able to look at section information as below.

sys.cpu cortexa53
sys.u

d.load.elf vmlinux

y.l.sec
____________address________________|path\section___________________________|acc|init|physical
P:FFFFFF8008080000--FFFFFF8008081FFF|\\vmlinux\.head.text                   |R-X|L-  |
P:FFFFFF8008082000--FFFFFF800888202F|\\vmlinux\.text                        |R-X|L-  |
D:FFFFFF8008883000--FFFFFF8008AE44F7|\\vmlinux\.rodata                      |R--|L-  |
D:FFFFFF8008AE44F8--FFFFFF8008AE453F|\\vmlinux\.eh_frame                    |R--|L-  |


The .text section where kernel code exists is located between 0xFFFFFF8008082000 and 0xFFFFFF800888202F
So I could dump memory content of .text section using below command.

crash64> rd 0xFFFFFF8008082000 -e 0xFFFFFF800888202F -r kernel_code_dump.bin
8388655 bytes copied from 0xffffff8008082000 to kernel_code_dump.bin


2. Code dump using Trace32 with vmlinux
Run below T32 script and be aware that vmlinux is located in the specified directory.

;****************************************************************************
;**           _Elf_KernelCodeDumpFromELF_ARM64.cmm                                          
;**           This script is to dump kernel-text area memory dump of ARM64 architecture to figure out bit-flip in memory area.         
;**                        
;**
;**       
;** when        who      what, where, why
;** --------------   ------------     ------------------------------------------------------
;** 07/03/2017   austin.kim     First version
;****************************************************************************
Reset

Area.Create IO 80. 100.
Area.Select IO
Area IO

;=====specify the output directory of dump file, start =====
DIALOG.DIR D:\kernel_panic\*
ENTRY &output_dir

print "Text Kernel dump from ELF"

&elf_dump_file="&output_dir"+"/kernel_ro_elf.c"
&load_elf_file_name="&output_dir"+"/vmlinux"

printer.FILE &elf_dump_file
printer.OPEN &elf_dump_file

SYS.CPU cortexa53
SYS.UP

// load vmlinux
d.load.elf &load_elf_file_name 

// dump text section in the kernel ramdump
gosub  procKernelRODump

enddo

; *************************************************************************
; procKernelRODump
;
;   Parse Kernel RO dump
;
; *************************************************************************
procKernelRODump:
  LOCAL &loc_code_start &loc_code_end
  
  printer.FILE &elf_dump_file
  printer.OPEN &elf_dump_file

  &loc_code_start=ADDRESS.OFFSET(sYmbol.SECADDRESS(\\vmlinux\.head.text))
  &loc_code_end=ADDRESS.OFFSET(sYmbol.SECEND(\\vmlinux\.text))
  
  // dump elf memory   
  wp.d.dump &loc_code_start--&loc_code_end

  printer.CLOSE
    
RETURN
// end of procKernelRODump


3. Code dump using Trace32 from kernel_code_dump.bin(vmcore) and vmlinux.

sys.cpu cortexa53
sys.u

d.load.binary kernel_code_dump.bin 0xFFFFFF8008082000
d.load.elf  vmlinux /nocode


And then run below script.

;****************************************************************************
;**           _dumpKernelTextSectionFromRamdump.cmm                                          
;**           This script is to dump kernel-text area memory dump to figure out bit-flip in memory area.         
;**                        
;**
;**       
;** when        who      what, where, why
;** --------------   ------------     ------------------------------------------------------
;** 07/03/2017   austin.kim     First version
;
;                 Attention: Please make sure that this cmm script should be used after kernel ramdump is loaded.
;****************************************************************************

Area.Create IO 80. 100.
Area.Select IO
Area IO

;=====specify the output directory of dump file, start =====
DIALOG.DIR D:\kernel_panic\*
ENTRY &output_dir

print "Text Kernel dump from Ramdump"

printer.FILE &elf_dump_file
printer.OPEN &elf_dump_file

&elf_dump_file="&output_dir"+"/kernel_ro_ramdump.c"

// dump text section in the kernel ramdump
gosub  procKernelRODump

enddo

; *************************************************************************
; procKernelRODump
;
;   Parse Kernel RO dump
;
; *************************************************************************
procKernelRODump:
  LOCAL &loc_code_start &loc_code_end
  
  printer.FILE &elf_dump_file
  printer.OPEN &elf_dump_file

  &loc_code_start=ADDRESS.OFFSET(sYmbol.SECADDRESS(\\vmlinux\.head.text))
  &loc_code_end=ADDRESS.OFFSET(sYmbol.SECEND(\\vmlinux\.text))
  
  // dump elf memory   
  wp.d.dump &loc_code_start--&loc_code_end

  printer.CLOSE
    
RETURN
// end of procKernelRODump


4. Compare kernel_ro_ramdump.c and kernel_ro_elf.c using beyond compare program.







Please be noticed that output files are attached in the 

__schedule() 함수의 구현부
 
MX:FFFFFFC010AD0898|A9B77BFD  __schedule:     stp     x29,x30,[sp,#-0x90]!   ; x29,x30,[sp,#-144]!
MX:FFFFFFC010AD089C|910003FD                  mov     x29,sp
MX:FFFFFFC010AD08A0|A90153F3                  stp     x19,x20,[sp,#0x10]   ; x19,x20,[sp,#16]
MX:FFFFFFC010AD08A4|A9025BF5                  stp     x21,x22,[sp,#0x20]   ; x21,x22,[sp,#32]
MX:FFFFFFC010AD08A8|12001C16                  and     w22,w0,#0xFF     ; w22,preempt,#255
MX:FFFFFFC010AD08AC|D0002935                  adrp    x21,0xFFFFFFC010FF6000   ; x21,dummy_timer_evt
MX:FFFFFFC010AD08B0|A90363F7                  stp     x23,x24,[sp,#0x30]   ; x23,x24,[sp,#48]
MX:FFFFFFC010AD08B4|D5384117                  mrs     x23,#0x3,#0x0,c4,c1,#0x0   ; x23, SP_EL0
MX:FFFFFFC010AD08B8|D00029D8                  adrp    x24,0xFFFFFFC01100A000
MX:FFFFFFC010AD08BC|A9046BF9                  stp     x25,x26,[sp,#0x40]   ; x25,x26,[sp,#64]
MX:FFFFFFC010AD08C0|91188318                  add     x24,x24,#0x620   ; x24,x24,#1568
MX:FFFFFFC010AD08C4|913502B5                  add     x21,x21,#0xD40   ; x21,x21,#3392
MX:FFFFFFC010AD08C8|A90573FB                  stp     x27,x28,[sp,#0x50]   ; x27,x28,[sp,#80]
MX:FFFFFFC010AD08CC|AA1503F3                  mov     x19,x21
 
0xFFFFFFC010AD0898가 vmlinux에서 본 __schedule() 함수의 가상 주소다. 
 
kimage_voffset인 0xffffffbf90000000을 빼자.
 
0x80AD0898 = 0xFFFFFFC010AD0898 - 0xffffffbf90000000 
 
0x80AD0898 주소에 있는 명령어를 보자. __schedule() 함수의 명령어와 완전히 같다.
 
____addr/line|code_____|label____|mnemonic________________|comment
MX:80AD0898|A9B77BFD            stp     x29,x30,[sp,#-0x90]!   ; x29,x30,[sp,#-144]!
MX:80AD089C|910003FD            mov     x29,sp
MX:80AD08A0|A90153F3            stp     x19,x20,[sp,#0x10]   ; x19,x20,[sp,#16]
MX:80AD08A4|A9025BF5            stp     x21,x22,[sp,#0x20]   ; x21,x22,[sp,#32]
MX:80AD08A8|12001C16            and     w22,w0,#0xFF     ; w22,w0,#255
MX:80AD08AC|D0002935            adrp    x21,0x80FF6000
MX:80AD08B0|A90363F7            stp     x23,x24,[sp,#0x30]   ; x23,x24,[sp,#48]
MX:80AD08B4|D5384117            mrs     x23,#0x3,#0x0,c4,c1,#0x0   ; x23, SP_EL0
MX:80AD08B8|D00029D8            adrp    x24,0x8100A000
MX:80AD08BC|A9046BF9            stp     x25,x26,[sp,#0x40]   ; x25,x26,[sp,#64]
MX:80AD08C0|91188318            add     x24,x24,#0x620   ; x24,x24,#1568
MX:80AD08C4|913502B5            add     x21,x21,#0xD40   ; x21,x21,#3392
MX:80AD08C8|A90573FB            stp     x27,x28,[sp,#0x50]   ; x27,x28,[sp,#80]
MX:80AD08CC|AA1503F3            mov     x19,x21
MX:80AD08D0|F90037BE            str     x30,[x29,#0x68]   ; x30,[x29,#104]
MX:80AD08D4|F9428AE0            ldr     x0,[x23,#0x510]   ; x0,[x23,#1296]
MX:80AD08D8|F90047A0            str     x0,[x29,#0x88]   ; x0,[x29,#136]
MX:80AD08DC|D2800000            mov     x0,#0x0          ; x0,#0
MX:80AD08E0|97E6697A            bl      0x8046AEC8
 
이번에는 vmlinux에서 swapper_pg_dir의 주소를 체크하자
 
  (pgd_t [512] *) &swapper_pg_dir = 0xFFFFFFC010F45000 = swapper_pg_dir -> ([0 = 0x0] = ((pgdval_t)
 
0xFFFFFFC010F45000 가 가상 주소다.
 
kimage_voffset인 0xffffffbf90000000을 빼자.
 
0x80F45000 = 0xFFFFFFC010F45000 - 0xffffffbf90000000  
 
0x80F45000로 확인된다.
 
linux_banner
 
  (const char [110] *) &linux_banner = 0xFFFFFFC010AE0090 = linux_banner -> "Linux version 5.4.61 (o
 
____________address|________0________4________8________C_0123456789ABCDEF
MD:FFFFFFC010AE0090|>756E694C 65762078 6F697372 2E35206E Linux version 5.
MD:FFFFFFC010AE00A0| 31362E34 656F2820 6573752D 656F4072 4.61 (oe-user@oe
MD:FFFFFFC010AE00B0| 736F682D 28202974 20636367 73726576 -host) (gcc vers
MD:FFFFFFC010AE00C0| 206E6F69 2E332E39 47282030 29294343 ion 9.3.0 (GCC))
MD:FFFFFFC010AE00D0| 20312320 20504D53 45455250 2054504D  #1 SMP PREEMPT
MD:FFFFFFC010AE00E0| 20646557 20636544 30203232 37353A33 Wed Dec 22 03:57
MD:FFFFFFC010AE00F0| 2035333A 20435455 31323032 0000000A :35 UTC 2021....
 
 
0x80AE0090 = FFFFFFC010AE0090 - 0xffffffbf90000000
 
____address|________0________4________8________C_0123456789ABCDEF
MD:80AE0090|>756E694C 65762078 6F697372 2E35206E Linux version 5.
MD:80AE00A0| 31362E34 656F2820 6573752D 656F4072 4.61 (oe-user@oe
MD:80AE00B0| 736F682D 28202974 20636367 73726576 -host) (gcc vers
MD:80AE00C0| 206E6F69 2E332E39 47282030 29294343 ion 9.3.0 (GCC))
MD:80AE00D0| 20312320 20504D53 45455250 2054504D  #1 SMP PREEMPT
MD:80AE00E0| 20646557 20636544 30203232 37353A33 Wed Dec 22 03:57
MD:80AE00F0| 2035333A 20435455 31323032 0000000A :35 UTC 2021....
MD:80AE0100| 10D69260 FFFFFFC0 00000000 00000000 `...............
vmcore 실행
 
아래와 같은 커맨드를 셸 스크립트로 저장한 다음에 last_run_arm64.sh으로 저장합니다.
 
#!/bin/sh
export CRASH_EXTENSIONS=/home001/austindh.kim/crashtool/crash/extensions
export TRACE_CMD=/home001/austindh.kim/bin/CrashTool/trace-cmd
 
~/ramdumps/99_crash/crash/crash dump.202203252027 vmlinux-5.4.0-105-generic
 
last_run_arm64.sh 셸 스크립트를 실행합니다.
 
(base) austindh.kim:~/ramdumps/kvm_aarch64_coredump$ ./last_run_arm64.sh
 
crash 8.0.0++
Copyright (C) 2002-2021  Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
 
 
crash 8.0.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.
Copyright (C) 2015, 2021  VMware, 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.
 
GNU gdb (GDB) 10.2
Copyright (C) 2021 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-pc-linux-gnu --target=aarch64-elf-linux".
Type "show configuration" for configuration details.
Find the GDB manual and other documentation resources online at:
 
For help, type "help".
Type "apropos word" to search for commands related to "word"...
 
      KERNEL: vmlinux-5.4.0-105-generic
    DUMPFILE: dump.202203252027  [PARTIAL DUMP]
        CPUS: 2
        DATE: Sat Mar 26 05:26:00 KST 2022
      UPTIME: 00:02:36
LOAD AVERAGE: 0.45, 0.48, 0.20
       TASKS: 150
    NODENAME: kim
     RELEASE: 5.4.0-105-generic
     VERSION: #119-Ubuntu SMP Mon Mar 7 18:50:13 UTC 2022
     MACHINE: aarch64  (unknown Mhz)
      MEMORY: 2 GB
       PANIC: "Kernel panic - not syncing: sysrq triggered crash"
         PID: 1098
     COMMAND: "bash"
        TASK: ffff195a20b5bc00  [THREAD_INFO: ffff195a20b5bc00]
         CPU: 0
       STATE: TASK_RUNNING (PANIC)
 
시스템 정보 확인하기
 
잘 로딩되네요. 이번에 mach 명령어를 입력해 커널과 관련된 메모리 설정을 확인하겠습니다.
 
crash> mach
       MACHINE TYPE: aarch64
        MEMORY SIZE: 2 GB
               CPUS: 2
                 HZ: 250
          PAGE SIZE: 4096
KERNEL VIRTUAL BASE: ffff000000000000
KERNEL MODULES BASE: ffff800008000000
KERNEL VMALLOC BASE: ffff800010000000
KERNEL VMEMMAP BASE: fffffdffffe00000
  KERNEL STACK SIZE: 16384
     IRQ STACK SIZE: 16384
         IRQ STACKS:
              CPU 0: ffff800010000000
              CPU 1: ffff800010008000
OVERFLOW STACK SIZE: 4096
    OVERFLOW STACKS:
              CPU 0: ffff195a3fbb42a0
              CPU 1: ffff195a3fbd52a0
 
이번에는 sys 명령어를 입력해 시스템 정보를 확인합니다.   
  
crash> sys
      KERNEL: vmlinux-5.4.0-105-generic
    DUMPFILE: dump.202203252027  [PARTIAL DUMP]
        CPUS: 2
        DATE: Sat Mar 26 05:26:00 KST 2022
      UPTIME: 00:02:36
LOAD AVERAGE: 0.45, 0.48, 0.20
       TASKS: 150
    NODENAME: kim
     RELEASE: 5.4.0-105-generic
     VERSION: #119-Ubuntu SMP Mon Mar 7 18:50:13 UTC 2022
     MACHINE: aarch64  (unknown Mhz)
      MEMORY: 2 GB
       PANIC: "Kernel panic - not syncing: sysrq triggered crash"
   
런큐를 확인하니 CPU 코어의 갯수는 2개이네요.    
   
crash> runq
CPU 0 RUNQUEUE: ffff195a3fbc9e40
  CURRENT: PID: 1098   TASK: ffff195a20b5bc00  COMMAND: "bash"
  RT PRIO_ARRAY: ffff195a3fbca100
     [no tasks queued]
  CFS RB_ROOT: ffff195a3fbc9f78
     [no tasks queued]
 
CPU 1 RUNQUEUE: ffff195a3fbeae40
  CURRENT: PID: 0      TASK: ffff195a3c129e00  COMMAND: "swapper/1"
  RT PRIO_ARRAY: ffff195a3fbeb100
     [no tasks queued]
  CFS RB_ROOT: ffff195a3fbeaf78
     [no tasks queued]
crash>
 
crash> log -m
[    0.000000] <2>Booting Linux on physical CPU 0x0000000000 [0x410fd083]
[    0.000000] <2>Linux version 5.4.0-105-generic (buildd@bos02-arm64-047) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04)) #119-Ubuntu SMP Mon Mar 7 18:50:13 UTC 2022 (Ubuntu 5.4.0-105.119-generic 5.4.174)
[    0.000000] <2>efi: Getting EFI parameters from FDT:
[    0.000000] <2>efi: EFI v2.70 by EDK II
[    0.000000] <2>efi:  SMBIOS 3.0=0xbbef0000  MEMATTR=0xba43d018  ACPI 2.0=0xb8520000  MOKvar=0xba444000  RNG=0xbbffca98  MEMRESERVE=0xb850d718
[    0.000000] <2>efi: seeding entropy pool
[    0.000000] <2>random: fast init done
...
[   27.130013] <2>audit: type=1400 audit(1648239831.635:11): apparmor="STATUS" operation="profile_load" profile="unconfined" name="/usr/lib/NetworkManager/nm-dhcp-client.action" pid=590 comm="apparmor_parser"
[   42.101160] <2>fbcon: Taking over console
[  157.573606] <2>sysrq: Trigger a crash
[  157.579851] <2>Kernel panic - not syncing: sysrq triggered crash
[  157.587393] <2>CPU: 0 PID: 1098 Comm: bash Kdump: loaded Not tainted 5.4.0-105-generic #119-Ubuntu
[  157.598299] <2>Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
[  157.607011] <2>Call trace:
[  157.610187] <2> dump_backtrace+0x0/0x190
[  157.614918] <2> show_stack+0x28/0x38
[  157.619169] <2> dump_stack+0xb4/0x10c
[  157.623689] <2> panic+0x150/0x364
[  157.627649] <2> sysrq_handle_reboot+0x0/0x30
[  157.632842] <2> __handle_sysrq+0x90/0x180
[  157.637666] <2> write_sysrq_trigger+0x138/0x178
[  157.643105] <2> proc_reg_write+0x90/0xe0
[  157.647864] <2> __vfs_write+0x4c/0x90
[  157.652416] <2> vfs_write+0xe8/0x1c8
[  157.657366] <2> ksys_write+0x7c/0x108
[  157.661709] <2> __arm64_sys_write+0x28/0x38
 
vmcore에서 ftrace 추출하기
 
이번에는 vmcore에서 ftrace를 추출하겠습니다. 
 
extend 명령어와 '/home001/austindh.kim/crashtool/crash/extensions/trace.so' 경로를 지정합니다.
 
crash> extend /home001/austindh.kim/crashtool/crash/extensions/trace.so
/home001/austindh.kim/crashtool/crash/extensions/trace.so: shared object loaded
 
'trace show' 명령어를 실행해 vmcore에서 ftrace 메시지를 추출합니다. 
 
crash> trace show
...
 
cpus=2
           <...>-1090  [001]   137.918598: sched_wakeup:         comm=bash pid=1057 prio=120 target_cpu=000
           <...>-1090  [001]   137.918646: sched_switch:         prev_comm=bash prev_pid=1090 prev_prio=120 prev_state=Z ==> next_comm=swapper/1 next_pid=0 next_prio=120
          <idle>-0     [000]   137.918696: sched_switch:         prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=bash next_pid=1057 next_prio=120
            bash-1057  [000]   137.919187: irq_handler_entry:    irq=2 name=arch_timer
            bash-1057  [000]   137.919217: softirq_raise:        vec=1 [action=TIMER]
            bash-1057  [000]   137.919229: softirq_raise:        vec=7 [action=SCHED]
          <idle>-0     [001]   137.919241: irq_handler_entry:    irq=2 name=arch_timer
            bash-1057  [000]   137.919243: irq_handler_exit:     irq=2 ret=handled
...
          <idle>-0     [001]   157.675082: softirq_raise:        vec=1 [action=TIMER]
          <idle>-0     [001]   157.675092: softirq_raise:        vec=7 [action=SCHED]
          <idle>-0     [001]   157.675155: sched_wakeup:         comm=irqbalance pid=647 prio=120 target_cpu=001
          <idle>-0     [001]   157.675162: irq_handler_exit:     irq=2 ret=handled
          <idle>-0     [001]   157.675165: softirq_entry:        vec=1 [action=TIMER]
          <idle>-0     [001]   157.675181: sched_wakeup:         comm=rcu_sched pid=10 prio=120 target_cpu=001
          <idle>-0     [001]   157.675185: softirq_exit:         vec=1 [action=TIMER]
          <idle>-0     [001]   157.675186: softirq_entry:        vec=7 [action=SCHED]
          <idle>-0     [001]   157.675208: softirq_exit:         vec=7 [action=SCHED]
          <idle>-0     [001]   157.675234: sched_switch:         prev_comm=swapper/1 prev_pid=0 prev_prio=120          prev_state=R ==> next_comm=irqbalance next_pid=647 next_prio=120
      irqbalance-647   [001]   157.677484: sched_switch:         prev_comm=irqbalance prev_pid=647 prev_prio=120       prev_state=S ==> next_comm=rcu_sched next_pid=10 next_prio=120
       rcu_sched-10    [001]   157.677579: sched_switch:         prev_comm=rcu_sched prev_pid=10 prev_prio=120         prev_state=I ==> next_comm=swapper/1 next_pid=0 next_prio=120
          <idle>-0     [001]   157.679116: irq_handler_entry:    irq=2 name=arch_timer
          <idle>-0     [001]   157.679239: irq_handler_exit:     irq=2 ret=handled
          <idle>-0     [001]   157.683337: irq_handler_entry:    irq=2 name=arch_timer
          <idle>-0     [001]   157.683497: irq_handler_exit:     irq=2 ret=handled
          <idle>-0     [001]   157.687195: irq_handler_entry:    irq=2 name=arch_timer
          <idle>-0     [001]   157.687279: irq_handler_exit:     irq=2 ret=handled
 
sched_switch와 irq 관련 이벤트를 활성화했군요.
LKDTM 소개
 
LKDTM은 Linux Kernel Dump Test Module (LKDTM)의 약자로 kdump를 활용해 덤프(vmcore)가 제대로 추출되는지 테스트하는 용도로 작성된 드라이버입니다.
 
관련 자료는 아래 링크에서 확인할 수 있습니다.
 
 
LKDTM 소스는 커널 버전이 업그레이드되면서 (불필요하게) 복잡해 졌는데요. 
전체 구조는 예전 v3.18 소스를 보면 더 빨리 파악할 수 있습니다.
 
 
LKDTM 컨피그를 키는 방법
 
LKDTM는 드라이버 모듈 형식으로 빌드하거나 아예 빌트인으로 커널 이미지에 포함되도록 빌드할 수 있습니다. 이번에는 커널 이미지에 LKDTM을 포함시키는 방법을 소개합니다.
 
아래는 LKDTM 컨피그를 키는 예제 코드입니다. 라즈비안 커널 소스 기준입니다.
 
diff --git a/arch/arm64/configs/bcm2711_defconfig b/arch/arm64/configs/bcm2711_defconfig
index 16d756c..191fb28 100644
--- a/arch/arm64/configs/bcm2711_defconfig
+++ b/arch/arm64/configs/bcm2711_defconfig
@@ -16,6 +16,11 @@ CONFIG_IKCONFIG=m
 CONFIG_IKCONFIG_PROC=y
 CONFIG_MEMCG=y
 CONFIG_BLK_CGROUP=y
 CONFIG_DEBUG_INFO=y
+CONFIG_LKDTM=y
 CONFIG_CFS_BANDWIDTH=y
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_FREEZER=y
 
bcm2711_defconfig 파일에 'CONFIG_LKDTM=y' 코드 한 줄이 추가됐음을 확인할 수 있습니다.
위와 같은 커널 컨피그를 적용한 후 빌드를 하면, .config(빌드하면 생성되는)에서 'CONFIG_LKDTM=y'가 확인됩니다.
 
$ vi out/.config
...
CONFIG_FUNCTION_ERROR_INJECTION=y
# CONFIG_FAULT_INJECTION is not set
CONFIG_ARCH_HAS_KCOV=y
CONFIG_RUNTIME_TESTING_MENU=y
CONFIG_LKDTM=y
# CONFIG_TEST_MIN_HEAP is not set
 
'CONFIG_LKDTM=y'을 반영하고 커널을 빌드합니다. 빌드한 다음에 생성되는 커널 이미지를 타겟에 다운로드(플래시)합니다.
 
LKDTM 실행 하기 전 체크 포인트
 
LKDTM 컨피그가 플레시된 타겟 디바이스에서, LKDTM 실행 하기 전에 먼저 아래 파일이 제대로 보이는지 확인해야 합니다.
 
/sys/kernel/debug/provoke-crash
 
만약 위 파일이 보이지 않으면 'CONFIG_LKDTM=y' 컨피그에 제대로 적용되지 않고 빌드됐으니 다시 빌드를 해야 합니다.
 
LKDTM 간략한 코드 리뷰
 
LKDTM을 실행하는 방법을 설명드리기 전에 간단히 LKDTM에 대한 코드를 리뷰합니다.
 
LKDTM은 강제로 크래시를 유발할 수 있는 코드로 구성돼 있으며 각각 종류는 아래 코드에서 확인할 수 있습니다. (v5.4 기준)
 
/* Define the possible types of crashes that can be triggered. */
static const struct crashtype crashtypes[] = {
CRASHTYPE(PANIC),
CRASHTYPE(BUG),
CRASHTYPE(WARNING),
CRASHTYPE(WARNING_MESSAGE),
CRASHTYPE(EXCEPTION),
CRASHTYPE(LOOP),
CRASHTYPE(EXHAUST_STACK),
CRASHTYPE(CORRUPT_STACK),
CRASHTYPE(CORRUPT_STACK_STRONG),
CRASHTYPE(CORRUPT_LIST_ADD),
CRASHTYPE(CORRUPT_LIST_DEL),
CRASHTYPE(CORRUPT_USER_DS),
CRASHTYPE(STACK_GUARD_PAGE_LEADING),
CRASHTYPE(STACK_GUARD_PAGE_TRAILING),
CRASHTYPE(UNSET_SMEP),
CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
CRASHTYPE(OVERWRITE_ALLOCATION),
CRASHTYPE(WRITE_AFTER_FREE),
CRASHTYPE(READ_AFTER_FREE),
CRASHTYPE(WRITE_BUDDY_AFTER_FREE),
CRASHTYPE(READ_BUDDY_AFTER_FREE),
CRASHTYPE(SLAB_FREE_DOUBLE),
CRASHTYPE(SLAB_FREE_CROSS),
CRASHTYPE(SLAB_FREE_PAGE),
CRASHTYPE(SOFTLOCKUP),
CRASHTYPE(HARDLOCKUP),
CRASHTYPE(SPINLOCKUP),
CRASHTYPE(HUNG_TASK),
CRASHTYPE(EXEC_DATA),
CRASHTYPE(EXEC_STACK),
CRASHTYPE(EXEC_KMALLOC),
CRASHTYPE(EXEC_VMALLOC),
CRASHTYPE(EXEC_RODATA),
CRASHTYPE(EXEC_USERSPACE),
CRASHTYPE(EXEC_NULL),
CRASHTYPE(ACCESS_USERSPACE),
CRASHTYPE(ACCESS_NULL),
CRASHTYPE(WRITE_RO),
CRASHTYPE(WRITE_RO_AFTER_INIT),
CRASHTYPE(WRITE_KERN),
CRASHTYPE(REFCOUNT_INC_OVERFLOW),
CRASHTYPE(REFCOUNT_ADD_OVERFLOW),
CRASHTYPE(REFCOUNT_INC_NOT_ZERO_OVERFLOW),
CRASHTYPE(REFCOUNT_ADD_NOT_ZERO_OVERFLOW),
CRASHTYPE(REFCOUNT_DEC_ZERO),
CRASHTYPE(REFCOUNT_DEC_NEGATIVE),
CRASHTYPE(REFCOUNT_DEC_AND_TEST_NEGATIVE),
CRASHTYPE(REFCOUNT_SUB_AND_TEST_NEGATIVE),
CRASHTYPE(REFCOUNT_INC_ZERO),
CRASHTYPE(REFCOUNT_ADD_ZERO),
CRASHTYPE(REFCOUNT_INC_SATURATED),
CRASHTYPE(REFCOUNT_DEC_SATURATED),
CRASHTYPE(REFCOUNT_ADD_SATURATED),
CRASHTYPE(REFCOUNT_INC_NOT_ZERO_SATURATED),
CRASHTYPE(REFCOUNT_ADD_NOT_ZERO_SATURATED),
CRASHTYPE(REFCOUNT_DEC_AND_TEST_SATURATED),
CRASHTYPE(REFCOUNT_SUB_AND_TEST_SATURATED),
CRASHTYPE(REFCOUNT_TIMING),
CRASHTYPE(ATOMIC_TIMING),
CRASHTYPE(USERCOPY_HEAP_SIZE_TO),
CRASHTYPE(USERCOPY_HEAP_SIZE_FROM),
CRASHTYPE(USERCOPY_HEAP_WHITELIST_TO),
CRASHTYPE(USERCOPY_HEAP_WHITELIST_FROM),
CRASHTYPE(USERCOPY_STACK_FRAME_TO),
CRASHTYPE(USERCOPY_STACK_FRAME_FROM),
CRASHTYPE(USERCOPY_STACK_BEYOND),
CRASHTYPE(USERCOPY_KERNEL),
CRASHTYPE(USERCOPY_KERNEL_DS),
CRASHTYPE(STACKLEAK_ERASING),
CRASHTYPE(CFI_FORWARD_PROTO),
}; 
 
크래시 타입 별로 크래시를 유발하는 코드를 확인하는게 중요한데요.
CRASHTYPE(BUG)은 다음 코드에 매핑됩니다.
 
void lkdtm_BUG(void)
{
BUG();
}
 
CRASHTYPE(EXCEPTION)에 매핑되는 루틴은 다음과 같습니다.
 
void lkdtm_EXCEPTION(void)
{
*((volatile int *) 0) = 0;
}
 
제가 위에서 정의된 크래시 타입을 전부 실행했는데, 대부분 크래시가 유발되나 크래시가 유발되지 
않는 경우도 확인했습니다.
 
LKDTM 실행하기
 
(LKDTM 실행하기 전에 먼저 ftrace 이벤트를 활성화하면 좋습니다. vmcore에서 ftrace를 함께 보면 더 많은 디버깅 정보를 확인할 수 있거든요. e.g: sched_switch, irq_handle_entry, irq_handle_exit)
 
LKDTM을 실행하는 방법은 간단합니다. 셸을 하나 열고 아래 포멧으로 명령어를 입력하면 됩니다.
 
$ echo '크래시 타입' > /sys/kernel/debug/provoke-crash/DIRECT
 
몇 가지 예를 들겠습니다. CRASHTYPE(BUG)을 유발하려면 다음과 같은 명령어를 입력하면 됩니다.
 
$ echo BUG > /sys/kernel/debug/provoke-crash/DIRECT
 
'/sys/kernel/debug/provoke-crash/DIRECT'에 BUG 문자열을 전달하면 아래 코드가 실행됩니다.
 
void lkdtm_BUG(void)
{
BUG();
}
 
만약 스택을 오염(Corrupt) 시켜서 크래시를 유발하고 싶으면 아래 명령어를 입력하면 되겠네요.
 
$ echo CORRUPT_STACK > /sys/kernel/debug/provoke-crash/DIRECT
 
위 명령어를 실행하면 lkdtm_CORRUPT_STACK() 함수가 실행되면서 스택을 깹니다.
 
static noinline void __lkdtm_CORRUPT_STACK(void *stack)
{
memset(stack, '\xff', 64);
}
noinline void lkdtm_CORRUPT_STACK(void)
{
/* Use default char array length that triggers stack protection. */
char data[8] __aligned(sizeof(void *));
 
__lkdtm_CORRUPT_STACK(&data);
 
pr_info("Corrupted stack containing char array ...\n");
}
 
data를 char 타입인 배열(8)로 잡았는데, __lkdtm_CORRUPT_STACK() 함수에서 64바이트 사이즈로 메모리 카피를 하니 스택에 '\xff'를 덮어 씁니다. 
 
권장 크래시 타입
 
사실 LKDTM으로 지원되는 크래시 타입을 모두 테스트하면 좋은데요.
실전 프로젝트에서 잘 발생하는 순서로 테스트를 하면 좋을 것 같아요.
 
주석을 달았으니 참고하시면 좋겠네요.
 
static const struct crashtype crashtypes[] = {
CRASHTYPE(PANIC),  /* 테스트 요망 | 자주 발생 | 100% 유발 *'/
CRASHTYPE(BUG), /* 테스트 요망 | 자주 발생 | 100% 유발 *'/
CRASHTYPE(WARNING), /* 테스트 요망 | 발생 가능 | 크래시 유발안됨 *'/
CRASHTYPE(WARNING_MESSAGE),
CRASHTYPE(EXCEPTION), /* 테스트 요망 | 자주 발생 | 100% 유발 *'/
CRASHTYPE(LOOP),
CRASHTYPE(EXHAUST_STACK), /* 테스트 요망 | 종종 발생 | 100% 유발 *'/
CRASHTYPE(CORRUPT_STACK), /* 테스트 요망 | 종종 발생 | 100% 유발 *'/
CRASHTYPE(CORRUPT_STACK_STRONG),
CRASHTYPE(CORRUPT_LIST_ADD), /* 테스트 요망 | 자주 발생 | 100% 유발 *'/
CRASHTYPE(CORRUPT_LIST_DEL),  /* 테스트 요망 | 자주 발생 | 100% 유발 *'/
CRASHTYPE(CORRUPT_USER_DS),  
CRASHTYPE(STACK_GUARD_PAGE_LEADING),
CRASHTYPE(STACK_GUARD_PAGE_TRAILING),
CRASHTYPE(UNSET_SMEP),
CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
CRASHTYPE(OVERWRITE_ALLOCATION),
CRASHTYPE(WRITE_AFTER_FREE), /* 테스트 요망 | 종종 발생(메모리 Corruption) | 100% 유발 *'/
CRASHTYPE(READ_AFTER_FREE),  /* 테스트 요망 | 종종 발생(메모리 Corruption) | 100% 유발 *'/
CRASHTYPE(WRITE_BUDDY_AFTER_FREE),
CRASHTYPE(READ_BUDDY_AFTER_FREE),
CRASHTYPE(SLAB_FREE_DOUBLE),
CRASHTYPE(SLAB_FREE_CROSS),
CRASHTYPE(SLAB_FREE_PAGE),
CRASHTYPE(SOFTLOCKUP), /* 테스트 요망 | 자주 발생 | 100% 유발 *'/
CRASHTYPE(HARDLOCKUP), /* 테스트 요망 | 자주 발생 | 100% 유발 *'/
CRASHTYPE(SPINLOCKUP), /* 테스트 요망 | 종종 발생 | 100% 유발 *'/
CRASHTYPE(HUNG_TASK),
CRASHTYPE(EXEC_DATA),
CRASHTYPE(EXEC_STACK),
CRASHTYPE(EXEC_KMALLOC),
CRASHTYPE(EXEC_VMALLOC),
CRASHTYPE(EXEC_RODATA),
CRASHTYPE(EXEC_USERSPACE),
CRASHTYPE(EXEC_NULL),
CRASHTYPE(ACCESS_USERSPACE),
CRASHTYPE(ACCESS_NULL),
CRASHTYPE(WRITE_RO),
CRASHTYPE(WRITE_RO_AFTER_INIT),
CRASHTYPE(WRITE_KERN),
CRASHTYPE(REFCOUNT_INC_OVERFLOW),
CRASHTYPE(REFCOUNT_ADD_OVERFLOW),
CRASHTYPE(REFCOUNT_INC_NOT_ZERO_OVERFLOW),
CRASHTYPE(REFCOUNT_ADD_NOT_ZERO_OVERFLOW),
CRASHTYPE(REFCOUNT_DEC_ZERO),
CRASHTYPE(REFCOUNT_DEC_NEGATIVE),
CRASHTYPE(REFCOUNT_DEC_AND_TEST_NEGATIVE),
CRASHTYPE(REFCOUNT_SUB_AND_TEST_NEGATIVE),
CRASHTYPE(REFCOUNT_INC_ZERO),
CRASHTYPE(REFCOUNT_ADD_ZERO),
CRASHTYPE(REFCOUNT_INC_SATURATED),
CRASHTYPE(REFCOUNT_DEC_SATURATED),
CRASHTYPE(REFCOUNT_ADD_SATURATED),
CRASHTYPE(REFCOUNT_INC_NOT_ZERO_SATURATED),
CRASHTYPE(REFCOUNT_ADD_NOT_ZERO_SATURATED),
CRASHTYPE(REFCOUNT_DEC_AND_TEST_SATURATED),
CRASHTYPE(REFCOUNT_SUB_AND_TEST_SATURATED),
CRASHTYPE(REFCOUNT_TIMING),
CRASHTYPE(ATOMIC_TIMING),
CRASHTYPE(USERCOPY_HEAP_SIZE_TO),
CRASHTYPE(USERCOPY_HEAP_SIZE_FROM),
CRASHTYPE(USERCOPY_HEAP_WHITELIST_TO),
CRASHTYPE(USERCOPY_HEAP_WHITELIST_FROM),
CRASHTYPE(USERCOPY_STACK_FRAME_TO),
CRASHTYPE(USERCOPY_STACK_FRAME_FROM),
CRASHTYPE(USERCOPY_STACK_BEYOND),
CRASHTYPE(USERCOPY_KERNEL),
CRASHTYPE(USERCOPY_KERNEL_DS),
CRASHTYPE(STACKLEAK_ERASING),
CRASHTYPE(CFI_FORWARD_PROTO),
}; 
 
시그니처
 
LKDTM을 실행한 후 덤프(vmcore)에서 받은 커널 로그를 소개합니다.
 
아래는 'echo EXCEPTION > /sys/kernel/debug/provoke-crash/DIRECT' 명령어를 실행후 받은 덤프에서 확인한 커널 로그입니다.
 
[   57.750675] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[   57.757757] pgd = ffffffc045138000
[   57.761957] [00000000] *pgd=0000000000000000
[   57.765404] Internal error: Oops: 96000045 [#1] PREEMPT SMP
[   57.770949] Modules linked in:
[   57.773996] CPU: 7 PID: 1897 Comm: sh Tainted: G    B   W    3.18.49-g9381d81-00083-gb8bb6a4-dirty #2
[   57.783215] task: ffffffc04e980000 ti: ffffffc0450ec000 task.ti: ffffffc0450ec000
[   57.790665] PC is at lkdtm_do_action+0x44/0x130
[   57.795191] LR is at direct_entry+0x100/0x128
[   57.799511] pc : [<ffffffc0006019e8>] lr : [<ffffffc000601bd4>] pstate: 80000145
[   57.806883] sp : ffffffc0450efdb0
[   57.810213] x29: ffffffc0450efdb0 x28: ffffffc0450ec000 
[   57.815480] x27: ffffffc00163b000 x26: 0000000000000040 
[   57.820774] x25: 0000000000000116 x24: 0000000000000015 
[   57.826068] x23: 0000000000000000 x22: 0000000000000003 
[   57.831370] x21: ffffffc0450efec8 x20: ffffffc02f240000 
[   57.836661] x19: 000000000000000a x18: 00000000ffffffff 
[   57.841956] x17: 0000007fa1e89344 x16: ffffffc0002ffb30 
[   57.847252] x15: 0000007fa1d1c120 x14: 0fffffffffffffff 
[   57.852549] x13: 0000000000000038 x12: 0101010101010101 
[   57.857842] x11: 7f7f7f7f7f7f7f7f x10: ff4d4e48534f4442 
[   57.863146] x9 : 7f7fffffffffffff x8 : 5045435845207972 
[   57.868430] x7 : 746e652074636572 x6 : ffffffc00186ee1f 
[   57.873727] x5 : 000000000000000a x4 : 0000000000000004 
[   57.879023] x3 : 0000000000000000 x2 : ffffffc0450ec000 
[   57.884316] x1 : ffffffc0006019d4 x0 : 0000000000000000 [   57.889316] mdss_mdp_video_wait4comp: vsync wait timeout 0, fallback to poll mode
 
이번에는 'echo WRITE_AFTER_FREE > /sys/kernel/debug/provoke-crash/DIRECT' 명령어를 실행한 다음에 받은 덤프에서 확인한 커널 로그입니다.
 
[   84.609150] lkdtm: Performing direct entry WRITE_AFTER_FREE
[   84.127146] BUG kmalloc-1024 (Tainted: G    B   W   ): Poison overwritten
[   84.133909] -----------------------------------------------------------------------------
[   84.143551] INFO: 0xffffffc00dd31600-0xffffffc00dd319fe. First byte 0x78 instead of 0x6b
[   84.151630] INFO: Allocated in lkdtm_do_action+0xd4/0x130 age=8 cpu=4 pid=4509
[   84.158827] +alloc_debug_processing+0x114/0x16c
[   84.163340] +__slab_alloc.isra.52.constprop.58+0x3f4/0x504
[   84.168805] +kmem_cache_alloc_trace+0x9c/0x1e8
[   84.173234] +lkdtm_do_action+0xd0/0x130
[   84.177053] +direct_entry+0xfc/0x128
[   84.180617] +vfs_write+0xcc/0x178
[   84.183912] +SyS_write+0x44/0x74
[   84.187132] +cpu_switch_to+0x48/0x4c
[   84.190689] INFO: Freed in lkdtm_do_action+0xdc/0x130 age=13 cpu=4 pid=4509
[   84.197629] +free_debug_processing+0x22c/0x2cc
[   84.202054] +__slab_free+0x44/0x2b0
[   84.205525] +kfree+0x1f8/0x218
[   84.208566] +lkdtm_do_action+0xd8/0x130
[   84.212387] +direct_entry+0xfc/0x128
[   84.215943] +vfs_write+0xcc/0x178
[   84.219240] +SyS_write+0x44/0x74
[   84.222454] +cpu_switch_to+0x48/0x4c
[   84.226016] INFO: Slab 0xffffffbc05d12780 objects=23 used=23 fp=0x          (null) flags=0x4080
[   84.243379] Bytes b4 ffffffc00dd315f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
[   84.837991] Object ffffffc00dd319f0: 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78  xxxxxxxxxxxxxxxx
[   84.847280] Redzone ffffffc00dd31a00: bb bb bb bb bb bb bb bb                          ........
[   84.855961] Padding ffffffc00dd31b40: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
[   84.884090] Padding ffffffc00dd31b70: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  ZZZZZZZZZZZZZZZZ
[   84.893467] CPU: 7 PID: 2510 Comm: Binder_10 Tainted: G    B   W    3.10.49-g9381d81-00083-gb8bb6a4-dirty #
디버깅 옵션(-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

;****************************************************************************
;**           save_current_registers.cmm                                           
;**           This script is designed to save current a set of registers.          
;**                        
;**
;**       
;** when        who      what, where, why
;** --------------   ------------     ------------------------------------------------------
;** 04/21/2018   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

&ARCH_MODE=0x0

&ARM_32_BIT_MODE=0x32
&ARM_64_BIT_MODE=0x64

&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 configureARMArchBitMode

; configure a set of registers
if (&ARCH_MODE==&ARM_32_BIT_MODE)
(
    gosub ConfigureRegister32Bit 
)
    
if (&ARCH_MODE==&ARM_64_BIT_MODE)
(
    gosub ConfigureRegister64Bit 
)

close #1

enddo

; *************************************************************************
; configureARMArchBitMode
;
; This function determines ARM architecture mode(ARM32/ARM64)
; *************************************************************************
configureARMArchBitMode:
  LOCAL &next_addr &prev_addr &TEMP_ADDRESS &address_unit
  
  // temp address for testing
  &TEMP_ADDRESS=V.VALUE(&init_task)
  
  &next_addr=V.ADDRESS( ( (struct list_head*)&TEMP_ADDRESS)->next )
  &prev_addr=V.ADDRESS( ( (struct list_head*)&TEMP_ADDRESS)->prev )
  
  &address_unit=&prev_addr-&next_addr
  
  if &address_unit==0x4
  (
   &ARCH_MODE=&ARM_32_BIT_MODE
  )
  
  else if &address_unit==0x8
  (
   &ARCH_MODE=&ARM_64_BIT_MODE
  )
  
  else
  (
   print "invalid fault"
  )
  
RETURN
// end of configureARMArchBitMode

; *************************************************************************
; ConfigureRegister32Bit
;
;   Read current Register and save it.
;
; *************************************************************************
ConfigureRegister32Bit:
  LOCAL &temp
  
  &r0=r(r0)
  &r1=r(r1)
  &r2=r(r2)
  &r3=r(r3)
  &r4=r(r4)
  &r5=r(r5)
  &r6=r(r6)
  &r7=r(r7)
  &r8=r(r8)
  &r9=r(r9)
  &r10=r(r10)
  &r11=r(r11)
  &r12=r(r12)
  &r14=r(r14)  
  &sp=r(r13)
  &pc=r(pc)
  
  write #1 "r.s r0 0x" &r0
  write #1 "r.s r1 0x" &r1
  write #1 "r.s r2 0x" &r2
  write #1 "r.s r3 0x" &r3 
  write #1 "r.s r4 0x" &r4
  write #1 "r.s r5 0x" &r5
  write #1 "r.s r6 0x" &r6
  write #1 "r.s r7 0x" &r7
  write #1 "r.s r8 0x" &r8
  write #1 "r.s r9 0x" &r9
  write #1 "r.s r10 0x" &r10
  write #1 "r.s r11 0x" &r11
  write #1 "r.s r12 0x" &r12
  write #1 "r.s r13 0x" &sp
  write #1 "r.s r14 0x" &r14
  write #1 "r.s pc 0x" &pc
  
//  gosub ConfigureRegister32Bit

RETURN


; *************************************************************************
; ConfigureRegister32Bit
;
;   Read current Register and save it.
;
; *************************************************************************
ConfigureRegister64Bit:
  LOCAL &temp
  
  &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 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 
  
//  gosub ConfigureRegister64Bit

RETURN



리눅스 커널 코드를 분석하다 보면 아래 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)
 
 

 

리눅스 커널이 제공하는 매크로를 그대로 사용할 수 있어서 좋고, 효율적으로 관련 변수를 확인할 수 있어서 좋습니다.
아래와 같이 t32 파일을 수정하면 폰트 사이즈를 LARGE로 변경할 수 있습니다.
 
index d07418b..db9c6c9 100644
--- a/config-sim.t32
+++ b/config-sim.t32

 

@@ -16,7 +16,7 @@ ID=T32
 SYS=${2}                       ; make system directory the same as the executable directory
 
 SCREEN=
-FONT=SMALL
+FONT=LARGE
 HEADER=iTSP - HANCOM MDS GUI ${4}
 
 ; Ethernet on Host information
@@ -26,4 +26,4 @@ CORE=${4}                     ; CORE=1 indicates the primary core that has the trace windowsen
 
 ; Printer settings
 ;PRINTER=WINDOWS
-;-------------------------------------------------------------------------------------------------------------
\ No newline at end of file
+;-------------------------------------------------------------------------------------------------------------
 
 
# Reference: For more information on 'Linux Kernel';
 
디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1
 
디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2
 
1. linked list를 표현하고자 할 경우
아래와 같은 명령어를 입력하면 dcc_tcb의 linked list를 표현한다.
v.chain %l %m %all dcc_tcb dcc_tcb.link.next_ptr
 
2. 특정 변수의 데이터를 dump하고 싶은 경우
var.dump %BIN err_f3_trace_buffer  /orient
 
3. 소스 코드의 패스를 지정
y.spath.srd "Y:\f3_main_src\non_HLOS\modem_proc"
 
4. 소스 코드에서 스트링을 검색
data.grep "err_init" err.c
 
4.1 모든 소스에서  아래 스트링을 검색 
data.grep "err_f3_trace_buffer" 
 
 
5. 현재 심볼의 상태(소스 수, 라인 수)를 표현  -------- good ---------
y.state
 
6. address에 해당하는 소스 파일 이름과 라인 정보를 볼 수 있음  -------- fantastic ---------
y.l.line 0x8D56C460
 
7. register logging
AREA.Create REG_LOG
AREA.OPEN REG_LOG regfile.log
AREA.view REG_LOG
Register.LOG ALL /AREA REG_LOG
[여기서 부터 디버깅 진행 ]
Register.LOG
AREA.CLOSE REG_LOG
 
8. register 정보를 리셋시킴
register.reset
 
9. T32를 사용할 때의 모든 커맨드 사용에 대한 기록을 저장함
LOG.OPEN crash.cmm
... 디버깅 진행 ...
LOG.CLOSE
 
10. y.l.spath 
현재 T32 심볼의 path를 알려줌 
 
11. y.l.tree -------- good ---------
현재 T32 심볼의 address 별로 관련 소스 파일의 이름을 보여줌
 
12. y.l.source  -------- good ---------
현재 T32 심볼에 대한 full source code를 보여줌
소스를 처음 볼때 상당히 좋음 
 
13. y.l.section -------- good ---------
처음 코드를 볼 때 아주 좋음 
현재 코드 전체에 대한 section 정보를 보여줌
 
14. y.RELOCate.List
현재 코드의 빌드 정보를 보여줌 
 
15. sYmbol.Browse.Source
소스 파일 이름으로 심볼을 볼 수 있음 
sYmbol.Browse.Source err.c    
 
16. y.l.l [address] -------- fantastic ---------
address 정보에 대한 local register 정보를 볼 수 있음 
 
17. sYmbol.List.Module   err_init
모듈에 대한 정보를 볼 수 있음 
 
18. sYmbol.List.STACK sbl1_main_ctl
y.l.s
각 address별로 사용하는 stack정보를 파악할 수 있음 
 
19. sYmbol.List.Static 
map 파일에서 선언된 memory region 값 및 static으로 선언된 변수를 확인 가능
fs_rmts_cookie_copy_buffer 
 
18. sYmbol.NEW.Var 
심볼 변수를 새롭게 만듦 
ex) sYmbol.NEW.Var austinLove 0x8cf00000 uint32       
 
19. Data.A [주소] 명령어 -------- fantastic ---------
Data.A 0x8cf000c0 R1=memub(R16+#0x1)
instruction을 바꿀 수 있는 명령어             
 
20. history의 내용을 저장할 수 있는 명령어
history.save "filiename"
 
21. 특정 파일에 디버그 정보를 저장할 수 있음
printer.open "file name"
...명령어 입력...
printer.close "file name"
 
ex) printer.open debug.txt
wp.r
wp.v.f. /a /l /c
wp.v.w %all coredump
printer.close
C:\T32\iTSP\debug.txt 파일이 생성됨
 
22. 특정 함수로 바로 이동할 수 있음
v.c function(param1, param2, ...)
ex)v.c err_init(0)
 
23. 지역변수를 볼 수 있음
v.l %all 
 
24. MMU 정보를 확인
mmu
 
25. 페이지 테이블을 확인
mmu.list.pagetable
mmu.list.KernelPageTable
 
26. 테스크 정보를 읽어옴
task.dtask
 
태스크 별 스택을 프로파일링함
task.stack 
 
>>>
 
&sctlr_el1_reg=0x0
&tcr_el1_reg=0x0
&ttbr0_el1_reg=0x0
&ttbr1_el1_reg=0x0
&esr_el1_reg=0x0
&far_el1_reg=0x0
&contextidr_el1_reg=0x0
&tpidr_el0_reg=0x0
&tpidr_el1_reg=0x0
&tpidrro_el0_reg=0x0
 
&sctlr_el1_reg=V.VALUE(sctlr_el1)
&tcr_el1_reg=V.VALUE(tcr_el1)
&ttbr0_el1_reg=V.VALUE(ttbr0_el1)
&ttbr1_el1_reg=V.VALUE(ttbr1_el1)
&esr_el1_reg=V.VALUE(esr_el1)
&far_el1_reg=V.VALUE(far_el1)
&contextidr_el1_reg=V.VALUE(contextidr_el1)
&tpidr_el0_reg=V.VALUE(tpidr_el0)
&tpidr_el1_reg=V.VALUE(tpidr_el1)
&tpidrro_el0_reg=V.VALUE(tpidrro_el0)
 
&sctlr_el1_reg_t=FORMAT.DECIMAL(0., &sctlr_el1_reg)
 
PER.Set SPR:0x30100 %QUAD &sctlr_el1_reg    // SCTLR_EL1
PER.Set SPR:0x30200 %QUAD &ttbr0_el1_reg    // TTBR0_EL1
PER.Set SPR:0x30201 %QUAD &ttbr1_el1_reg    // TTBR1_EL1
PER.Set SPR:0x30202 %QUAD &tcr_el1_reg      // TCR_EL1
PER.Set SPR:0x30520 %QUAD &esr_el1_reg      // ESR_EL1
PER.Set SPR:0x30600 %QUAD &far_el1_reg      // FAR_EL1
PER.Set SPR:0x30D01 %QUAD &contextidr_el1_reg               // CONTEXTIDR_EL1
PER.Set SPR:0x33D02 %QUAD &tpidr_el0_reg // TPIDR_EL0
PER.Set SPR:0x33D03 %QUAD &tpidrro_el0_reg  // TPIDRRO_EL0
PER.Set SPR:0x33D04 %QUAD &tpidr_el1_reg // TPIDR_EL1
 
mmu.delete
mmu.scan
mmu.on
 
enddo
 
>>>

+ Recent posts