]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libpmc/libpmc_json.cc
Implement pci_enable_msi() and pci_disable_msi() in the LinuxKPI.
[FreeBSD/FreeBSD.git] / lib / libpmc / libpmc_json.cc
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2018, Matthew Macy
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  *
29  */
30
31 #include <sys/types.h>
32 #include <sys/sysctl.h>
33 #include <assert.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <limits.h>
37 #include <stddef.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <string>
42 #include <sysexits.h>
43
44 #include <pmc.h>
45 #include <pmcformat.h>
46 #include <pmclog.h>
47
48 using std::string;
49
50 static const char *typenames[] = {
51         "",
52         "{\"type\": \"closelog\"}\n",
53         "{\"type\": \"dropnotify\"}\n",
54         "{\"type\": \"initialize\"",
55         "",
56         "{\"type\": \"pmcallocate\"",
57         "{\"type\": \"pmcattach\"",
58         "{\"type\": \"pmcdetach\"",
59         "{\"type\": \"proccsw\"",
60         "{\"type\": \"procexec\"",
61         "{\"type\": \"procexit\"",
62         "{\"type\": \"procfork\"",
63         "{\"type\": \"sysexit\"",
64         "{\"type\": \"userdata\"",
65         "{\"type\": \"map_in\"",
66         "{\"type\": \"map_out\"",
67         "{\"type\": \"callchain\"",
68         "{\"type\": \"pmcallocatedyn\"",
69         "{\"type\": \"thr_create\"",
70         "{\"type\": \"thr_exit\"",
71         "{\"type\": \"proc_create\"",
72 };
73
74 static string
75 startentry(struct pmclog_ev *ev)
76 {
77         char eventbuf[128];
78
79         snprintf(eventbuf, sizeof(eventbuf), "%s, \"tsc\": \"%jd\"",
80             typenames[ev->pl_type], (uintmax_t)ev->pl_ts.tv_sec);
81         return (string(eventbuf));
82 }
83
84 static string
85 initialize_to_json(struct pmclog_ev *ev)
86 {
87         char eventbuf[256];
88         string startent;
89
90         startent = startentry(ev);
91         snprintf(eventbuf, sizeof(eventbuf),
92             "%s, \"version\": \"0x%08x\", \"arch\": \"0x%08x\", \"cpuid\": \"%s\", "
93                 "\"tsc_freq\": \"%jd\", \"sec\": \"%jd\", \"nsec\": \"%jd\"}\n",
94                 startent.c_str(), ev->pl_u.pl_i.pl_version, ev->pl_u.pl_i.pl_arch,
95                 ev->pl_u.pl_i.pl_cpuid, (uintmax_t)ev->pl_u.pl_i.pl_tsc_freq,
96                 (uintmax_t)ev->pl_u.pl_i.pl_ts.tv_sec, (uintmax_t)ev->pl_u.pl_i.pl_ts.tv_nsec);
97         return string(eventbuf);
98 }
99
100 static string
101 pmcallocate_to_json(struct pmclog_ev *ev)
102 {
103         char eventbuf[256];
104         string startent;
105
106         startent = startentry(ev);
107         snprintf(eventbuf, sizeof(eventbuf),
108             "%s, \"pmcid\": \"0x%08x\", \"event\": \"0x%08x\", \"flags\": \"0x%08x\", "
109             "\"rate\": \"%jd\"}\n",
110                 startent.c_str(), ev->pl_u.pl_a.pl_pmcid, ev->pl_u.pl_a.pl_event,
111             ev->pl_u.pl_a.pl_flags, (intmax_t)ev->pl_u.pl_a.pl_rate);
112         return string(eventbuf);
113 }
114
115 static string
116 pmcattach_to_json(struct pmclog_ev *ev)
117 {
118         char eventbuf[2048];
119         string startent;
120
121         startent = startentry(ev);
122         snprintf(eventbuf, sizeof(eventbuf),
123             "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", \"pathname\": \"%s\"}\n",
124                 startent.c_str(), ev->pl_u.pl_t.pl_pmcid, ev->pl_u.pl_t.pl_pid,
125             ev->pl_u.pl_t.pl_pathname);
126         return string(eventbuf);
127 }
128
129 static string
130 pmcdetach_to_json(struct pmclog_ev *ev)
131 {
132         char eventbuf[128];
133         string startent;
134
135         startent = startentry(ev);
136         snprintf(eventbuf, sizeof(eventbuf),
137                 "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\"}\n",
138                          startent.c_str(), ev->pl_u.pl_d.pl_pmcid, ev->pl_u.pl_d.pl_pid);
139         return string(eventbuf);
140 }
141
142
143 static string
144 proccsw_to_json(struct pmclog_ev *ev)
145 {
146         char eventbuf[128];
147         string startent;
148
149         startent = startentry(ev);
150         snprintf(eventbuf, sizeof(eventbuf), "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\" "
151             "\"tid\": \"%d\", \"value\": \"0x%016jx\"}\n",
152                 startent.c_str(), ev->pl_u.pl_c.pl_pmcid, ev->pl_u.pl_c.pl_pid,
153             ev->pl_u.pl_c.pl_tid, (uintmax_t)ev->pl_u.pl_c.pl_value);
154         return string(eventbuf);
155 }
156
157 static string
158 procexec_to_json(struct pmclog_ev *ev)
159 {
160         char eventbuf[2048];
161         string startent;
162
163         startent = startentry(ev);
164         snprintf(eventbuf, sizeof(eventbuf),
165                 "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", "
166             "\"start\": \"0x%016jx\", \"pathname\": \"%s\"}\n",
167                 startent.c_str(), ev->pl_u.pl_x.pl_pmcid, ev->pl_u.pl_x.pl_pid,
168                 (uintmax_t)ev->pl_u.pl_x.pl_entryaddr, ev->pl_u.pl_x.pl_pathname);
169         return string(eventbuf);
170 }
171
172 static string
173 procexit_to_json(struct pmclog_ev *ev)
174 {
175         char eventbuf[128];
176         string startent;
177
178         startent = startentry(ev);
179         snprintf(eventbuf, sizeof(eventbuf),
180                 "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", "
181             "\"value\": \"0x%016jx\"}\n",
182                 startent.c_str(), ev->pl_u.pl_e.pl_pmcid, ev->pl_u.pl_e.pl_pid,
183             (uintmax_t)ev->pl_u.pl_e.pl_value);
184         return string(eventbuf);
185 }
186
187 static string
188 procfork_to_json(struct pmclog_ev *ev)
189 {
190         char eventbuf[128];
191         string startent;
192
193         startent = startentry(ev);
194         snprintf(eventbuf, sizeof(eventbuf),
195                 "%s, \"oldpid\": \"%d\", \"newpid\": \"%d\"}\n",
196                 startent.c_str(), ev->pl_u.pl_f.pl_oldpid, ev->pl_u.pl_f.pl_newpid);
197         return string(eventbuf);
198 }
199
200 static string
201 sysexit_to_json(struct pmclog_ev *ev)
202 {
203         char eventbuf[128];
204         string startent;
205
206         startent = startentry(ev);
207         snprintf(eventbuf, sizeof(eventbuf), "%s, \"pid\": \"%d\"}\n",
208                 startent.c_str(), ev->pl_u.pl_se.pl_pid);
209         return string(eventbuf);
210 }
211
212 static string
213 userdata_to_json(struct pmclog_ev *ev)
214 {
215         char eventbuf[128];
216         string startent;
217
218         startent = startentry(ev);
219         snprintf(eventbuf, sizeof(eventbuf), "%s, \"userdata\": \"0x%08x\"}\n",
220             startent.c_str(), ev->pl_u.pl_u.pl_userdata);
221         return string(eventbuf);
222 }
223
224 static string
225 map_in_to_json(struct pmclog_ev *ev)
226 {
227         char eventbuf[2048];
228         string startent;
229
230         startent = startentry(ev);
231         snprintf(eventbuf, sizeof(eventbuf), "%s, \"pid\": \"%d\", "
232             "\"start\": \"0x%016jx\", \"pathname\": \"%s\"}\n",
233             startent.c_str(), ev->pl_u.pl_mi.pl_pid,
234             (uintmax_t)ev->pl_u.pl_mi.pl_start, ev->pl_u.pl_mi.pl_pathname);
235         return string(eventbuf);
236 }
237
238 static string
239 map_out_to_json(struct pmclog_ev *ev)
240 {
241         char eventbuf[256];
242         string startent;
243
244         startent = startentry(ev);
245         snprintf(eventbuf, sizeof(eventbuf), "%s, \"pid\": \"%d\", "
246             "\"start\": \"0x%016jx\", \"end\": \"0x%016jx\"}\n",
247             startent.c_str(), ev->pl_u.pl_mi.pl_pid,
248             (uintmax_t)ev->pl_u.pl_mi.pl_start,
249             (uintmax_t)ev->pl_u.pl_mo.pl_end);
250         return string(eventbuf);
251 }
252
253 static string
254 callchain_to_json(struct pmclog_ev *ev)
255 {
256         char eventbuf[1024];
257         string result;
258         uint32_t i;
259         string startent;
260
261         startent = startentry(ev);
262         snprintf(eventbuf, sizeof(eventbuf),
263             "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", \"tid\": \"%d\", "
264             "\"cpuflags\": \"0x%08x\", \"cpuflags2\": \"0x%08x\", \"pc\": [ ",
265                 startent.c_str(), ev->pl_u.pl_cc.pl_pmcid, ev->pl_u.pl_cc.pl_pid,
266             ev->pl_u.pl_cc.pl_tid, ev->pl_u.pl_cc.pl_cpuflags, ev->pl_u.pl_cc.pl_cpuflags2);
267         result = string(eventbuf);
268         for (i = 0; i < ev->pl_u.pl_cc.pl_npc - 1; i++) {
269                 snprintf(eventbuf, sizeof(eventbuf), "\"0x%016jx\", ", (uintmax_t)ev->pl_u.pl_cc.pl_pc[i]);
270                 result += string(eventbuf);
271         }
272         snprintf(eventbuf, sizeof(eventbuf), "\"0x%016jx\"]}\n", (uintmax_t)ev->pl_u.pl_cc.pl_pc[i]);
273         result += string(eventbuf);
274         return (result);
275 }
276
277 static string
278 pmcallocatedyn_to_json(struct pmclog_ev *ev)
279 {
280         char eventbuf[2048];
281         string startent;
282
283         startent = startentry(ev);
284         snprintf(eventbuf, sizeof(eventbuf),
285             "%s, \"pmcid\": \"0x%08x\", \"event\": \"%d\", \"flags\": \"0x%08x\", \"evname\": \"%s\"}\n",
286             startent.c_str(), ev->pl_u.pl_ad.pl_pmcid, ev->pl_u.pl_ad.pl_event,
287             ev->pl_u.pl_ad.pl_flags, ev->pl_u.pl_ad.pl_evname);
288         return string(eventbuf);
289 }
290
291 static string
292 proccreate_to_json(struct pmclog_ev *ev)
293 {
294         char eventbuf[2048];
295         string startent;
296
297         startent = startentry(ev);
298         snprintf(eventbuf, sizeof(eventbuf),
299             "%s, \"pid\": \"%d\", \"flags\": \"0x%08x\", \"pcomm\": \"%s\"}\n",
300             startent.c_str(), ev->pl_u.pl_pc.pl_pid,
301             ev->pl_u.pl_pc.pl_flags, ev->pl_u.pl_pc.pl_pcomm);
302         return string(eventbuf);
303 }
304
305 static string
306 threadcreate_to_json(struct pmclog_ev *ev)
307 {
308         char eventbuf[2048];
309         string startent;
310
311         startent = startentry(ev);
312         snprintf(eventbuf, sizeof(eventbuf),
313             "%s, \"tid\": \"%d\", \"pid\": \"%d\", \"flags\": \"0x%08x\", \"tdname\": \"%s\"}\n",
314             startent.c_str(), ev->pl_u.pl_tc.pl_tid, ev->pl_u.pl_tc.pl_pid,
315             ev->pl_u.pl_tc.pl_flags, ev->pl_u.pl_tc.pl_tdname);
316         return string(eventbuf);
317 }
318
319 static string
320 threadexit_to_json(struct pmclog_ev *ev)
321 {
322         char eventbuf[256];
323         string startent;
324
325         startent = startentry(ev);
326         snprintf(eventbuf, sizeof(eventbuf), "%s, \"tid\": \"%d\"}\n",
327             startent.c_str(), ev->pl_u.pl_te.pl_tid);
328         return string(eventbuf);
329 }
330
331 static string
332 stub_to_json(struct pmclog_ev *ev)
333 {
334         string startent;
335
336         startent = startentry(ev);
337         startent += string("}\n");
338         return startent;
339 }
340
341 typedef string (*jconv) (struct pmclog_ev*);
342
343 static jconv jsonconvert[] = {
344         NULL,
345         stub_to_json,
346         stub_to_json,
347         initialize_to_json,
348         NULL,
349         pmcallocate_to_json,
350         pmcattach_to_json,
351         pmcdetach_to_json,
352         proccsw_to_json,
353         procexec_to_json,
354         procexit_to_json,
355         procfork_to_json,
356         sysexit_to_json,
357         userdata_to_json,
358         map_in_to_json,
359         map_out_to_json,
360         callchain_to_json,
361         pmcallocatedyn_to_json,
362         threadcreate_to_json,
363         threadexit_to_json,
364         proccreate_to_json,
365 };
366
367 string
368 event_to_json(struct pmclog_ev *ev){
369
370         switch (ev->pl_type) {
371         case PMCLOG_TYPE_DROPNOTIFY:
372         case PMCLOG_TYPE_CLOSELOG:
373         case PMCLOG_TYPE_INITIALIZE:
374         case PMCLOG_TYPE_PMCALLOCATE:
375         case PMCLOG_TYPE_PMCATTACH:
376         case PMCLOG_TYPE_PMCDETACH:
377         case PMCLOG_TYPE_PROCCSW:
378         case PMCLOG_TYPE_PROCEXEC:
379         case PMCLOG_TYPE_PROCEXIT:
380         case PMCLOG_TYPE_PROCFORK:
381         case PMCLOG_TYPE_SYSEXIT:
382         case PMCLOG_TYPE_USERDATA:
383         case PMCLOG_TYPE_MAP_IN:
384         case PMCLOG_TYPE_MAP_OUT:
385         case PMCLOG_TYPE_CALLCHAIN:
386         case PMCLOG_TYPE_PMCALLOCATEDYN:
387         case PMCLOG_TYPE_THR_CREATE:
388         case PMCLOG_TYPE_THR_EXIT:
389         case PMCLOG_TYPE_PROC_CREATE:
390                 return jsonconvert[ev->pl_type](ev);
391         default:
392                 errx(EX_USAGE, "ERROR: unrecognized event type: %d\n", ev->pl_type);
393         }
394 }
395