runtime/lib_base.c - ktap

Global variables defined

Functions defined

Macros defined

Source code

  1. /*
  2. * lib_base.c - base library
  3. *
  4. * Caveat: all kernel funtion called by ktap library have to be lock free,
  5. * otherwise system will deadlock.
  6. *
  7. * This file is part of ktap by Jovi Zhangwei.
  8. *
  9. * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
  10. *
  11. * ktap is free software; you can redistribute it and/or modify it
  12. * under the terms and conditions of the GNU General Public License,
  13. * version 2, as published by the Free Software Foundation.
  14. *
  15. * ktap is distributed in the hope it will be useful, but WITHOUT
  16. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  17. * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  18. * more details.
  19. *
  20. * You should have received a copy of the GNU General Public License along with
  21. * this program; if not, write to the Free Software Foundation, Inc.,
  22. * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  23. */

  24. #include <linux/version.h>
  25. #include <linux/hardirq.h>
  26. #include <linux/module.h>
  27. #include <linux/kallsyms.h>
  28. #include <linux/sched.h>
  29. #include <linux/uaccess.h>
  30. #include <linux/utsname.h>
  31. #include <linux/time.h>
  32. #include <linux/clocksource.h>
  33. #include <linux/ring_buffer.h>
  34. #include <linux/stacktrace.h>
  35. #include <linux/cred.h>
  36. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
  37. #include <linux/uidgid.h>
  38. #endif
  39. #include "../include/ktap_types.h"
  40. #include "ktap.h"
  41. #include "kp_obj.h"
  42. #include "kp_str.h"
  43. #include "kp_tab.h"
  44. #include "kp_transport.h"
  45. #include "kp_events.h"
  46. #include "kp_vm.h"

  47. static int kplib_print(ktap_state_t *ks)
  48. {
  49.     int i;
  50.     int n = kp_arg_nr(ks);

  51.     for (i = 1; i <= n; i++) {
  52.         ktap_val_t *arg = kp_arg(ks, i);
  53.         if (i > 1)
  54.             kp_puts(ks, "\t");
  55.         kp_obj_show(ks, arg);
  56.     }

  57.     kp_puts(ks, "\n");
  58.     return 0;
  59. }

  60. /* don't engage with intern string in printf, use buffer directly */
  61. static int kplib_printf(ktap_state_t *ks)
  62. {
  63.     struct trace_seq *seq;

  64.     preempt_disable_notrace();

  65.     seq = kp_this_cpu_print_buffer(ks);
  66.     trace_seq_init(seq);

  67.     if (kp_str_fmt(ks, seq))
  68.         goto out;

  69.     seq->buffer[seq->len] = '\0';
  70.     kp_transport_write(ks, seq->buffer, seq->len + 1);

  71. out:
  72.     preempt_enable_notrace();
  73.     return 0;
  74. }

  75. #define HISTOGRAM_DEFAULT_TOP_NUM    20

  76. static int kplib_print_hist(ktap_state_t *ks)
  77. {
  78.     int n ;

  79.     kp_arg_check(ks, 1, KTAP_TTAB);
  80.     n = kp_arg_checkoptnumber(ks, 2, HISTOGRAM_DEFAULT_TOP_NUM);

  81.     n = min(n, 1000);
  82.     n = max(n, HISTOGRAM_DEFAULT_TOP_NUM);

  83.     kp_tab_print_hist(ks, hvalue(kp_arg(ks, 1)), n);

  84.     return 0;
  85. }

  86. static int kplib_pairs(ktap_state_t *ks)
  87. {
  88.     kp_arg_check(ks, 1, KTAP_TTAB);

  89.     set_cfunc(ks->top++, (ktap_cfunction)kp_tab_next);
  90.     set_table(ks->top++, hvalue(kp_arg(ks, 1)));
  91.     set_nil(ks->top++);
  92.     return 3;
  93. }

  94. static int kplib_len(ktap_state_t *ks)
  95. {
  96.     int len = kp_obj_len(ks, kp_arg(ks, 1));

  97.     if (len < 0)
  98.         return -1;

  99.     set_number(ks->top, len);
  100.     incr_top(ks);
  101.     return 1;
  102. }

  103. static int kplib_delete(ktap_state_t *ks)
  104. {
  105.     kp_arg_check(ks, 1, KTAP_TTAB);
  106.     kp_tab_clear(hvalue(kp_arg(ks, 1)));
  107.     return 0;
  108. }

  109. #ifdef CONFIG_STACKTRACE
  110. static int kplib_stack(ktap_state_t *ks)
  111. {
  112.     uint16_t skip, depth = 10;

  113.     depth = kp_arg_checkoptnumber(ks, 1, 10); /* default as 10 */
  114.     depth = min_t(uint16_t, depth, KP_MAX_STACK_DEPTH);
  115.     skip = kp_arg_checkoptnumber(ks, 2, 10); /* default as 10 */

  116.     set_kstack(ks->top, depth, skip);
  117.     incr_top(ks);
  118.     return 1;
  119. }
  120. #else
  121. static int kplib_stack(ktap_state_t *ks)
  122. {
  123.     kp_error(ks, "Please enable CONFIG_STACKTRACE before call stack()\n");
  124.     return -1;
  125. }
  126. #endif


  127. extern unsigned long long ns2usecs(cycle_t nsec);
  128. static int kplib_print_trace_clock(ktap_state_t *ks)
  129. {
  130.     unsigned long long t;
  131.     unsigned long secs, usec_rem;
  132.     u64 timestamp;

  133.     /* use ring buffer's timestamp */
  134.     timestamp = ring_buffer_time_stamp(G(ks)->buffer, smp_processor_id());

  135.     t = ns2usecs(timestamp);
  136.     usec_rem = do_div(t, USEC_PER_SEC);
  137.     secs = (unsigned long)t;

  138.     kp_printf(ks, "%5lu.%06lu\n", secs, usec_rem);
  139.     return 0;
  140. }

  141. static int kplib_num_cpus(ktap_state_t *ks)
  142. {
  143.     set_number(ks->top, num_online_cpus());
  144.     incr_top(ks);
  145.     return 1;
  146. }

  147. /* TODO: intern string firstly */
  148. static int kplib_arch(ktap_state_t *ks)
  149. {
  150.     ktap_str_t *ts = kp_str_newz(ks, utsname()->machine);
  151.     if (unlikely(!ts))
  152.         return -1;

  153.     set_string(ks->top, ts);
  154.     incr_top(ks);
  155.     return 1;
  156. }

  157. /* TODO: intern string firstly */
  158. static int kplib_kernel_v(ktap_state_t *ks)
  159. {
  160.     ktap_str_t *ts = kp_str_newz(ks, utsname()->release);
  161.     if (unlikely(!ts))
  162.         return -1;

  163.     set_string(ks->top, ts);
  164.     incr_top(ks);
  165.     return 1;
  166. }

  167. static int kplib_kernel_string(ktap_state_t *ks)
  168. {
  169.     unsigned long addr = kp_arg_checknumber(ks, 1);
  170.     char str[256] = {0};
  171.     ktap_str_t *ts;
  172.     char *ret;

  173.     ret = strncpy((void *)str, (const void *)addr, 256);
  174.     (void) &ret;  /* Silence compiler warning. */
  175.     str[255] = '\0';

  176.     ts = kp_str_newz(ks, str);
  177.     if (unlikely(!ts))
  178.         return -1;

  179.     set_string(ks->top, ts);
  180.     incr_top(ks);
  181.     return 1;
  182. }

  183. static int kplib_user_string(ktap_state_t *ks)
  184. {
  185.     unsigned long addr = kp_arg_checknumber(ks, 1);
  186.     char str[256] = {0};
  187.     ktap_str_t *ts;
  188.     int ret;

  189.     pagefault_disable();
  190.     ret = __copy_from_user_inatomic((void *)str, (const void *)addr, 256);
  191.     (void) &ret;  /* Silence compiler warning. */
  192.     pagefault_enable();
  193.     str[255] = '\0';

  194.     ts = kp_str_newz(ks, str);
  195.     if (unlikely(!ts))
  196.         return -1;

  197.     set_string(ks->top, ts);
  198.     incr_top(ks);
  199.     return 1;
  200. }

  201. static int kplib_stringof(ktap_state_t *ks)
  202. {
  203.     ktap_val_t *v = kp_arg(ks, 1);
  204.     const ktap_str_t *ts = NULL;

  205.     if (itype(v) == KTAP_TEVENTSTR) {
  206.         ts = kp_event_stringify(ks);
  207.     } else if (itype(v) == KTAP_TKIP) {
  208.         char str[KSYM_SYMBOL_LEN];

  209.         SPRINT_SYMBOL(str, nvalue(v));
  210.         ts = kp_str_newz(ks, str);
  211.     }

  212.     if (unlikely(!ts))
  213.         return -1;

  214.     set_string(ks->top++, ts);
  215.     return 1;
  216. }

  217. static int kplib_ipof(ktap_state_t *ks)
  218. {
  219.     unsigned long addr = kp_arg_checknumber(ks, 1);

  220.     set_ip(ks->top++, addr);
  221.     return 1;
  222. }

  223. static int kplib_gettimeofday_ns(ktap_state_t *ks)
  224. {
  225.     set_number(ks->top, gettimeofday_ns());
  226.     incr_top(ks);

  227.     return 1;
  228. }

  229. static int kplib_gettimeofday_us(ktap_state_t *ks)
  230. {
  231.     set_number(ks->top, gettimeofday_ns() / NSEC_PER_USEC);
  232.     incr_top(ks);

  233.     return 1;
  234. }

  235. static int kplib_gettimeofday_ms(ktap_state_t *ks)
  236. {
  237.     set_number(ks->top, gettimeofday_ns() / NSEC_PER_MSEC);
  238.     incr_top(ks);

  239.     return 1;
  240. }

  241. static int kplib_gettimeofday_s(ktap_state_t *ks)
  242. {
  243.     set_number(ks->top, gettimeofday_ns() / NSEC_PER_SEC);
  244.     incr_top(ks);

  245.     return 1;
  246. }

  247. /*
  248. * use gdb to get field offset of struct task_struct, for example:
  249. *
  250. * gdb vmlinux
  251. * (gdb)p &(((struct task_struct *)0).prio)
  252. */
  253. static int kplib_curr_taskinfo(ktap_state_t *ks)
  254. {
  255.     int offset = kp_arg_checknumber(ks, 1);
  256.     int fetch_bytes  = kp_arg_checkoptnumber(ks, 2, 4); /* fetch 4 bytes */

  257.     if (offset >= sizeof(struct task_struct)) {
  258.         set_nil(ks->top++);
  259.         kp_error(ks, "access out of bound value of task_struct\n");
  260.         return 1;
  261.     }

  262. #define RET_VALUE ((unsigned long)current + offset)

  263.     switch (fetch_bytes) {
  264.     case 4:
  265.         set_number(ks->top, *(unsigned int *)RET_VALUE);
  266.         break;
  267.     case 8:
  268.         set_number(ks->top, *(unsigned long *)RET_VALUE);
  269.         break;
  270.     default:
  271.         kp_error(ks, "unsupported fetch bytes in curr_task_info\n");
  272.         set_nil(ks->top);
  273.         break;
  274.     }

  275. #undef RET_VALUE

  276.     incr_top(ks);
  277.     return 1;
  278. }

  279. /*
  280. * This built-in function mainly purpose scripts/schedule/schedtimes.kp
  281. */
  282. static int kplib_in_iowait(ktap_state_t *ks)
  283. {
  284.     set_number(ks->top, current->in_iowait);
  285.     incr_top(ks);

  286.     return 1;
  287. }

  288. static int kplib_in_interrupt(ktap_state_t *ks)
  289. {
  290.     int ret = in_interrupt();

  291.     set_number(ks->top, ret);
  292.     incr_top(ks);
  293.     return 1;
  294. }

  295. static int kplib_exit(ktap_state_t *ks)
  296. {
  297.     kp_vm_try_to_exit(ks);

  298.     /* do not execute bytecode any more in this thread */
  299.     return -1;
  300. }

  301. static const ktap_libfunc_t base_lib_funcs[] = {
  302.     {"print", kplib_print},
  303.     {"printf", kplib_printf},
  304.     {"print_hist", kplib_print_hist},

  305.     {"pairs", kplib_pairs},
  306.     {"len", kplib_len},
  307.     {"delete", kplib_delete},

  308.     {"stack", kplib_stack},
  309.     {"print_trace_clock", kplib_print_trace_clock},

  310.     {"num_cpus", kplib_num_cpus},
  311.     {"arch", kplib_arch},
  312.     {"kernel_v", kplib_kernel_v},
  313.     {"kernel_string", kplib_kernel_string},
  314.     {"user_string", kplib_user_string},
  315.     {"stringof", kplib_stringof},
  316.     {"ipof", kplib_ipof},

  317.     {"gettimeofday_ns", kplib_gettimeofday_ns},
  318.     {"gettimeofday_us", kplib_gettimeofday_us},
  319.     {"gettimeofday_ms", kplib_gettimeofday_ms},
  320.     {"gettimeofday_s", kplib_gettimeofday_s},

  321.     {"curr_taskinfo", kplib_curr_taskinfo},

  322.     {"in_iowait", kplib_in_iowait},
  323.     {"in_interrupt", kplib_in_interrupt},

  324.     {"exit", kplib_exit},
  325.     {NULL}
  326. };

  327. int kp_lib_init_base(ktap_state_t *ks)
  328. {
  329.     return kp_vm_register_lib(ks, NULL, base_lib_funcs);
  330. }