]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libpmc/libpmc_json.cc
Update to ELF Tool Chain r3668
[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/errno.h>
33 #include <sys/sysctl.h>
34 #include <stddef.h>
35 #include <stdlib.h>
36 #include <err.h>
37 #include <limits.h>
38 #include <string.h>
39 #include <pmc.h>
40 #include <pmclog.h>
41 #include <assert.h>
42 #include <string>
43 #include <sysexits.h>
44 #include <pmcformat.h>
45
46 using std::string;
47
48 static const char *typenames[] = {
49         "",
50         "{\"type\": \"closelog\"}\n",
51         "{\"type\": \"dropnotify\"}\n",
52         "{\"type\": \"initialize\"",
53         "",
54         "{\"type\": \"pmcallocate\"",
55         "{\"type\": \"pmcattach\"",
56         "{\"type\": \"pmcdetach\"",
57         "{\"type\": \"proccsw\"",
58         "{\"type\": \"procexec\"",
59         "{\"type\": \"procexit\"",
60         "{\"type\": \"procfork\"",
61         "{\"type\": \"sysexit\"",
62         "{\"type\": \"userdata\"",
63         "{\"type\": \"map_in\"",
64         "{\"type\": \"map_out\"",
65         "{\"type\": \"callchain\"",
66         "{\"type\": \"pmcallocatedyn\"",
67         "{\"type\": \"thr_create\"",
68         "{\"type\": \"thr_exit\"",
69         "{\"type\": \"proc_create\"",
70 };
71
72 static string
73 startentry(struct pmclog_ev *ev)
74 {
75         char eventbuf[128];
76
77         snprintf(eventbuf, sizeof(eventbuf), "%s, \"tsc\": \"%jd\"",
78             typenames[ev->pl_type], (uintmax_t)ev->pl_ts.tv_sec);
79         return (string(eventbuf));
80 }
81
82 static string
83 initialize_to_json(struct pmclog_ev *ev)
84 {
85         char eventbuf[256];
86         string startent;
87
88         startent = startentry(ev);
89         snprintf(eventbuf, sizeof(eventbuf),
90             "%s, \"version\": \"0x%08x\", \"arch\": \"0x%08x\", \"cpuid\": \"%s\", "
91                 "\"tsc_freq\": \"%jd\", \"sec\": \"%jd\", \"nsec\": \"%jd\"}\n",
92                 startent.c_str(), ev->pl_u.pl_i.pl_version, ev->pl_u.pl_i.pl_arch,
93                 ev->pl_u.pl_i.pl_cpuid, (uintmax_t)ev->pl_u.pl_i.pl_tsc_freq,
94                 (uintmax_t)ev->pl_u.pl_i.pl_ts.tv_sec, (uintmax_t)ev->pl_u.pl_i.pl_ts.tv_nsec);
95         return string(eventbuf);
96 }
97
98 static string
99 pmcallocate_to_json(struct pmclog_ev *ev)
100 {
101         char eventbuf[256];
102         string startent;
103
104         startent = startentry(ev);
105         snprintf(eventbuf, sizeof(eventbuf),
106             "%s, \"pmcid\": \"0x%08x\", \"event\": \"0x%08x\", \"flags\": \"0x%08x\", "
107             "\"rate\": \"%jd\"}\n",
108                 startent.c_str(), ev->pl_u.pl_a.pl_pmcid, ev->pl_u.pl_a.pl_event,
109             ev->pl_u.pl_a.pl_flags, (intmax_t)ev->pl_u.pl_a.pl_rate);
110         return string(eventbuf);
111 }
112
113 static string
114 pmcattach_to_json(struct pmclog_ev *ev)
115 {
116         char eventbuf[2048];
117         string startent;
118
119         startent = startentry(ev);
120         snprintf(eventbuf, sizeof(eventbuf),
121             "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", \"pathname\": \"%s\"}\n",
122                 startent.c_str(), ev->pl_u.pl_t.pl_pmcid, ev->pl_u.pl_t.pl_pid,
123             ev->pl_u.pl_t.pl_pathname);
124         return string(eventbuf);
125 }
126
127 static string
128 pmcdetach_to_json(struct pmclog_ev *ev)
129 {
130         char eventbuf[128];
131         string startent;
132
133         startent = startentry(ev);
134         snprintf(eventbuf, sizeof(eventbuf),
135                 "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\"}\n",
136                          startent.c_str(), ev->pl_u.pl_d.pl_pmcid, ev->pl_u.pl_d.pl_pid);
137         return string(eventbuf);
138 }
139
140
141 static string
142 proccsw_to_json(struct pmclog_ev *ev)
143 {
144         char eventbuf[128];
145         string startent;
146
147         startent = startentry(ev);
148         snprintf(eventbuf, sizeof(eventbuf), "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\" "
149             "\"tid\": \"%d\", \"value\": \"0x%016jx\"}\n",
150                 startent.c_str(), ev->pl_u.pl_c.pl_pmcid, ev->pl_u.pl_c.pl_pid,
151             ev->pl_u.pl_c.pl_tid, (uintmax_t)ev->pl_u.pl_c.pl_value);
152         return string(eventbuf);
153 }
154
155 static string
156 procexec_to_json(struct pmclog_ev *ev)
157 {
158         char eventbuf[2048];
159         string startent;
160
161         startent = startentry(ev);
162         snprintf(eventbuf, sizeof(eventbuf),
163                 "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", "
164             "\"start\": \"0x%016jx\", \"pathname\": \"%s\"}\n",
165                 startent.c_str(), ev->pl_u.pl_x.pl_pmcid, ev->pl_u.pl_x.pl_pid,
166                 (uintmax_t)ev->pl_u.pl_x.pl_entryaddr, ev->pl_u.pl_x.pl_pathname);
167         return string(eventbuf);
168 }
169
170 static string
171 procexit_to_json(struct pmclog_ev *ev)
172 {
173         char eventbuf[128];
174         string startent;
175
176         startent = startentry(ev);
177         snprintf(eventbuf, sizeof(eventbuf),
178                 "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", "
179             "\"value\": \"0x%016jx\"}\n",
180                 startent.c_str(), ev->pl_u.pl_e.pl_pmcid, ev->pl_u.pl_e.pl_pid,
181             (uintmax_t)ev->pl_u.pl_e.pl_value);
182         return string(eventbuf);
183 }
184
185 static string
186 procfork_to_json(struct pmclog_ev *ev)
187 {
188         char eventbuf[128];
189         string startent;
190
191         startent = startentry(ev);
192         snprintf(eventbuf, sizeof(eventbuf),
193                 "%s, \"oldpid\": \"%d\", \"newpid\": \"%d\"}\n",
194                 startent.c_str(), ev->pl_u.pl_f.pl_oldpid, ev->pl_u.pl_f.pl_newpid);
195         return string(eventbuf);
196 }
197
198 static string
199 sysexit_to_json(struct pmclog_ev *ev)
200 {
201         char eventbuf[128];
202         string startent;
203
204         startent = startentry(ev);
205         snprintf(eventbuf, sizeof(eventbuf), "%s, \"pid\": \"%d\"}\n",
206                 startent.c_str(), ev->pl_u.pl_se.pl_pid);
207         return string(eventbuf);
208 }
209
210 static string
211 userdata_to_json(struct pmclog_ev *ev)
212 {
213         char eventbuf[128];
214         string startent;
215
216         startent = startentry(ev);
217         snprintf(eventbuf, sizeof(eventbuf), "%s, \"userdata\": \"0x%08x\"}\n",
218             startent.c_str(), ev->pl_u.pl_u.pl_userdata);
219         return string(eventbuf);
220 }
221
222 static string
223 map_in_to_json(struct pmclog_ev *ev)
224 {
225         char eventbuf[2048];
226         string startent;
227
228         startent = startentry(ev);
229         snprintf(eventbuf, sizeof(eventbuf), "%s, \"pid\": \"%d\", "
230             "\"start\": \"0x%016jx\", \"pathname\": \"%s\"}\n",
231             startent.c_str(), ev->pl_u.pl_mi.pl_pid,
232             (uintmax_t)ev->pl_u.pl_mi.pl_start, ev->pl_u.pl_mi.pl_pathname);
233         return string(eventbuf);
234 }
235
236 static string
237 map_out_to_json(struct pmclog_ev *ev)
238 {
239         char eventbuf[256];
240         string startent;
241
242         startent = startentry(ev);
243         snprintf(eventbuf, sizeof(eventbuf), "%s, \"pid\": \"%d\", "
244             "\"start\": \"0x%016jx\", \"end\": \"0x%016jx\"}\n",
245             startent.c_str(), ev->pl_u.pl_mi.pl_pid,
246             (uintmax_t)ev->pl_u.pl_mi.pl_start,
247             (uintmax_t)ev->pl_u.pl_mo.pl_end);
248         return string(eventbuf);
249 }
250
251 static string
252 callchain_to_json(struct pmclog_ev *ev)
253 {
254         char eventbuf[1024];
255         string result;
256         uint32_t i;
257         string startent;
258
259         startent = startentry(ev);
260         snprintf(eventbuf, sizeof(eventbuf),
261             "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", \"tid\": \"%d\", "
262             "\"cpuflags\": \"0x%08x\", \"cpuflags2\": \"0x%08x\", \"pc\": [ ",
263                 startent.c_str(), ev->pl_u.pl_cc.pl_pmcid, ev->pl_u.pl_cc.pl_pid,
264             ev->pl_u.pl_cc.pl_tid, ev->pl_u.pl_cc.pl_cpuflags, ev->pl_u.pl_cc.pl_cpuflags2);
265         result = string(eventbuf);
266         for (i = 0; i < ev->pl_u.pl_cc.pl_npc - 1; i++) {
267                 snprintf(eventbuf, sizeof(eventbuf), "\"0x%016jx\", ", (uintmax_t)ev->pl_u.pl_cc.pl_pc[i]);
268                 result += string(eventbuf);
269         }
270         snprintf(eventbuf, sizeof(eventbuf), "\"0x%016jx\"]}\n", (uintmax_t)ev->pl_u.pl_cc.pl_pc[i]);
271         result += string(eventbuf);
272         return (result);
273 }
274
275 static string
276 pmcallocatedyn_to_json(struct pmclog_ev *ev)
277 {
278         char eventbuf[2048];
279         string startent;
280
281         startent = startentry(ev);
282         snprintf(eventbuf, sizeof(eventbuf),
283             "%s, \"pmcid\": \"0x%08x\", \"event\": \"%d\", \"flags\": \"0x%08x\", \"evname\": \"%s\"}\n",
284             startent.c_str(), ev->pl_u.pl_ad.pl_pmcid, ev->pl_u.pl_ad.pl_event,
285             ev->pl_u.pl_ad.pl_flags, ev->pl_u.pl_ad.pl_evname);
286         return string(eventbuf);
287 }
288
289 static string
290 proccreate_to_json(struct pmclog_ev *ev)
291 {
292         char eventbuf[2048];
293         string startent;
294
295         startent = startentry(ev);
296         snprintf(eventbuf, sizeof(eventbuf),
297             "%s, \"pid\": \"%d\", \"flags\": \"0x%08x\", \"pcomm\": \"%s\"}\n",
298             startent.c_str(), ev->pl_u.pl_pc.pl_pid,
299             ev->pl_u.pl_pc.pl_flags, ev->pl_u.pl_pc.pl_pcomm);
300         return string(eventbuf);
301 }
302
303 static string
304 threadcreate_to_json(struct pmclog_ev *ev)
305 {
306         char eventbuf[2048];
307         string startent;
308
309         startent = startentry(ev);
310         snprintf(eventbuf, sizeof(eventbuf),
311             "%s, \"tid\": \"%d\", \"pid\": \"%d\", \"flags\": \"0x%08x\", \"tdname\": \"%s\"}\n",
312             startent.c_str(), ev->pl_u.pl_tc.pl_tid, ev->pl_u.pl_tc.pl_pid,
313             ev->pl_u.pl_tc.pl_flags, ev->pl_u.pl_tc.pl_tdname);
314         return string(eventbuf);
315 }
316
317 static string
318 threadexit_to_json(struct pmclog_ev *ev)
319 {
320         char eventbuf[256];
321         string startent;
322
323         startent = startentry(ev);
324         snprintf(eventbuf, sizeof(eventbuf), "%s, \"tid\": \"%d\"}\n",
325             startent.c_str(), ev->pl_u.pl_te.pl_tid);
326         return string(eventbuf);
327 }
328
329 static string
330 stub_to_json(struct pmclog_ev *ev)
331 {
332         string startent;
333
334         startent = startentry(ev);
335         startent += string("}\n");
336         return startent;
337 }
338
339 typedef string (*jconv) (struct pmclog_ev*);
340
341 static jconv jsonconvert[] = {
342         NULL,
343         stub_to_json,
344         stub_to_json,
345         initialize_to_json,
346         NULL,
347         pmcallocate_to_json,
348         pmcattach_to_json,
349         pmcdetach_to_json,
350         proccsw_to_json,
351         procexec_to_json,
352         procexit_to_json,
353         procfork_to_json,
354         sysexit_to_json,
355         userdata_to_json,
356         map_in_to_json,
357         map_out_to_json,
358         callchain_to_json,
359         pmcallocatedyn_to_json,
360         threadcreate_to_json,
361         threadexit_to_json,
362         proccreate_to_json,
363 };
364
365 string
366 event_to_json(struct pmclog_ev *ev){
367
368         switch (ev->pl_type) {
369         case PMCLOG_TYPE_DROPNOTIFY:
370         case PMCLOG_TYPE_CLOSELOG:
371         case PMCLOG_TYPE_INITIALIZE:
372         case PMCLOG_TYPE_PMCALLOCATE:
373         case PMCLOG_TYPE_PMCATTACH:
374         case PMCLOG_TYPE_PMCDETACH:
375         case PMCLOG_TYPE_PROCCSW:
376         case PMCLOG_TYPE_PROCEXEC:
377         case PMCLOG_TYPE_PROCEXIT:
378         case PMCLOG_TYPE_PROCFORK:
379         case PMCLOG_TYPE_SYSEXIT:
380         case PMCLOG_TYPE_USERDATA:
381         case PMCLOG_TYPE_MAP_IN:
382         case PMCLOG_TYPE_MAP_OUT:
383         case PMCLOG_TYPE_CALLCHAIN:
384         case PMCLOG_TYPE_PMCALLOCATEDYN:
385         case PMCLOG_TYPE_THR_CREATE:
386         case PMCLOG_TYPE_THR_EXIT:
387         case PMCLOG_TYPE_PROC_CREATE:
388                 return jsonconvert[ev->pl_type](ev);
389         default:
390                 errx(EX_USAGE, "ERROR: unrecognized event type: %d\n", ev->pl_type);
391         }
392 }
393