參考資訊:
https://sourceware.org/systemtap/ftp/releases/
https://sourceware.org/systemtap/SystemTap_Beginners_Guide/index.html
main.stp
probe oneshot
{
printf("hello, world!\n")
}
編譯成C語言
$ stap main.stp -p3 > main.c
module_init() runtime/linux/runtime.h
int init_module (void)
{
int rc;
/* With deliberate hash-collision-inducing data conceivably fed to
stap, it is beneficial to add some runtime-random value to the
map hash. */
get_random_bytes(&stap_hash_seed, sizeof (stap_hash_seed));
rc = systemtap_kernel_module_init();
if (rc)
return rc;
rc = _stp_transport_init();
if (rc)
systemtap_kernel_module_exit();
return rc;
}
SystemTap的init_module()會呼叫systemtap_kernel_module_init(),這個副程式是包含在main.stp編譯出來的*.ko檔案裡面
systemtap_kernel_module_init() main.c
static int systemtap_kernel_module_init (void)
{
int rc = 0;
int i=0, j=0;
if (rc) {
goto out;
}
out:
return rc;
}
_stp_transport_init() runtime/transport/transport.c
/**
* _stp_transport_init() is called from the module initialization.
* It does the bare minimum to exchange commands with staprun
*/
static int _stp_transport_init(void)
{
...
/* create control channel */
ret = _stp_register_ctl_channel();
if (ret < 0)
goto err1;
...
}
由init_module()呼叫的第二個副程式是_stp_transport_init(),主要用來初始化SystemTap相關fs
_stp_register_ctl_channel() runtime/transport/control.c
static int _stp_register_ctl_channel(void)
{
...
if (_stp_register_ctl_channel_fs() != 0) // procfs or debugfs decision time
goto err0;
...
}
_stp_register_ctl_channel_fs() runtime/transport/transport.c
static int _stp_register_ctl_channel_fs(void)
{
...
if (procfs_p)
return _stp_procfs_register_ctl_channel_fs();
...
}
_stp_procfs_register_ctl_channel_fs()用來註冊staprun需要使用的fs
_stp_procfs_register_ctl_channel_fs() runtime/transport/procfs.c
static int _stp_procfs_register_ctl_channel_fs(void)
{
...
#ifdef STAPCONF_PROC_OPS
de = proc_create(".cmd", 0600, _stp_procfs_module_dir, &_stp_ctl_proc_ops_cmd);
#else
de = proc_create(".cmd", 0600, _stp_procfs_module_dir, &_stp_ctl_fops_cmd);
#endif
...
}
_stp_ctl_fops_cmd runtime/transport/control.c
static struct file_operations _stp_ctl_fops_cmd = {
.owner = THIS_MODULE,
.read = _stp_ctl_read_cmd,
.write = _stp_ctl_write_cmd,
.open = _stp_ctl_open_cmd,
.release = _stp_ctl_close_cmd,
.poll = _stp_ctl_poll_cmd
};
#ifdef STAPCONF_PROC_OPS
static struct proc_ops _stp_ctl_proc_ops_cmd = {
.proc_read = _stp_ctl_read_cmd,
.proc_write = _stp_ctl_write_cmd,
.proc_open = _stp_ctl_open_cmd,
.proc_release = _stp_ctl_close_cmd,
.proc_poll = _stp_ctl_poll_cmd
};
#endif
_stp_ctl_write_cmd() runtime/transport/control.c
static ssize_t _stp_ctl_write_cmd(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
...
switch (type) {
case STP_START:
{
static struct _stp_msg_start st;
if (count < sizeof(st)) {
rc = 0; // ?
goto out;
}
if (copy_from_user(&st, buf, sizeof(st))) {
rc = -EFAULT;
goto out;
}
_stp_handle_start(&st);
}
break;
...
}
_stp_handle_start() runtime/transport/transport.c
static void _stp_handle_start(struct _stp_msg_start *st)
{
...
st->res = systemtap_module_init();
...
}
systemtap_module_init() main.c
static int systemtap_module_init (void)
{
...
for (i=0; i<1; i++) {
struct stap_be_probe* stp = &stap_be_probes[i];
if (stp->type == 0)
enter_be_probe(stp); /* rc = 0 */
}
...
}
stap_be_probe main.c
static struct stap_be_probe {
const struct stap_probe * const probe;
int state, type;
} stap_be_probes[] = {
{ .probe=(&stap_probes[0]), .state=STAP_SESSION_STARTING, .type=0 },
};
static struct stap_probe stap_probes[] = {
STAP_PROBE_INIT(0, &probe_6334, "begin", "oneshot", "main.stp:1:7", " from: oneshot from: oneshot"),
};
probe_6334 main.c
static void probe_6334(struct context * __restrict__ c)
{
...
_stp_print("hello, world!\n");
...
}
STP_START是由staprun發起