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



리눅스 커널 코드를 분석하다 보면 아래 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 아키텍처의 구조와 원리' 저자>
 
 
 

 

리눅스 커널이 제공하는 매크로를 그대로 사용할 수 있어서 좋고, 효율적으로 관련 변수를 확인할 수 있어서 좋습니다.
디버깅 옵션(-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
 
>>>
config.t32 파일에 다음 명령어를 입력하면 Trace32 폰트 색상이 바뀝니다.
PALETTE 0 = 56 56 56
PALETTE 1 = 221 221 221
PALETTE 4 = 128 0 255
PALETTE 11 = 255 0 0
PALETTE 18 = 255 128 64
PALETTE 27 = 255 128 64
PALETTE 48 = 128 128 0
PALETTE 50 = 255 128 64.
 
Trace32를 열고 setup.color을 입력해서 폰트나 텍스트 상자 색상을 바꿀 수도 있습니다.
 
cmm 스크립트로는 다음과 같은 명령어를 입력하면 됩니다.
//PALETTE 0 = 56 56 56
SETUP.COLOR 0. 56. 56. 56.
 
//PALETTE 1 = 221 221 221
SETUP.COLOR 1. 221. 221. 221.
 
//PALETTE 4 = 128 0 255
SETUP.COLOR 4. 128. 0. 255.
 
//PALETTE 11 = 255 0 0
SETUP.COLOR 11. 255. 0. 0.
 
//PALETTE 18 = 255 128 64
SETUP.COLOR 18. 255. 128. 64.
 
//PALETTE 27 = 255 128 64
SETUP.COLOR 27. 255. 128. 64.
 
//PALETTE 48 = 128 128 0
SETUP.COLOR 48. 128. 128. 0.
 
//PALETTE 50 = 255 128 64.
SETUP.COLOR 50. 255. 128. 64.

+ Recent posts