athrill(アスリル)機能マニュアル(データアクセス制御)

#概要
[athrill(アスリル)](https://qiita.com/kanetugu2018/items/cf3dea16710a3f0737e8)のデータアクセス制御について解説します．

#データアクセス制御
##メモリ情報表示(p)
メモリ表示コマンドの書式は以下のとおりです．

```
 * print(p):
   1) print <variable_name>
      show memory information of the <variable_name>
   2) print <addr(hex)> <size>
      show memory information from <addr> to (<addr> + <size>)
   3) print <addr(hex)> <type(s|t)> <typename>
      show memory information from <addr> by <typename>)
```

メモリ表示機能は頻繁に使いますので，機能を豊富にしています．

###1) print \<variable_name\>
変数名を指定して，当該変数のメモリ状態を表示できます．変数はデータ型を持っていますので，データ型に応じた表示に対応しています．以下に代表的なデータ型の表示例を示します(asp3のデータ)．

####プリミティブ型

```
p task_loop
task_loop = (typedef ulong_t )100000 (long unsigned int:4) @ 0x5fff088(0x0)
```

####ポインタ型(typedef)
```
p _kernel_p_runtsk
_kernel_p_runtsk = (TCB *: 4 ) 0x5fff780  @ 0x5fff848(0x0)
```

####構造体型
```
p tSCIF_CB_tab
tSCIF_CB_tab = ( tSCIF_CB ) = {
   = (typedef tSCIF_CB )struct tag_tSCIF_CB {
    _inib = (tSCIF_INIB *: 4 ) 0x713c  @ 0x5fff6e4(0x0)
    initialized = (typedef bool_t )1 (int:4) @ 0x5fff6e8(0x4)
    }
}
```

####配列型

```
p bitmap_search_table
bitmap_search_table = ( unsigned char ) = {
  [0] = 0 (unsigned char:1) @ 0x7651(0x0)
  [1] = 1 (unsigned char:1) @ 0x7652(0x1)
  [2] = 0 (unsigned char:1) @ 0x7653(0x2)
  [3] = 2 (unsigned char:1) @ 0x7654(0x3)
  [4] = 0 (unsigned char:1) @ 0x7655(0x4)
  [5] = 1 (unsigned char:1) @ 0x7656(0x5)
  [6] = 0 (unsigned char:1) @ 0x7657(0x6)
  [7] = 3 (unsigned char:1) @ 0x7658(0x7)
  [8] = 0 (unsigned char:1) @ 0x7659(0x8)
  [9] = 1 (unsigned char:1) @ 0x765a(0x9)
  [10] = 0 (unsigned char:1) @ 0x765b(0xa)
  [11] = 2 (unsigned char:1) @ 0x765c(0xb)
  [12] = 0 (unsigned char:1) @ 0x765d(0xc)
  [13] = 1 (unsigned char:1) @ 0x765e(0xd)
  [14] = 0 (unsigned char:1) @ 0x765f(0xe)
}
```
###構造体・配列型
```
p _kernel_tcb_table
_kernel_tcb_table = ( TCB ) = {
  [0] = (typedef TCB )struct task_control_block {
    task_queue = (typedef QUEUE )struct queue {
      p_next = (struct queue *: 4 ) 0x5fff868  @ 0x5fff760(0x0)
      p_prev = (struct queue *: 4 ) 0x5fff868  @ 0x5fff764(0x4)
      }
    p_tinib = (TINIB *: 4 ) 0x742c  @ 0x5fff768(0x8)
    tstat = (typedef uint8_t )(typedef __uint8_t )8 (unsigned char:1) @ 0x5fff76c(0xc)
    bpriority = (typedef uint8_t )(typedef __uint8_t )2 (unsigned char:1) @ 0x5fff76d(0xd)
    priority = (typedef uint8_t )(typedef __uint8_t )2 (unsigned char:1) @ 0x5fff76e(0xe)
    actque = 134349320 (unsigned int:4) @ 0x5fff76c(0xc)
    wupque = 134349320 (unsigned int:4) @ 0x5fff76c(0xc)
    raster = 134349320 (unsigned int:4) @ 0x5fff76c(0xc)
    enater = 134349320 (unsigned int:4) @ 0x5fff76c(0xc)
    p_winfo = (WINFO *: 4 ) 0x5ffef94  @ 0x5fff770(0x10)
    p_lastmtx = (MTXCB *: 4 ) 0x0  @ 0x5fff774(0x14)
    tskctxb = (typedef TSKCTXB )struct task_context_block {
      sp = (Unknown type: 4 ) 0x5ffef58  @ 0x5fff778(0x18)
      pc = (typedef FP )(typedef TOPPERS_fp_t )(Unknown type: 4 ) 0x317e  @ 0x5fff77c(0x1c)
      }
    }
  [1] = (typedef TCB )struct task_control_block {
    task_queue = (typedef QUEUE )struct queue {
      p_next = (struct queue *: 4 ) 0x5fff7a0  @ 0x5fff780(0x20)
      p_prev = (struct queue *: 4 ) 0x5fff8a0  @ 0x5fff784(0x24)
      }
    p_tinib = (TINIB *: 4 ) 0x7444  @ 0x5fff788(0x28)
    tstat = (typedef uint8_t )(typedef __uint8_t )1 (unsigned char:1) @ 0x5fff78c(0x2c)
    bpriority = (typedef uint8_t )(typedef __uint8_t )9 (unsigned char:1) @ 0x5fff78d(0x2d)
    priority = (typedef uint8_t )(typedef __uint8_t )9 (unsigned char:1) @ 0x5fff78e(0x2e)
    actque = 134809857 (unsigned int:4) @ 0x5fff78c(0x2c)
    wupque = 134809857 (unsigned int:4) @ 0x5fff78c(0x2c)
    raster = 134809857 (unsigned int:4) @ 0x5fff78c(0x2c)
    enater = 134809857 (unsigned int:4) @ 0x5fff78c(0x2c)
    p_winfo = (WINFO *: 4 ) 0x0  @ 0x5fff790(0x30)
    p_lastmtx = (MTXCB *: 4 ) 0x0  @ 0x5fff794(0x34)
    tskctxb = (typedef TSKCTXB )struct task_context_block {
      sp = (Unknown type: 4 ) 0x5ffdf10  @ 0x5fff798(0x38)
      pc = (typedef FP )(typedef TOPPERS_fp_t )(Unknown type: 4 ) 0x3370  @ 0x5fff79c(0x3c)
      }
    }
    :
}
```

###2) print \<addr(hex)\> \<size\>
アドレス番地指定でメモリ情報を参照します．sizeによって表示形式が変わります．

####1バイト
unsigned char型で表示します．

```
p 0x5fff80c 1
size=1 byte
   0 0x5fff80c 0x0      ()
```
####2バイト
unsigned short型で表示します．

```
p 0x5fff80c 2
size=2 byte
0x5fff80c 0x0
```
####4バイト
unsigned int型で表示します．

```
size=4 byte
0x5fff80c 0x8000000
```
####1, 2, 4バイト以外
1, 2, 4バイト以外のサイズ指定があった場合は，１バイトずつ表示します．

```
p 0x5fff80c 8
size=8 byte
   0 0x5fff80c 0x0      ()
   1 0x5fff80d 0x0      ()
   2 0x5fff80e 0x0      ()
   3 0x5fff80f 0x8      )
   4 0x5fff810 0x0      ()
   5 0x5fff811 0x0      ()
   6 0x5fff812 0x0      ()
   7 0x5fff813 0x0      ()
```


###3) print \<addr(hex)\> \<type(s|t)\> \<typename\>
構造体内にポインタ型のメンバがあった場合，その先のメモリ情報を参照したくなりますよね．
そのための表示機能が本機能です．

####構造体型のポインタ
```
p 0x74a4 s task_initialization_block
struct task_initialization_block {
  tskatr = (typedef ATR )(typedef uint_t )0 (unsigned int:4) @ 0x74a4(0x0)
  exinf = (typedef intptr_t )(typedef __intptr_t )0 (int:4) @ 0x74a8(0x4)
  task = (typedef TASK )(Unknown type: 4 ) 0xd00  @ 0x74ac(0x8)
  ipriority = (typedef uint_t )0 (unsigned int:4) @ 0x74b0(0xc)
  stksz = (typedef size_t )4096 (unsigned int:4) @ 0x74b4(0x10)
  stk = (Unknown type: 4 ) 0x5ff9000  @ 0x74b8(0x14)
  }
```
####typedef型のポインタ
```
p 0x74a4 t TINIB
(typedef TINIB )struct task_initialization_block {
  tskatr = (typedef ATR )(typedef uint_t )0 (unsigned int:4) @ 0x74a4(0x0)
  exinf = (typedef intptr_t )(typedef __intptr_t )0 (int:4) @ 0x74a8(0x4)
  task = (typedef TASK )(Unknown type: 4 ) 0xd00  @ 0x74ac(0x8)
  ipriority = (typedef uint_t )0 (unsigned int:4) @ 0x74b0(0xc)
  stksz = (typedef size_t )4096 (unsigned int:4) @ 0x74b4(0x10)
  stk = (Unknown type: 4 ) 0x5ff9000  @ 0x74b8(0x14)
  }
```

##メモリ設定(s)
メモリ設定コマンドの書式は以下のとおりです．

```
 * set(s):
   1) set <addr(hex)> <value>
      set <value> on memory <addr> by byte
```

メモリ設定は，現時点では，１バイトしか書き込みできません．
設定例は以下のとおりです．

[設定前]

```
[DBG>p 0x5fff80c 1
size=1 byte
   0 0x5fff80c 0x0      
```

[設定]

```
[DBG>s 0x5fff80c 255
```

[設定後]

```
[DBG>p 0x5fff80c 1
size=1 byte
   0 0x5fff80c 0xff     
```

##データウォッチ(w)
メモリ破壊バグ解析に欠かせないのが，データウォッチ機能です．CPUが監視対象メモリへのアクセスを検出した場合，CPUの実行を停止しブレークします(メモリアクセス完了後に停止します)．
(OS移植では頻繁に使用しました‥)

```
 * watch(w):
   1) watch {r|w|rw} {<addr(hex)> size(dec)|<variable_name>}
      set a watch point. Watch points are shown using 'info watch' command.
   2) watch d
      delete all watch points
   3) watch d <watch_no>
      delete the watch point of <watch_no>
```

asp3の_kernel_p_runtskのウォッチ実行例を見てみましょう．

[WRITEアクセス]

```
[DBG>w w _kernel_p_runtsk
set watch point 0x5fff848 4
[DBG>info watch
[0] w    0x5fff848 4 _kernel_p_runtsk(+0x0)
[DBG>c
[CPU>
core0 HIT watch data : write access : [0] 0x5fff848 0x0 4
[NEXT> pc=0x82a start.S 93
```

[READアクセス]

```
[DBG>w rw _kernel_p_runtsk
set watch point 0x5fff848 4
[DBG>info watch
[0] r    0x5fff848 4 _kernel_p_runtsk(+0x0)
[DBG>c
[CPU>
ore0 HIT watch data : read access : [0] 0x5fff848 0x5fff760 4
[NEXT> pc=0x320c prc_support.S 288
```

[RWアクセス]

```
[DBG>w rw _kernel_p_runtsk
set watch point 0x5fff848 4
[DBG>info watch
[0] rw   0x5fff848 4 _kernel_p_runtsk(+0x0)
[DBG>c
[CPU>
ore0 HIT watch data : read access : [0] 0x5fff848 0x5fff760 4
[NEXT> pc=0x54e8 semaphore.c 201
```


##メモリREAD/WRITE実行タスク/関数表示(access)
メモリアクセス実行コンテキストがわかると，排他漏れの問題を早期に検出できる可能性が高いと思い，本機能を追加しました．
書式は以下のとおりです．

```
 * access(-):
   1) access <variable_name>
      show variable access functions
```

表示形式は以下の通り．

```
+<clock> [<access type>] [<core>] [access stack] [access func]
```
|項目|説明|
|---|---|
|clock|アクセス発生クロック|
|access type|書き込み=WRITE, 読み込み=READ|
|core|アクセス発生コア|
|access stack|アクセス発生スタック変数(※)|
|access func|アクセス発生関数(アセンブラ関数の場合はunknownと表記される)|

(※)TOPPERS OSの場合，アクセス発生スタック変数から実行コンテキスト(タスク or カーネル)が判別可能

asp3の_kernel_p_schedtskのaccessコマンド実行例を見てみましょう．

```
[DBG>access _kernel_p_schedtsk
* _kernel_p_schedtsk
 + <43640> [WRITE] [core0] [                  _kernel_stack_EXC_TASK] [                       unknown()]
 + <44087> [WRITE] [core0] [                          _kernel_istack] [       _kernel_initialize_task()]
 + <45138> [ READ] [core0] [                            intcfg_table] [                       unknown()]
 + <45630> [WRITE] [core0] [  _kernel_stack_TSKID_tTask_LogTask_Task] [                       ena_dsp()]
 + <254671> [WRITE] [core0] [                 _kernel_stack_MAIN_TASK] [                       ena_dsp()]
 + <255984> [ READ] [core0] [                 _kernel_stack_MAIN_TASK] [         _kernel_make_runnable()]
 + <255995> [ READ] [core0] [                 _kernel_stack_MAIN_TASK] [                       act_tsk()]
 + <256289> [ READ] [core0] [                 _kernel_stack_MAIN_TASK] [     _kernel_make_non_runnable()]
 + <256315> [WRITE] [core0] [                 _kernel_stack_MAIN_TASK] [     _kernel_make_non_runnable()]
 + <256415> [ READ] [core0] [                 _kernel_stack_MAIN_TASK] [                       unknown()]
 + <1536670> [ READ] [core0] [                          _kernel_istack] [         _kernel_make_runnable()]
 + <1536676> [WRITE] [core0] [                          _kernel_istack] [         _kernel_make_runnable()]
 + <1537007> [ READ] [core0] [                     _kernel_stack_TASK1] [                       unknown()]
 + <1552963> [ READ] [core0] [  _kernel_stack_TSKID_tTask_LogTask_Task] [     _kernel_make_non_runnable()]
 + <1552989> [WRITE] [core0] [  _kernel_stack_TSKID_tTask_LogTask_Task] [     _kernel_make_non_runnable()]
 + <1553187> [ READ] [core0] [  _kernel_stack_TSKID_tTask_LogTask_Task] [                       unknown()]

```