2 * Copyright (c) 2009, 2010 Aggelos Economopoulos. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
14 * 3. Neither the name of The DragonFly Project nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific, prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 #include <sys/param.h>
42 #include <sys/queue.h>
54 printd_set_flags(const char *str, unsigned int *flags)
57 * This is suboptimal as we don't detect
66 err(2, "invalid debug flag %c\n", *str);
67 *flags |= 1 << (*str - 'a');
73 MAX_EVHDR_SIZE = PATH_MAX + 200,
74 /* string namespaces */
79 NR_BUCKETS = 1021, /* prime */
80 PARSE_ERR_BUFSIZE = 256,
82 REC_BOUNDARY = 1 << 14,
84 EVTRF_WR = 0x1, /* open for writing */
88 typedef uint16_t fileid_t;
89 typedef uint16_t funcid_t;
90 typedef uint16_t fmtid_t;
92 struct trace_event_header {
94 uint64_t ts; /* XXX: this should only be part of probe */
95 } __attribute__((packed));
97 struct probe_event_header {
98 struct trace_event_header eh;
100 * For these fields, 0 implies "not available"
109 uint8_t cpu; /* -1 if n/a */
110 } __attribute__((packed));
112 struct string_event_header {
113 struct trace_event_header eh;
117 } __attribute__((packed));
119 struct fmt_event_header {
120 struct trace_event_header eh;
124 } __attribute__((packed));
126 struct cpuinfo_event_header {
129 } __attribute__((packed));
134 struct hashentry *next;
138 struct hashentry *buckets[NR_BUCKETS];
139 uintptr_t (*hashfunc)(uintptr_t);
140 uintptr_t (*cmpfunc)(uintptr_t, uintptr_t);
152 struct event_filter_unresolved {
153 TAILQ_ENTRY(event_filter_unresolved) link;
158 RB_ENTRY(id_map) rb_node;
163 RB_HEAD(id_tree, id_map);
172 RB_HEAD(thread_tree, evtr_thread);
175 struct thread_tree root;
178 struct event_callback {
179 void (*cb)(evtr_event_t, void *data);
180 void *data; /* this field must be malloc()ed */
184 struct evtr_thread *td; /* currently executing thread */
196 * When writing, we keep track of the strings we've
197 * already dumped so we only dump them once.
198 * Paths, function names etc belong to different
201 struct hashtab_str *strings[EVTR_NS_MAX - 1];
203 * When reading, we build a map from id to string.
204 * Every id must be defined at the point of use.
206 struct string_map maps[EVTR_NS_MAX - 1];
209 /* same as above, but for subsys+fmt pairs */
210 struct fmt_map fmtmap;
211 struct hashtab_str *fmts;
213 struct thread_map threads;
227 struct symtab *symtab;
229 struct event_callback **cbs;
231 * Filters that have a format specified and we
232 * need to resolve that to an fmtid
234 TAILQ_HEAD(, event_filter_unresolved) unresolved_filtq;
237 char parse_err_buf[PARSE_ERR_BUFSIZE];
239 struct evtr_event pending_event;
243 evtr_set_debug(const char *str)
245 printd_set_flags(str, &evtr_debug);
248 static int id_map_cmp(struct id_map *, struct id_map *);
249 RB_PROTOTYPE2(id_tree, id_map, rb_node, id_map_cmp, int);
250 RB_GENERATE2(id_tree, id_map, rb_node, id_map_cmp, int, id);
252 static int thread_cmp(struct evtr_thread *, struct evtr_thread *);
253 RB_PROTOTYPE2(thread_tree, evtr_thread, rb_node, thread_cmp, void *);
254 RB_GENERATE2(thread_tree, evtr_thread, rb_node, thread_cmp, void *, id);
258 validate_string(const char *str)
260 if (!(evtr_debug & MISC))
263 assert(isprint(*str));
268 id_tree_free(struct id_tree *root)
270 struct id_map *v, *n;
272 for (v = RB_MIN(id_tree, root); v; v = n) {
273 n = RB_NEXT(id_tree, root, v);
274 RB_REMOVE(id_tree, root, v);
280 evtr_register_callback(evtr_query_t q, void (*fn)(evtr_event_t, void *), void *d)
282 struct event_callback *cb;
285 if (!(cb = malloc(sizeof(*cb)))) {
291 if (!(cbs = realloc(q->cbs, (++q->ncbs) * sizeof(cb)))) {
298 q->cbs[q->ncbs - 1] = cb;
304 evtr_deregister_callbacks(evtr_query_t q)
308 for (i = 0; i < q->ncbs; ++i) {
317 evtr_run_callbacks(evtr_event_t ev, evtr_query_t q)
319 struct event_callback *cb;
322 for (i = 0; i < q->ncbs; ++i) {
324 cb->cb(ev, cb->data);
330 evtr_cpu(evtr_t evtr, int c)
332 if ((c < 0) || (c >= evtr->ncpus))
334 return &evtr->cpus[c];
337 static int parse_format_data(evtr_event_t ev, const char *fmt, ...)
338 __printflike(2, 3) __scanflike(2, 3);
342 parse_format_data(evtr_event_t ev, const char *fmt, ...)
347 if (strcmp(fmt, ev->fmt))
349 vsnprintf(buf, sizeof(buf), fmt, __DECONST(void *, ev->fmtdata));
350 printd(MISC, "string is: %s\n", buf);
352 return vsscanf(buf, fmt, ap);
357 evtr_deregister_filters(evtr_query_t q, evtr_filter_t filt, int nfilt)
359 struct event_filter_unresolved *u, *tmp;
361 TAILQ_FOREACH_MUTABLE(u, &q->unresolved_filtq, link, tmp) {
362 for (i = 0; i < nfilt; ++i) {
363 if (u->filt == &filt[i]) {
364 TAILQ_REMOVE(&q->unresolved_filtq, u, link);
372 evtr_filter_register(evtr_query_t q, evtr_filter_t filt)
374 struct event_filter_unresolved *res;
376 if (!(res = malloc(sizeof(*res)))) {
381 TAILQ_INSERT_TAIL(&q->unresolved_filtq, res, link);
387 evtr_query_needs_parsing(evtr_query_t q)
391 for (i = 0; i < q->nfilt; ++i)
392 if (q->filt[i].ev_type == EVTR_TYPE_STMT)
398 evtr_event_data(evtr_event_t ev, char *buf, size_t len)
401 * XXX: we implicitly trust the format string.
404 if (ev->fmtdatalen) {
405 vsnprintf(buf, len, ev->fmt, __DECONST(void *, ev->fmtdata));
407 strlcpy(buf, ev->fmt, len);
412 evtr_error(evtr_t evtr)
414 return evtr->err || (evtr->errmsg != NULL);
418 evtr_errmsg(evtr_t evtr)
420 return evtr->errmsg ? evtr->errmsg : strerror(evtr->err);
424 evtr_query_error(evtr_query_t q)
426 return q->err || (q->errmsg != NULL) || evtr_error(q->evtr);
430 evtr_query_errmsg(evtr_query_t q)
432 return q->errmsg ? q->errmsg :
433 (q->err ? strerror(q->err) :
434 (evtr_errmsg(q->evtr)));
439 id_map_cmp(struct id_map *a, struct id_map *b)
441 return a->id - b->id;
446 thread_cmp(struct evtr_thread *a, struct evtr_thread *b)
457 #define DEFINE_MAP_FIND(prefix, type) \
460 prefix ## _map_find(struct id_tree *tree, int id)\
462 struct id_map *sid; \
464 sid = id_tree_RB_LOOKUP(tree, id); \
465 return sid ? sid->data : NULL; \
468 DEFINE_MAP_FIND(string, const char *)
469 DEFINE_MAP_FIND(fmt, const struct event_fmt *)
473 thread_map_find(struct thread_map *map, void *id)
475 return thread_tree_RB_LOOKUP(&map->root, id);
478 #define DEFINE_MAP_INSERT(prefix, type, _cmp, _dup) \
481 prefix ## _map_insert(struct id_tree *tree, type data, int id) \
483 struct id_map *sid, *osid; \
485 sid = malloc(sizeof(*sid)); \
491 if ((osid = id_tree_RB_INSERT(tree, sid))) { \
493 if (_cmp((type)osid->data, data)) { \
496 printd(DS, "mapping already exists, skipping\n"); \
497 /* we're OK with redefinitions of an id to the same string */ \
500 /* only do the strdup if we're inserting a new string */ \
501 sid->data = _dup(data); /* XXX: oom */ \
507 thread_map_insert(struct thread_map *map, struct evtr_thread *td)
509 struct evtr_thread *otd;
511 if ((otd = thread_tree_RB_INSERT(&map->root, td))) {
513 * Thread addresses might be reused, we're
515 * DANGER, Will Robinson: this means the user
516 * of the API needs to copy event->td if they
517 * want it to remain stable.
519 free((void *)otd->comm);
520 otd->comm = td->comm;
527 event_fmt_cmp(const struct event_fmt *a, const struct event_fmt *b)
533 ret = strcmp(a->subsys, b->subsys);
535 ret = strcmp(a->subsys, "");
537 } else if (b->subsys) {
538 ret = strcmp("", b->subsys);
542 return strcmp(a->fmt, b->fmt);
547 event_fmt_dup(const struct event_fmt *o)
551 if (!(n = malloc(sizeof(*n)))) {
554 memcpy(n, o, sizeof(*n));
558 DEFINE_MAP_INSERT(string, const char *, strcmp, strdup)
559 DEFINE_MAP_INSERT(fmt, const struct event_fmt *, event_fmt_cmp, event_fmt_dup)
562 hash_find(const struct hashtab *tab, uintptr_t key, uintptr_t *val)
564 struct hashentry *ent;
566 for(ent = tab->buckets[tab->hashfunc(key)];
567 ent && tab->cmpfunc(ent->key, key);
577 hash_insert(struct hashtab *tab, uintptr_t key, uintptr_t val)
579 struct hashentry *ent;
582 if (!(ent = malloc(sizeof(*ent)))) {
583 fprintf(stderr, "out of memory\n");
586 hsh = tab->hashfunc(key);
587 ent->next = tab->buckets[hsh];
590 tab->buckets[hsh] = ent;
596 cmpfunc_pointer(uintptr_t a, uintptr_t b)
603 hashfunc_pointer(uintptr_t p)
605 return p % NR_BUCKETS;
612 if (!(tab = calloc(sizeof(struct hashtab), 1)))
614 tab->hashfunc = &hashfunc_pointer;
615 tab->cmpfunc = &cmpfunc_pointer;
619 struct hashtab_str { /* string -> id map */
626 hashfunc_string(uintptr_t p)
628 const char *str = (char *)p;
629 unsigned long hash = 5381;
633 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
634 return hash % NR_BUCKETS;
639 cmpfunc_string(uintptr_t a, uintptr_t b)
641 return strcmp((char *)a, (char *)b);
649 struct hashtab_str *strtab;
650 if (!(strtab = calloc(sizeof(struct hashtab_str), 1)))
652 strtab->tab.hashfunc = &hashfunc_string;
653 strtab->tab.cmpfunc = &cmpfunc_string;
659 strhash_destroy(struct hashtab_str *strtab)
666 strhash_find(struct hashtab_str *strtab, const char *str, uint16_t *id)
670 if (hash_find(&strtab->tab, (uintptr_t)str, &val))
678 strhash_insert(struct hashtab_str *strtab, const char *str, uint16_t *id)
683 if (strtab->id == 0) {
684 fprintf(stderr, "too many strings\n");
689 fprintf(stderr, "out of memory\n");
693 hash_insert(&strtab->tab, (uintptr_t)str, (uintptr_t)val);
701 struct symtab *symtab;
702 if (!(symtab = calloc(sizeof(struct symtab), 1)))
704 symtab->tab.hashfunc = &hashfunc_string;
705 symtab->tab.cmpfunc = &cmpfunc_string;
710 symtab_destroy(struct symtab *symtab)
715 struct evtr_variable *
716 symtab_find(const struct symtab *symtab, const char *str)
720 if (hash_find(&symtab->tab, (uintptr_t)str, &val))
722 return (struct evtr_variable *)val;
726 symtab_insert(struct symtab *symtab, const char *name,
727 struct evtr_variable *var)
731 fprintf(stderr, "out of memory\n");
734 hash_insert(&symtab->tab, (uintptr_t)name, (uintptr_t)var);
740 evtr_filter_match(evtr_query_t q, evtr_filter_t f, evtr_event_t ev)
742 if ((f->cpu != -1) && (f->cpu != ev->cpu))
745 assert(!(f->flags & FILTF_ID));
746 if (ev->type != f->ev_type)
748 if (ev->type == EVTR_TYPE_PROBE) {
749 if (f->fmt && strcmp(ev->fmt, f->fmt))
751 } else if (ev->type == EVTR_TYPE_STMT) {
752 struct evtr_variable *var;
754 /* XXX: no need to do that *every* time */
755 parse_var(f->var, q->symtab, &var, &q->parse_err_buf[0],
758 * Ignore errors, they're expected since the
759 * variable might not be instantiated yet
761 if (var != ev->stmt.var)
769 evtr_match_filters(struct evtr_query *q, evtr_event_t ev)
773 /* no filters means we're interested in all events */
777 for (i = 0; i < q->nfilt; ++i) {
778 if (evtr_filter_match(q, &q->filt[i], ev)) {
788 parse_callback(evtr_event_t ev, void *d)
790 evtr_query_t q = (evtr_query_t)d;
791 if (ev->type != EVTR_TYPE_PROBE)
793 if (!ev->fmt || (ev->fmt[0] != '#'))
796 * Copy the event to ->pending_event, then call
797 * the parser to convert it into a synthesized
798 * EVTR_TYPE_STMT event.
800 memcpy(&q->pending_event, ev, sizeof(*ev));
801 parse_string(&q->pending_event, q->symtab, &ev->fmt[1],
802 &q->parse_err_buf[0], PARSE_ERR_BUFSIZE);
803 if (q->parse_err_buf[0]) { /* parse error */
804 q->errmsg = &q->parse_err_buf[0];
807 if (!evtr_match_filters(q, &q->pending_event))
810 * This will cause us to return ->pending_event next time
813 q->flags |= EVTRQF_PENDING;
818 thread_creation_callback(evtr_event_t ev, void *d)
820 evtr_query_t q = (evtr_query_t)d;
821 evtr_t evtr = q->evtr;
822 struct evtr_thread *td;
826 if (parse_format_data(ev, "new_td %p %s", &ktd, buf) != 2) {
831 if (!(td = malloc(sizeof(*td)))) {
837 if (!(td->comm = strdup(buf))) {
842 printd(DS, "inserting new thread %p: %s\n", td->id, td->comm);
843 thread_map_insert(&evtr->threads, td);
848 thread_switch_callback(evtr_event_t ev, void *d)
850 evtr_t evtr = ((evtr_query_t)d)->evtr;
851 struct evtr_thread *tdp, *tdn;
854 static struct evtr_event tdcr;
855 static char *fmt = "new_td %p %s";
857 char fmtdata[sizeof(void *) + sizeof(char *)];
859 cpu = evtr_cpu(evtr, ev->cpu);
861 printw("invalid cpu %d\n", ev->cpu);
864 if (parse_format_data(ev, "sw %p > %p", &ktdp, &ktdn) != 2) {
867 tdp = thread_map_find(&evtr->threads, ktdp);
869 printd(DS, "switching from unknown thread %p\n", ktdp);
871 tdn = thread_map_find(&evtr->threads, ktdn);
874 * Fake a thread creation event for threads we
875 * haven't seen before.
877 tdcr.type = EVTR_TYPE_PROBE;
883 tdcr.fmtdata = &fmtdata;
884 tdcr.fmtdatalen = sizeof(fmtdata);
887 snprintf(tidstr, sizeof(tidstr), "%p", ktdn);
888 ((void **)fmtdata)[0] = ktdn;
889 ((char **)fmtdata)[1] = &tidstr[0];
890 thread_creation_callback(&tdcr, d);
892 tdn = thread_map_find(&evtr->threads, ktdn);
894 printd(DS, "switching to unknown thread %p\n", ktdn);
898 printd(DS, "cpu %d: switching to thread %p\n", ev->cpu, ktdn);
904 assert_foff_in_sync(evtr_t evtr)
909 * We keep our own offset because we
910 * might want to support mmap()
912 off = ftello(evtr->f);
913 if (evtr->bytes != off) {
914 fprintf(stderr, "bytes %jd, off %jd\n", evtr->bytes, off);
921 evtr_write(evtr_t evtr, const void *buf, size_t bytes)
923 assert_foff_in_sync(evtr);
924 if (fwrite(buf, bytes, 1, evtr->f) != 1) {
926 evtr->errmsg = strerror(errno);
929 evtr->bytes += bytes;
930 assert_foff_in_sync(evtr);
935 * Called after dumping a record to make sure the next
936 * record is REC_ALIGN aligned. This does not make much sense,
937 * as we shouldn't be using packed structs anyway.
941 evtr_dump_pad(evtr_t evtr)
944 static char buf[REC_ALIGN];
946 pad = REC_ALIGN - (evtr->bytes % REC_ALIGN);
948 return evtr_write(evtr, buf, pad);
954 * We make sure that there is a new record every REC_BOUNDARY
955 * bytes, this costs next to nothing in space and allows for
960 evtr_dump_avoid_boundary(evtr_t evtr, size_t bytes)
963 static char buf[256];
965 pad = REC_BOUNDARY - (evtr->bytes % REC_BOUNDARY);
966 /* if adding @bytes would cause us to cross a boundary... */
968 /* then pad to the boundary */
969 for (i = 0; i < (pad / sizeof(buf)); ++i) {
970 if (evtr_write(evtr, buf, sizeof(buf))) {
974 i = pad % sizeof(buf);
976 if (evtr_write(evtr, buf, i)) {
986 evtr_dump_fmt(evtr_t evtr, uint64_t ts, const evtr_event_t ev)
988 struct fmt_event_header fmt;
991 char *subsys = "", buf[1024];
993 if (strlcpy(buf, subsys, sizeof(buf)) >= sizeof(buf)) {
994 evtr->errmsg = "name of subsystem is too large";
998 if (strlcat(buf, ev->fmt, sizeof(buf)) >= sizeof(buf)) {
999 evtr->errmsg = "fmt + name of subsystem is too large";
1004 if (!strhash_find(evtr->fmts, buf, &id)) {
1007 if ((err = strhash_insert(evtr->fmts, buf, &id))) {
1012 fmt.eh.type = EVTR_TYPE_FMT;
1014 fmt.subsys_len = strlen(subsys);
1015 fmt.fmt_len = strlen(ev->fmt);
1017 if (evtr_dump_avoid_boundary(evtr, sizeof(fmt) + fmt.subsys_len +
1020 if (evtr_write(evtr, &fmt, sizeof(fmt)))
1022 if (evtr_write(evtr, subsys, fmt.subsys_len))
1024 if (evtr_write(evtr, ev->fmt, fmt.fmt_len))
1026 if (evtr_dump_pad(evtr))
1032 * Replace string pointers or string ids in fmtdata
1036 mangle_string_ptrs(const char *fmt, uint8_t *fmtdata,
1037 const char *(*replace)(void *, const char *), void *ctx)
1040 size_t skipsize, intsz;
1043 for (f = fmt; f[0] != '\0'; ++f) {
1048 for (p = f; p[0]; ++p) {
1051 * Eat flags. Notice this will accept duplicate
1067 /* Eat minimum field width, if any */
1068 for (; isdigit(p[0]); ++p)
1072 /* Eat precision, if any */
1073 for (; isdigit(p[0]); ++p)
1080 intsz = sizeof(long long);
1082 intsz = sizeof(long);
1086 intsz = sizeof(intmax_t);
1089 intsz = sizeof(ptrdiff_t);
1092 intsz = sizeof(size_t);
1100 intsz = sizeof(int);
1113 skipsize = sizeof(void *);
1117 skipsize = sizeof(double);
1119 skipsize = sizeof(float);
1122 ((const char **)fmtdata)[0] =
1123 replace(ctx, ((char **)fmtdata)[0]);
1124 skipsize = sizeof(char *);
1128 fprintf(stderr, "Unknown conversion specifier %c "
1129 "in fmt starting with %s", p[0], f - 1);
1132 fmtdata += skipsize;
1137 /* XXX: do we really want the timestamp? */
1140 evtr_dump_string(evtr_t evtr, uint64_t ts, const char *str, int ns)
1142 struct string_event_header s;
1146 assert((0 <= ns) && (ns < EVTR_NS_MAX));
1147 if (!strhash_find(evtr->strings[ns], str, &id)) {
1150 if ((err = strhash_insert(evtr->strings[ns], str, &id))) {
1155 printd(DS, "hash_insert %s ns %d id %d\n", str, ns, id);
1156 s.eh.type = EVTR_TYPE_STR;
1160 s.len = strnlen(str, PATH_MAX);
1162 if (evtr_dump_avoid_boundary(evtr, sizeof(s) + s.len))
1164 if (evtr_write(evtr, &s, sizeof(s)))
1166 if (evtr_write(evtr, str, s.len))
1168 if (evtr_dump_pad(evtr))
1173 struct replace_ctx {
1180 replace_strptr(void *_ctx, const char *s)
1182 struct replace_ctx *ctx = _ctx;
1183 return (const char *)(uintptr_t)evtr_dump_string(ctx->evtr, ctx->ts, s,
1189 replace_strid(void *_ctx, const char *s)
1191 struct replace_ctx *ctx = _ctx;
1194 ret = string_map_find(&ctx->evtr->maps[EVTR_NS_DSTR - 1].root,
1197 fprintf(stderr, "Unknown id for data string\n");
1198 ctx->evtr->errmsg = "unknown id for data string";
1199 ctx->evtr->err = !0;
1201 validate_string(ret);
1202 printd(DS, "replacing strid %d (ns %d) with string '%s' (or int %#x)\n",
1203 (int)(uintptr_t)s, EVTR_NS_DSTR, ret ? ret : "NULL", (int)(uintptr_t)ret);
1209 evtr_dump_probe(evtr_t evtr, evtr_event_t ev)
1211 struct probe_event_header kev;
1214 memset(&kev, '\0', sizeof(kev));
1215 kev.eh.type = ev->type;
1217 kev.line = ev->line;
1220 kev.file = evtr_dump_string(evtr, kev.eh.ts, ev->file,
1224 kev.func = evtr_dump_string(evtr, kev.eh.ts, ev->func,
1228 kev.fmt = evtr_dump_fmt(evtr, kev.eh.ts, ev);
1231 struct replace_ctx replctx = {
1235 assert(ev->fmtdatalen <= (int)sizeof(buf));
1236 kev.datalen = ev->fmtdatalen;
1238 * Replace all string pointers with string ids before dumping
1241 memcpy(buf, ev->fmtdata, ev->fmtdatalen);
1242 if (mangle_string_ptrs(ev->fmt, buf,
1243 replace_strptr, &replctx) < 0)
1248 if (evtr_dump_avoid_boundary(evtr, sizeof(kev) + ev->fmtdatalen))
1250 if (evtr_write(evtr, &kev, sizeof(kev)))
1252 if (evtr_write(evtr, buf, ev->fmtdatalen))
1254 if (evtr_dump_pad(evtr))
1261 evtr_dump_sysinfo(evtr_t evtr, evtr_event_t ev)
1263 uint8_t type = EVTR_TYPE_SYSINFO;
1264 uint16_t ncpus = ev->ncpus;
1267 evtr->errmsg = "invalid number of cpus";
1270 if (evtr_dump_avoid_boundary(evtr, sizeof(type) + sizeof(ncpus)))
1272 if (evtr_write(evtr, &type, sizeof(type))) {
1275 if (evtr_write(evtr, &ncpus, sizeof(ncpus))) {
1278 if (evtr_dump_pad(evtr))
1284 evtr_dump_cpuinfo(evtr_t evtr, evtr_event_t ev)
1286 struct cpuinfo_event_header ci;
1289 if (evtr_dump_avoid_boundary(evtr, sizeof(type) + sizeof(ci)))
1291 type = EVTR_TYPE_CPUINFO;
1292 if (evtr_write(evtr, &type, sizeof(type))) {
1296 ci.freq = ev->cpuinfo.freq;
1297 if (evtr_dump_avoid_boundary(evtr, sizeof(ci)))
1299 if (evtr_write(evtr, &ci, sizeof(ci))) {
1302 if (evtr_dump_pad(evtr))
1308 evtr_rewind(evtr_t evtr)
1310 assert((evtr->flags & EVTRF_WR) == 0);
1312 if (fseek(evtr->f, 0, SEEK_SET)) {
1320 evtr_dump_event(evtr_t evtr, evtr_event_t ev)
1323 case EVTR_TYPE_PROBE:
1324 return evtr_dump_probe(evtr, ev);
1325 case EVTR_TYPE_SYSINFO:
1326 return evtr_dump_sysinfo(evtr, ev);
1327 case EVTR_TYPE_CPUINFO:
1328 return evtr_dump_cpuinfo(evtr, ev);
1330 evtr->errmsg = "unknown event type";
1339 if (!(evtr = malloc(sizeof(*evtr)))) {
1345 evtr->errmsg = NULL;
1350 static int evtr_next_event(evtr_t, evtr_event_t);
1353 evtr_open_read(FILE *f)
1356 struct evtr_event ev;
1359 if (!(evtr = evtr_alloc(f))) {
1363 for (i = 0; i < (EVTR_NS_MAX - 1); ++i) {
1364 RB_INIT(&evtr->maps[i].root);
1366 RB_INIT(&evtr->fmtmap.root);
1367 RB_INIT(&evtr->threads.root);
1371 * Load the first event so we can pick up any
1374 if (evtr_next_event(evtr, &ev)) {
1377 if (evtr_rewind(evtr))
1386 evtr_open_write(FILE *f)
1391 if (!(evtr = evtr_alloc(f))) {
1395 evtr->flags = EVTRF_WR;
1396 if (!(evtr->fmts = strhash_new()))
1398 for (i = 0; i < EVTR_NS_MAX; ++i) {
1399 evtr->strings[i] = strhash_new();
1400 if (!evtr->strings[i]) {
1401 for (j = 0; j < i; ++j) {
1402 strhash_destroy(evtr->strings[j]);
1410 strhash_destroy(evtr->fmts);
1418 hashtab_destroy(struct hashtab *h)
1420 struct hashentry *ent, *next;
1422 for (i = 0; i < NR_BUCKETS; ++i) {
1423 for (ent = h->buckets[i]; ent; ent = next) {
1432 evtr_close(evtr_t evtr)
1436 if (evtr->flags & EVTRF_WR) {
1437 hashtab_destroy(&evtr->fmts->tab);
1438 for (i = 0; i < EVTR_NS_MAX - 1; ++i)
1439 hashtab_destroy(&evtr->strings[i]->tab);
1441 id_tree_free(&evtr->fmtmap.root);
1442 for (i = 0; i < EVTR_NS_MAX - 1; ++i) {
1443 id_tree_free(&evtr->maps[i].root);
1451 evtr_read(evtr_t evtr, void *buf, size_t size)
1454 assert_foff_in_sync(evtr);
1455 printd(IO, "evtr_read at %#jx, %zd bytes\n", evtr->bytes, size);
1456 if (fread(buf, size, 1, evtr->f) != 1) {
1457 if (feof(evtr->f)) {
1458 evtr->errmsg = "incomplete record";
1460 evtr->errmsg = strerror(errno);
1464 evtr->bytes += size;
1465 assert_foff_in_sync(evtr);
1471 evtr_load_fmt(evtr_query_t q, char *buf)
1473 evtr_t evtr = q->evtr;
1474 struct fmt_event_header *evh = (struct fmt_event_header *)buf;
1475 struct event_fmt *fmt;
1476 char *subsys = NULL, *fmtstr;
1478 if (!(fmt = malloc(sizeof(*fmt)))) {
1482 if (evtr_read(evtr, buf + sizeof(struct trace_event_header),
1483 sizeof(*evh) - sizeof(evh->eh))) {
1486 assert(!evh->subsys_len);
1487 if (evh->subsys_len) {
1488 if (!(subsys = malloc(evh->subsys_len))) {
1492 if (evtr_read(evtr, subsys, evh->subsys_len)) {
1495 fmt->subsys = subsys;
1499 if (!(fmtstr = malloc(evh->fmt_len + 1))) {
1503 if (evtr_read(evtr, fmtstr, evh->fmt_len)) {
1506 fmtstr[evh->fmt_len] = '\0';
1509 printd(DS, "fmt_map_insert (%d, %s)\n", evh->id, fmt->fmt);
1510 evtr->err = fmt_map_insert(&evtr->fmtmap.root, fmt, evh->id);
1511 switch (evtr->err) {
1513 evtr->errmsg = "out of memory";
1516 evtr->errmsg = "redefinition of an id to a "
1517 "different format (corrupt input)";
1536 evtr_load_string(evtr_t evtr, char *buf)
1538 char sbuf[PATH_MAX + 1];
1539 struct string_event_header *evh = (struct string_event_header *)buf;
1541 if (evtr_read(evtr, buf + sizeof(struct trace_event_header),
1542 sizeof(*evh) - sizeof(evh->eh))) {
1545 if (evh->len > PATH_MAX) {
1546 evtr->errmsg = "string too large (corrupt input)";
1549 if (evh->len && evtr_read(evtr, sbuf, evh->len)) {
1553 if (evh->ns >= EVTR_NS_MAX) {
1554 evtr->errmsg = "invalid namespace (corrupt input)";
1557 validate_string(sbuf);
1558 printd(DS, "evtr_load_string:ns %d id %d : \"%s\"\n", evh->ns, evh->id,
1560 evtr->err = string_map_insert(&evtr->maps[evh->ns - 1].root, sbuf, evh->id);
1561 switch (evtr->err) {
1563 evtr->errmsg = "out of memory";
1566 evtr->errmsg = "redefinition of an id to a "
1567 "different string (corrupt input)";
1577 evtr_skip(evtr_t evtr, off_t bytes)
1579 if (fseek(evtr->f, bytes, SEEK_CUR)) {
1581 evtr->errmsg = strerror(errno);
1584 evtr->bytes += bytes;
1589 * Make sure q->buf is at least len bytes
1593 evtr_query_reserve_buf(struct evtr_query *q, int len)
1597 if (q->bufsize >= len)
1599 if (!(tmp = realloc(q->buf, len)))
1608 evtr_load_probe(evtr_t evtr, evtr_event_t ev, char *buf, struct evtr_query *q)
1610 struct probe_event_header *evh = (struct probe_event_header *)buf;
1613 if (evtr_read(evtr, buf + sizeof(struct trace_event_header),
1614 sizeof(*evh) - sizeof(evh->eh)))
1616 memset(ev, '\0', sizeof(*ev));
1617 ev->ts = evh->eh.ts;
1618 ev->type = EVTR_TYPE_PROBE;
1619 ev->line = evh->line;
1621 if ((cpu = evtr_cpu(evtr, evh->cpu))) {
1627 ev->file = string_map_find(
1628 &evtr->maps[EVTR_NS_PATH - 1].root,
1631 evtr->errmsg = "unknown id for file path";
1633 ev->file = "<unknown>";
1635 validate_string(ev->file);
1638 ev->file = "<unknown>";
1641 const struct event_fmt *fmt;
1642 if (!(fmt = fmt_map_find(&evtr->fmtmap.root, evh->fmt))) {
1643 evtr->errmsg = "unknown id for event fmt";
1648 validate_string(fmt->fmt);
1652 if (evtr_query_reserve_buf(q, evh->datalen + 1)) {
1654 } else if (!evtr_read(evtr, q->buf, evh->datalen)) {
1655 struct replace_ctx replctx = {
1661 ev->fmtdata = q->buf;
1663 * If the format specifies any string pointers, there
1664 * is a string id stored in the fmtdata. Look it up
1665 * and replace it with a string pointer before
1666 * returning it to the user.
1668 if (mangle_string_ptrs(ev->fmt, __DECONST(uint8_t *,
1670 replace_strid, &replctx) < 0)
1674 ((char *)ev->fmtdata)[evh->datalen] = '\0';
1675 ev->fmtdatalen = evh->datalen;
1678 evtr_run_callbacks(ev, q);
1684 evtr_skip_to_record(evtr_t evtr)
1688 skip = REC_ALIGN - (evtr->bytes % REC_ALIGN);
1690 if (fseek(evtr->f, skip, SEEK_CUR)) {
1692 evtr->errmsg = strerror(errno);
1695 evtr->bytes += skip;
1702 evtr_load_sysinfo(evtr_t evtr)
1707 if (evtr_read(evtr, &ncpus, sizeof(ncpus))) {
1712 evtr->cpus = malloc(ncpus * sizeof(struct cpu));
1717 evtr->ncpus = ncpus;
1718 for (i = 0; i < ncpus; ++i) {
1719 evtr->cpus[i].td = NULL;
1720 evtr->cpus[i].freq = -1.0;
1727 evtr_load_cpuinfo(evtr_t evtr)
1729 struct cpuinfo_event_header cih;
1732 if (evtr_read(evtr, &cih, sizeof(cih))) {
1735 if (cih.freq < 0.0) {
1736 evtr->errmsg = "cpu freq is negative";
1741 * Notice that freq is merely a multiplier with
1742 * which we convert a timestamp to seconds; if
1743 * ts is not in cycles, freq is not the frequency.
1745 if (!(cpu = evtr_cpu(evtr, cih.cpu))) {
1746 evtr->errmsg = "freq for invalid cpu";
1750 cpu->freq = cih.freq;
1756 _evtr_next_event(evtr_t evtr, evtr_event_t ev, struct evtr_query *q)
1758 char buf[MAX_EVHDR_SIZE];
1760 struct trace_event_header *evhdr = (struct trace_event_header *)buf;
1762 for (ret = 0; !ret;) {
1763 if (q->flags & EVTRQF_PENDING) {
1764 q->off = evtr->bytes;
1765 memcpy(ev, &q->pending_event, sizeof(*ev));
1766 q->flags &= ~EVTRQF_PENDING;
1769 if (evtr_read(evtr, &evhdr->type, 1)) {
1770 if (feof(evtr->f)) {
1771 evtr->errmsg = NULL;
1778 * skip pad records -- this will only happen if there's a
1779 * variable sized record close to the boundary
1781 if (evhdr->type == EVTR_TYPE_PAD) {
1782 evtr_skip_to_record(evtr);
1785 if (evhdr->type == EVTR_TYPE_SYSINFO) {
1786 evtr_load_sysinfo(evtr);
1788 } else if (evhdr->type == EVTR_TYPE_CPUINFO) {
1789 evtr_load_cpuinfo(evtr);
1792 if (evtr_read(evtr, buf + 1, sizeof(*evhdr) - 1))
1793 return feof(evtr->f) ? -1 : !0;
1794 switch (evhdr->type) {
1795 case EVTR_TYPE_PROBE:
1796 if ((err = evtr_load_probe(evtr, ev, buf, q))) {
1808 if (evtr_load_string(evtr, buf)) {
1813 if (evtr_load_fmt(q, buf)) {
1819 evtr->errmsg = "unknown event type (corrupt input?)";
1822 evtr_skip_to_record(evtr);
1824 if (!evtr_match_filters(q, ev)) {
1828 q->off = evtr->bytes;
1832 /* can't get here */
1838 evtr_next_event(evtr_t evtr, evtr_event_t ev)
1840 struct evtr_query *q;
1843 if (!(q = evtr_query_init(evtr, NULL, 0))) {
1847 ret = _evtr_next_event(evtr, ev, q);
1848 evtr_query_destroy(q);
1853 evtr_last_event(evtr_t evtr, evtr_event_t ev)
1857 off_t last_boundary;
1859 if (evtr_error(evtr))
1862 fd = fileno(evtr->f);
1866 * This skips pseudo records, so we can't provide
1867 * an event with all fields filled in this way.
1868 * It's doable, just needs some care. TBD.
1870 if (0 && (st.st_mode & S_IFREG)) {
1872 * Skip to last boundary, that's the closest to the EOF
1873 * location that we are sure contains a header so we can
1874 * pick up the stream.
1876 last_boundary = rounddown(st.st_size, REC_BOUNDARY);
1877 /* XXX: ->bytes should be in query */
1878 assert(evtr->bytes == 0);
1879 evtr_skip(evtr, last_boundary);
1884 * If we can't seek, we need to go through the whole file.
1885 * Since you can't seek back, this is pretty useless unless
1886 * you really are interested only in the last event.
1888 while (!evtr_next_event(evtr, ev))
1890 if (evtr_error(evtr))
1897 evtr_query_init(evtr_t evtr, evtr_filter_t filt, int nfilt)
1899 struct evtr_query *q;
1902 if (!(q = malloc(sizeof(*q)))) {
1906 if (!(q->buf = malloc(q->bufsize))) {
1909 if (!(q->symtab = symtab_new()))
1915 TAILQ_INIT(&q->unresolved_filtq);
1920 memset(&q->pending_event, '\0', sizeof(q->pending_event));
1921 if (evtr_register_callback(q, &thread_creation_callback, q)) {
1924 if (evtr_register_callback(q, &thread_switch_callback, q)) {
1927 if (evtr_query_needs_parsing(q) &&
1928 evtr_register_callback(q, &parse_callback, q)) {
1932 for (i = 0; i < nfilt; ++i) {
1934 if (filt[i].fmt == NULL)
1936 if (evtr_filter_register(q, &filt[i])) {
1937 evtr_deregister_filters(q, filt, i);
1944 evtr_deregister_callbacks(q);
1946 symtab_destroy(q->symtab);
1955 evtr_query_destroy(struct evtr_query *q)
1957 evtr_deregister_filters(q, q->filt, q->nfilt);
1964 evtr_query_next(struct evtr_query *q, evtr_event_t ev)
1966 if (evtr_query_error(q))
1968 /* we may support that in the future */
1969 if (q->off != q->evtr->bytes) {
1970 q->errmsg = "evtr/query offset mismatch";
1973 return _evtr_next_event(q->evtr, ev, q);
1977 evtr_ncpus(evtr_t evtr)
1983 evtr_cpufreqs(evtr_t evtr, double *freqs)
1989 for (i = 0; i < evtr->ncpus; ++i) {
1990 freqs[i] = evtr->cpus[i].freq;