xref: /aosp_15_r20/external/trace-cmd/lib/trace-cmd/trace-hooks.c (revision 58e6ee5f017f6a8912852c892d18457e4bafb554)
1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3  * Copyright (C) 2015 Red Hat Inc, Steven Rostedt <[email protected]>
4  *
5  */
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <ctype.h>
10 
11 #include "trace-cmd-private.h"
12 #include "trace-cmd-local.h"
13 #include "event-utils.h"
14 
tracecmd_create_event_hook(const char * arg)15 struct hook_list *tracecmd_create_event_hook(const char *arg)
16 {
17 	struct hook_list *hook;
18 	char *system = NULL;
19 	char *event;
20 	char *match;
21 	char *flags = NULL;
22 	char *pid = NULL;
23 	char *str;
24 	char *tok;
25 	int index;
26 	int ch;
27 	int i;
28 
29 	hook = malloc(sizeof(*hook));
30 	if (!hook)
31 		return NULL;
32 	memset(hook, 0, sizeof(*hook));
33 
34 	str = strdup(arg);
35 	if (!str) {
36 		free(hook);
37 		return NULL;
38 	}
39 
40 	hook->str = str;
41 	hook->hook = arg;
42 
43 	/*
44 	 * Hooks are in the form of:
45 	 *  [<start_system>:]<start_event>,<start_match>[,<start_pid>]/
46 	 *  [<end_system>:]<end_event>,<end_match>[,<flags>]
47 	 *
48 	 * Where start_system, start_pid, end_system, and flags are all
49 	 * optional.
50 	 *
51 	 * Flags are (case insensitive):
52 	 *  P - pinned to cpu (wont migrate)
53 	 *  G - global, not hooked to task - currently ignored.
54 	 *  S - save stacks for this event.
55 	 */
56 	tok = strtok(str, ":,");
57 	if (!tok)
58 		goto invalid_tok;
59 
60 	/* See what the token was from the original arg */
61 	index = strlen(tok);
62 	if (arg[index] == ':') {
63 		/* this is a system, the next token must be ',' */
64 		system = tok;
65 		tok = strtok(NULL, ",");
66 		if (!tok)
67 			goto invalid_tok;
68 	}
69 	event = tok;
70 
71 	tok = strtok(NULL, ",/");
72 	if (!tok)
73 		goto invalid_tok;
74 	match = tok;
75 	index = strlen(tok) + tok - str;
76 	if (arg[index] == ',') {
77 		tok = strtok(NULL, "/");
78 		if (!tok)
79 			goto invalid_tok;
80 		pid = tok;
81 	}
82 
83 	hook->start_system = system;
84 	hook->start_event = event;
85 	hook->start_match = match;
86 	hook->pid = pid;
87 
88 	/* Now process the end event */
89 	system = NULL;
90 
91 	tok = strtok(NULL, ":,");
92 	if (!tok)
93 		goto invalid_tok;
94 
95 	/* See what the token was from the original arg */
96 	index = tok - str + strlen(tok);
97 	if (arg[index] == ':') {
98 		/* this is a system, the next token must be ',' */
99 		system = tok;
100 		tok = strtok(NULL, ",");
101 		if (!tok)
102 			goto invalid_tok;
103 	}
104 	event = tok;
105 
106 	tok = strtok(NULL, ",");
107 	if (!tok)
108 		goto invalid_tok;
109 	match = tok;
110 	index = strlen(tok) + tok - str;
111 	if (arg[index] == ',') {
112 		tok = strtok(NULL, "");
113 		if (!tok)
114 			goto invalid_tok;
115 		flags = tok;
116 	}
117 
118 	hook->end_system = system;
119 	hook->end_event = event;
120 	hook->end_match = match;
121 	hook->migrate = 1;
122 	if (flags) {
123 		for (i = 0; flags[i]; i++) {
124 			ch = tolower(flags[i]);
125 			switch (ch) {
126 			case 'p':
127 				hook->migrate = 0;
128 				break;
129 			case 'g':
130 				hook->global = 1;
131 				break;
132 			case 's':
133 				hook->stack = 1;
134 				break;
135 			default:
136 				tracecmd_warning("unknown flag %c", flags[i]);
137 			}
138 		}
139 	}
140 
141 	printf("start %s:%s:%s (%s) end %s:%s:%s (%s)\n",
142 	       hook->start_system,
143 	       hook->start_event,
144 	       hook->start_match,
145 	       hook->pid,
146 	       hook->end_system,
147 	       hook->end_event,
148 	       hook->end_match,
149 	       flags);
150 	return hook;
151 
152 invalid_tok:
153 	tracecmd_warning("Invalid hook format '%s'", arg);
154 	return NULL;
155 }
156 
tracecmd_free_hooks(struct hook_list * hooks)157 void tracecmd_free_hooks(struct hook_list *hooks)
158 {
159 	struct hook_list *hook;
160 
161 	while (hooks) {
162 		hook = hooks;
163 		hooks = hooks->next;
164 
165 		free(hook->str);
166 		free(hook);
167 	}
168 }
169