動機

受不了只能一直放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
          • syscall的用法: syscall(num)syscall.namesyscall.*
          • 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
            • 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
        • 沒有DWARF(debug訊息)
          • kprobe
            • module(mpat)
            • funtion & statement
            • function與module不能用wildcard
          • nd_syscall
      • 異步
        • timer
          • ms
          • jiffies
          • profile
            • 週期性的在每顆cpu上發作
      • 略過
        • procfs: 在systemtap的/proc/systemtap/mod-name/中創檔案
        • java: 能看java
        • input: 能吃stdin
        • netfilter: 看netfilter
        • perf: 看perf event
        • python: 看python
        • 還有硬體追蹤的功能,去man stapprobes看看吧
    • 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 */
          • return時要注意,使用特別語法
            • STAP_RETURN(expr)
            • STAP_RETVALUE = expr
          • 目前看到的type
            • 數字: long
            • 字串: string
      • 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
    • 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

    短短的tutorial 讚 其他大大的筆記 systemtap的使用技巧 感覺值得深入去看