probe-event.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * probe-event.c : perf-probe definition to kprobe_events format converter
  3. *
  4. * Written by Masami Hiramatsu <mhiramat@redhat.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. *
  20. */
  21. #define _GNU_SOURCE
  22. #include <sys/utsname.h>
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <fcntl.h>
  26. #include <errno.h>
  27. #include <stdio.h>
  28. #include <unistd.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #undef _GNU_SOURCE
  32. #include "event.h"
  33. #include "debug.h"
  34. #include "parse-events.h" /* For debugfs_path */
  35. #include "probe-event.h"
  36. #define MAX_CMDLEN 256
  37. #define MAX_PROBE_ARGS 128
  38. #define PERFPROBE_GROUP "probe"
  39. #define semantic_error(msg ...) die("Semantic error :" msg)
  40. /* Parse probepoint definition. */
  41. static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
  42. {
  43. char *ptr, *tmp;
  44. char c, nc = 0;
  45. /*
  46. * <Syntax>
  47. * perf probe SRC:LN
  48. * perf probe FUNC[+OFFS|%return][@SRC]
  49. */
  50. ptr = strpbrk(arg, ":+@%");
  51. if (ptr) {
  52. nc = *ptr;
  53. *ptr++ = '\0';
  54. }
  55. /* Check arg is function or file and copy it */
  56. if (strchr(arg, '.')) /* File */
  57. pp->file = strdup(arg);
  58. else /* Function */
  59. pp->function = strdup(arg);
  60. DIE_IF(pp->file == NULL && pp->function == NULL);
  61. /* Parse other options */
  62. while (ptr) {
  63. arg = ptr;
  64. c = nc;
  65. ptr = strpbrk(arg, ":+@%");
  66. if (ptr) {
  67. nc = *ptr;
  68. *ptr++ = '\0';
  69. }
  70. switch (c) {
  71. case ':': /* Line number */
  72. pp->line = strtoul(arg, &tmp, 0);
  73. if (*tmp != '\0')
  74. semantic_error("There is non-digit charactor"
  75. " in line number.");
  76. break;
  77. case '+': /* Byte offset from a symbol */
  78. pp->offset = strtoul(arg, &tmp, 0);
  79. if (*tmp != '\0')
  80. semantic_error("There is non-digit charactor"
  81. " in offset.");
  82. break;
  83. case '@': /* File name */
  84. if (pp->file)
  85. semantic_error("SRC@SRC is not allowed.");
  86. pp->file = strdup(arg);
  87. DIE_IF(pp->file == NULL);
  88. if (ptr)
  89. semantic_error("@SRC must be the last "
  90. "option.");
  91. break;
  92. case '%': /* Probe places */
  93. if (strcmp(arg, "return") == 0) {
  94. pp->retprobe = 1;
  95. } else /* Others not supported yet */
  96. semantic_error("%%%s is not supported.", arg);
  97. break;
  98. default:
  99. DIE_IF("Program has a bug.");
  100. break;
  101. }
  102. }
  103. /* Exclusion check */
  104. if (pp->line && pp->offset)
  105. semantic_error("Offset can't be used with line number.");
  106. if (!pp->line && pp->file && !pp->function)
  107. semantic_error("File always requires line number.");
  108. if (pp->offset && !pp->function)
  109. semantic_error("Offset requires an entry function.");
  110. if (pp->retprobe && !pp->function)
  111. semantic_error("Return probe requires an entry function.");
  112. if ((pp->offset || pp->line) && pp->retprobe)
  113. semantic_error("Offset/Line can't be used with return probe.");
  114. pr_debug("symbol:%s file:%s line:%d offset:%d, return:%d\n",
  115. pp->function, pp->file, pp->line, pp->offset, pp->retprobe);
  116. }
  117. /* Parse perf-probe event definition */
  118. int parse_perf_probe_event(const char *str, struct probe_point *pp)
  119. {
  120. char *argv[MAX_PROBE_ARGS + 1]; /* probe + args */
  121. int argc, i, need_dwarf = 0;
  122. /* Separate arguments, similar to argv_split */
  123. argc = 0;
  124. do {
  125. /* Skip separators */
  126. while (isspace(*str))
  127. str++;
  128. /* Add an argument */
  129. if (*str != '\0') {
  130. const char *s = str;
  131. /* Check the limit number of arguments */
  132. if (argc == MAX_PROBE_ARGS + 1)
  133. semantic_error("Too many arguments");
  134. /* Skip the argument */
  135. while (!isspace(*str) && *str != '\0')
  136. str++;
  137. /* Duplicate the argument */
  138. argv[argc] = strndup(s, str - s);
  139. if (argv[argc] == NULL)
  140. die("strndup");
  141. pr_debug("argv[%d]=%s\n", argc, argv[argc]);
  142. argc++;
  143. }
  144. } while (*str != '\0');
  145. if (!argc)
  146. semantic_error("An empty argument.");
  147. /* Parse probe point */
  148. parse_perf_probe_probepoint(argv[0], pp);
  149. free(argv[0]);
  150. if (pp->file || pp->line)
  151. need_dwarf = 1;
  152. /* Copy arguments */
  153. pp->nr_args = argc - 1;
  154. if (pp->nr_args > 0) {
  155. pp->args = (char **)malloc(sizeof(char *) * pp->nr_args);
  156. if (!pp->args)
  157. die("malloc");
  158. memcpy(pp->args, &argv[1], sizeof(char *) * pp->nr_args);
  159. }
  160. /* Ensure return probe has no C argument */
  161. for (i = 0; i < pp->nr_args; i++)
  162. if (is_c_varname(pp->args[i])) {
  163. if (pp->retprobe)
  164. semantic_error("You can't specify local"
  165. " variable for kretprobe");
  166. need_dwarf = 1;
  167. }
  168. return need_dwarf;
  169. }
  170. int synthesize_trace_kprobe_event(struct probe_point *pp)
  171. {
  172. char *buf;
  173. int i, len, ret;
  174. pp->probes[0] = buf = zalloc(MAX_CMDLEN);
  175. if (!buf)
  176. die("Failed to allocate memory by zalloc.");
  177. ret = snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset);
  178. if (ret <= 0 || ret >= MAX_CMDLEN)
  179. goto error;
  180. len = ret;
  181. for (i = 0; i < pp->nr_args; i++) {
  182. ret = snprintf(&buf[len], MAX_CMDLEN - len, " %s",
  183. pp->args[i]);
  184. if (ret <= 0 || ret >= MAX_CMDLEN - len)
  185. goto error;
  186. len += ret;
  187. }
  188. pp->found = 1;
  189. return pp->found;
  190. error:
  191. free(pp->probes[0]);
  192. if (ret > 0)
  193. ret = -E2BIG;
  194. return ret;
  195. }
  196. static int write_trace_kprobe_event(int fd, const char *buf)
  197. {
  198. int ret;
  199. ret = write(fd, buf, strlen(buf));
  200. if (ret <= 0)
  201. die("Failed to create event.");
  202. else
  203. printf("Added new event: %s\n", buf);
  204. return ret;
  205. }
  206. void add_trace_kprobe_events(struct probe_point *probes, int nr_probes)
  207. {
  208. int i, j, fd;
  209. struct probe_point *pp;
  210. char buf[MAX_CMDLEN];
  211. snprintf(buf, MAX_CMDLEN, "%s/../kprobe_events", debugfs_path);
  212. fd = open(buf, O_WRONLY, O_APPEND);
  213. if (fd < 0) {
  214. if (errno == ENOENT)
  215. die("kprobe_events file does not exist -"
  216. " please rebuild with CONFIG_KPROBE_TRACER.");
  217. else
  218. die("Could not open kprobe_events file: %s",
  219. strerror(errno));
  220. }
  221. for (j = 0; j < nr_probes; j++) {
  222. pp = probes + j;
  223. if (pp->found == 1) {
  224. snprintf(buf, MAX_CMDLEN, "%c:%s/%s_%x %s\n",
  225. pp->retprobe ? 'r' : 'p', PERFPROBE_GROUP,
  226. pp->function, pp->offset, pp->probes[0]);
  227. write_trace_kprobe_event(fd, buf);
  228. } else
  229. for (i = 0; i < pp->found; i++) {
  230. snprintf(buf, MAX_CMDLEN, "%c:%s/%s_%x_%d %s\n",
  231. pp->retprobe ? 'r' : 'p',
  232. PERFPROBE_GROUP,
  233. pp->function, pp->offset, i,
  234. pp->probes[i]);
  235. write_trace_kprobe_event(fd, buf);
  236. }
  237. }
  238. close(fd);
  239. }