aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/lib/traceevent/Makefile6
-rw-r--r--tools/lib/traceevent/event-parse.h5
-rw-r--r--tools/lib/traceevent/event-plugin.c202
3 files changed, 212 insertions, 1 deletions
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index fc1502098595..2ccb5bc800e8 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -180,7 +180,11 @@ $(obj)/%.o: $(src)/%.c
180%.o: $(src)/%.c 180%.o: $(src)/%.c
181 $(Q)$(call do_compile) 181 $(Q)$(call do_compile)
182 182
183PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o 183PEVENT_LIB_OBJS = event-parse.o
184PEVENT_LIB_OBJS += event-plugin.o
185PEVENT_LIB_OBJS += trace-seq.o
186PEVENT_LIB_OBJS += parse-filter.o
187PEVENT_LIB_OBJS += parse-utils.o
184PEVENT_LIB_OBJS += kbuffer-parse.o 188PEVENT_LIB_OBJS += kbuffer-parse.o
185 189
186ALL_OBJS = $(PEVENT_LIB_OBJS) 190ALL_OBJS = $(PEVENT_LIB_OBJS)
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 8d73d2594f65..a28886066bcc 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -377,6 +377,11 @@ enum pevent_errno {
377}; 377};
378#undef _PE 378#undef _PE
379 379
380struct plugin_list;
381
382struct plugin_list *traceevent_load_plugins(struct pevent *pevent);
383void traceevent_unload_plugins(struct plugin_list *plugin_list);
384
380struct cmdline; 385struct cmdline;
381struct cmdline_list; 386struct cmdline_list;
382struct func_map; 387struct func_map;
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c
new file mode 100644
index 000000000000..d272d87aa7d4
--- /dev/null
+++ b/tools/lib/traceevent/event-plugin.c
@@ -0,0 +1,202 @@
1/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20
21#include <string.h>
22#include <dlfcn.h>
23#include <stdlib.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <unistd.h>
27#include <dirent.h>
28#include "event-parse.h"
29#include "event-utils.h"
30
31#define LOCAL_PLUGIN_DIR ".traceevent/plugins"
32
33struct plugin_list {
34 struct plugin_list *next;
35 char *name;
36 void *handle;
37};
38
39static void
40load_plugin(struct pevent *pevent, const char *path,
41 const char *file, void *data)
42{
43 struct plugin_list **plugin_list = data;
44 pevent_plugin_load_func func;
45 struct plugin_list *list;
46 const char *alias;
47 char *plugin;
48 void *handle;
49
50 plugin = malloc_or_die(strlen(path) + strlen(file) + 2);
51
52 strcpy(plugin, path);
53 strcat(plugin, "/");
54 strcat(plugin, file);
55
56 handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL);
57 if (!handle) {
58 warning("could not load plugin '%s'\n%s\n",
59 plugin, dlerror());
60 goto out_free;
61 }
62
63 alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME);
64 if (!alias)
65 alias = file;
66
67 func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME);
68 if (!func) {
69 warning("could not find func '%s' in plugin '%s'\n%s\n",
70 PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror());
71 goto out_free;
72 }
73
74 list = malloc_or_die(sizeof(*list));
75 list->next = *plugin_list;
76 list->handle = handle;
77 list->name = plugin;
78 *plugin_list = list;
79
80 pr_stat("registering plugin: %s", plugin);
81 func(pevent);
82 return;
83
84 out_free:
85 free(plugin);
86}
87
88static void
89load_plugins_dir(struct pevent *pevent, const char *suffix,
90 const char *path,
91 void (*load_plugin)(struct pevent *pevent,
92 const char *path,
93 const char *name,
94 void *data),
95 void *data)
96{
97 struct dirent *dent;
98 struct stat st;
99 DIR *dir;
100 int ret;
101
102 ret = stat(path, &st);
103 if (ret < 0)
104 return;
105
106 if (!S_ISDIR(st.st_mode))
107 return;
108
109 dir = opendir(path);
110 if (!dir)
111 return;
112
113 while ((dent = readdir(dir))) {
114 const char *name = dent->d_name;
115
116 if (strcmp(name, ".") == 0 ||
117 strcmp(name, "..") == 0)
118 continue;
119
120 /* Only load plugins that end in suffix */
121 if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0)
122 continue;
123
124 load_plugin(pevent, path, name, data);
125 }
126
127 closedir(dir);
128}
129
130static void
131load_plugins(struct pevent *pevent, const char *suffix,
132 void (*load_plugin)(struct pevent *pevent,
133 const char *path,
134 const char *name,
135 void *data),
136 void *data)
137{
138 char *home;
139 char *path;
140 char *envdir;
141
142 /*
143 * If a system plugin directory was defined,
144 * check that first.
145 */
146#ifdef PLUGIN_DIR
147 load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data);
148#endif
149
150 /*
151 * Next let the environment-set plugin directory
152 * override the system defaults.
153 */
154 envdir = getenv("TRACEEVENT_PLUGIN_DIR");
155 if (envdir)
156 load_plugins_dir(pevent, suffix, envdir, load_plugin, data);
157
158 /*
159 * Now let the home directory override the environment
160 * or system defaults.
161 */
162 home = getenv("HOME");
163 if (!home)
164 return;
165
166 path = malloc_or_die(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2);
167
168 strcpy(path, home);
169 strcat(path, "/");
170 strcat(path, LOCAL_PLUGIN_DIR);
171
172 load_plugins_dir(pevent, suffix, path, load_plugin, data);
173
174 free(path);
175}
176
177struct plugin_list*
178traceevent_load_plugins(struct pevent *pevent)
179{
180 struct plugin_list *list = NULL;
181
182 load_plugins(pevent, ".so", load_plugin, &list);
183 return list;
184}
185
186void
187traceevent_unload_plugins(struct plugin_list *plugin_list)
188{
189 pevent_plugin_unload_func func;
190 struct plugin_list *list;
191
192 while (plugin_list) {
193 list = plugin_list;
194 plugin_list = list->next;
195 func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME);
196 if (func)
197 func();
198 dlclose(list->handle);
199 free(list->name);
200 free(list);
201 }
202}