動機
受不了只能一直放printf與printk來猜到底哪裡錯的日子,所以來看看systemtap 發現他真的很強!!
systemtap
probe
- script -> C -> kernel module
- 基本就是
probe <event> { <handler> }
- event:
what-to-traced-type.suffix1.suffix2....
- 起點與終點
- begin
- end
- error
- 同步
- kernel & module(mpat) & process(pmat) & syscall
- mpat: 放lib的名字,支援
*
,[]
,?
等wildcard - pmat:
pid | "path-to-proc"
- process還可以
- thread: 看生出來的thread
- begin
- end
- 接下面的function, statement
- thread: 看生出來的thread
- syscall的用法:
syscall(num)
或syscall.name
或syscall.*
- syscall提供4個變數:
argstr
,name
,retvat
,retstr
- function(pat) : 函數
- pat:
function-name[@source-path[{:line-number|:first-line-last-line|+relative-line-number}]] | *
- exported
- callee
- callees
- pat:
- statement(pat) : 其中的code
- nearest
- 可以指定觸發的時機
- call
- return
- inline
- 省略就是 call+inline
- 在handler中可以看source code中的變數(context(target) variable)
$var
@var(“varname@src/file.c”)
- 這個能access到extern或是不在scope中的變數
- deref
$var->a
$var[0]
- check cxt var exists
@defined(expr)
- pretty-print
$$var
- print struct
$var$
- nested:
$var$$
- cast (如果struct在不同地方)
@cast(tv, “timeval”, “<sys/time.h>”)->tvsec
tmp = &@cast(tv, “timeval”, “<sys/time.h>”)[0]; tmp->tvsec
- function(pat) : 函數
- mpat: 放lib的名字,支援
- 沒有DWARF(debug訊息)
- kprobe
- module(mpat)
- funtion & statement
- function與module不能用wildcard
- nd_syscall
- kprobe
- kernel & module(mpat) & process(pmat) & syscall
- 異步
- timer
- ms
- jiffies
- profile
- 週期性的在每顆cpu上發作
- timer
- 略過
- procfs: 在systemtap的
/proc/systemtap/mod-name/
中創檔案 - java: 能看java
- input: 能吃stdin
- netfilter: 看netfilter
- perf: 看perf event
- python: 看python
- 還有硬體追蹤的功能,去
man stapprobes
看看吧
- procfs: 在systemtap的
- 起點與終點
- handler
- function:
- buildin
- tid, pid
- execname: 現在跑的proc name
- cpu: cpuid
- gettimeofday_s
- pp: probe目前的位置(配合pat有wildcard時可以印code檔名與行數與函數名)
- ppfunc: 被probe的func name
- print_backtrace: kernel stack
- print_ubacktrace: userspace stack
- thread_indent: 會根據stack深度噴indent
- exit
- 所有builtin
- 自訂
function func_name(var, ...) {}
- embedded c
function func_name(var:type, ...):type %{ ... %}
- 如果要取systemtap的變數要
- 參數:
STAP_ARG_varname
- 全域:
STAP_GLOBAL_GET_varname()
- 怎麼set
- 一般:
STAP_GLOBAL_SET_varname(val)
- array:
STAP_GLOBAL_SET_varname(key1,...,val)
- 一般:
- c的code要加
/* pragma:read:varname */ /* pragma:write:varname */
- 怎麼set
- 參數:
- return時要注意,使用特別語法
STAP_RETURN(expr)
STAP_RETVALUE = expr
- 目前看到的type
- 數字: long
- 字串: string
- buildin
- controll structrue
if (expr) ... else ...
while (expr) ...
for (A;B;C) ...
- comment:
#
,//
,/**/
- str concan: strA . strB
- var
- type: numder, string
var = expr
- scope: block, global
- global will be auto lock&unlock
- global:
global <name>
- data structrue
- array: 其實是hash,只能global
foreach (VALUE = [KEY1, KEY2, …] in ARRAY) STMT
delete array[KEY1, KEY2, …]
if ([KEY1, KEY2, …] in array) ...
- aggregate: 這是
set<int>
,只能用systemtap提供的函數來操作- append:
a <<< <number>
@avg(a) @count(a) @hist_linear @hist_log
- append:
- array: 其實是hash,只能global
- function:
- example:
probe kernel.function("*@net/socket.c") { }
man stapex
- systemtap’s module: tapset
- 與CSS一樣,後面會override前面
- Probe point aliases
- probe的wrapper,或是叫decorator,用python的話來說
probe name.suffix = probe, probe.... { .. }
- 後面就是把
name.suffix
當成一般的probe,但會先跑handler他handler的東西
- stap 參數
- -l PROBE: List matching probes.
- -L PROBE: List matching probes and local variables.
- 據說可以用這個追函數的實際地點(像用wildcard會把所有相關的列出來)
- 但我在我ubuntuVM上都出不來啊
- 還有ubuntu 20.04上的systemtap不能從apt裝,動不了
- -g: guru mode(如果要用embed c的話)
- all man
Ref