264 lines · 6.5 KB · C
RawDownload
#include <inttypes.h>#include <stdio.h>#include <stdbool.h>#include <traceevent/event-parse.h>#include "evsel.h"#include "callchain.h"#include "map.h"#include "strlist.h"#include "symbol.h"#include "srcline.h" static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...){	va_list args;	int ret = 0; 	if (!*first) {		ret += fprintf(fp, ",");	} else {		ret += fprintf(fp, ":");		*first = false;	} 	va_start(args, fmt);	ret += vfprintf(fp, fmt, args);	va_end(args);	return ret;} static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv){	return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);} int perf_evsel__fprintf(struct perf_evsel *evsel,			struct perf_attr_details *details, FILE *fp){	bool first = true;	int printed = 0; 	if (details->event_group) {		struct perf_evsel *pos; 		if (!perf_evsel__is_group_leader(evsel))			return 0; 		if (evsel->nr_members > 1)			printed += fprintf(fp, "%s{", evsel->group_name ?: ""); 		printed += fprintf(fp, "%s", perf_evsel__name(evsel));		for_each_group_member(pos, evsel)			printed += fprintf(fp, ",%s", perf_evsel__name(pos)); 		if (evsel->nr_members > 1)			printed += fprintf(fp, "}");		goto out;	} 	printed += fprintf(fp, "%s", perf_evsel__name(evsel)); 	if (details->verbose) {		printed += perf_event_attr__fprintf(fp, &evsel->attr,						    __print_attr__fprintf, &first);	} else if (details->freq) {		const char *term = "sample_freq"; 		if (!evsel->attr.freq)			term = "sample_period"; 		printed += comma_fprintf(fp, &first, " %s=%" PRIu64,					 term, (u64)evsel->attr.sample_freq);	} 	if (details->trace_fields) {		struct format_field *field; 		if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {			printed += comma_fprintf(fp, &first, " (not a tracepoint)");			goto out;		} 		field = evsel->tp_format->format.fields;		if (field == NULL) {			printed += comma_fprintf(fp, &first, " (no trace field)");			goto out;		} 		printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name); 		field = field->next;		while (field) {			printed += comma_fprintf(fp, &first, "%s", field->name);			field = field->next;		}	}out:	fputc('\n', fp);	return ++printed;} int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,			      unsigned int print_opts, struct callchain_cursor *cursor,			      FILE *fp){	int printed = 0;	struct callchain_cursor_node *node;	int print_ip = print_opts & EVSEL__PRINT_IP;	int print_sym = print_opts & EVSEL__PRINT_SYM;	int print_dso = print_opts & EVSEL__PRINT_DSO;	int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;	int print_oneline = print_opts & EVSEL__PRINT_ONELINE;	int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;	int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;	int print_arrow = print_opts & EVSEL__PRINT_CALLCHAIN_ARROW;	int print_skip_ignored = print_opts & EVSEL__PRINT_SKIP_IGNORED;	char s = print_oneline ? ' ' : '\t';	bool first = true; 	if (sample->callchain) {		struct addr_location node_al; 		callchain_cursor_commit(cursor); 		while (1) {			u64 addr = 0; 			node = callchain_cursor_current(cursor);			if (!node)				break; 			if (node->sym && node->sym->ignore && print_skip_ignored)				goto next; 			printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); 			if (print_arrow && !first)				printed += fprintf(fp, " <-"); 			if (print_ip)				printed += fprintf(fp, "%c%16" PRIx64, s, node->ip); 			if (node->map)				addr = node->map->map_ip(node->map, node->ip); 			if (print_sym) {				printed += fprintf(fp, " ");				node_al.addr = addr;				node_al.map  = node->map; 				if (print_symoffset) {					printed += __symbol__fprintf_symname_offs(node->sym, &node_al,										  print_unknown_as_addr,										  true, fp);				} else {					printed += __symbol__fprintf_symname(node->sym, &node_al,									     print_unknown_as_addr, fp);				}			} 			if (print_dso) {				printed += fprintf(fp, " (");				printed += map__fprintf_dsoname(node->map, fp);				printed += fprintf(fp, ")");			} 			if (print_srcline)				printed += map__fprintf_srcline(node->map, addr, "\n  ", fp); 			if (!print_oneline)				printed += fprintf(fp, "\n"); 			if (symbol_conf.inline_name && node->map) {				struct inline_node *inode; 				addr = map__rip_2objdump(node->map, node->ip),				inode = dso__parse_addr_inlines(node->map->dso, addr); 				if (inode) {					struct inline_list *ilist; 					list_for_each_entry(ilist, &inode->val, list) {						if (print_arrow)							printed += fprintf(fp, " <-"); 						/* IP is same, just skip it */						if (print_ip)							printed += fprintf(fp, "%c%16s",									   s, "");						if (print_sym)							printed += fprintf(fp, " %s",									   ilist->funcname);						if (print_srcline)							printed += fprintf(fp, "\n  %s:%d",									   ilist->filename,									   ilist->line_nr);						if (!print_oneline)							printed += fprintf(fp, "\n");					} 					inline_node__delete(inode);				}			} 			if (symbol_conf.bt_stop_list &&			    node->sym &&			    strlist__has_entry(symbol_conf.bt_stop_list,					       node->sym->name)) {				break;			} 			first = false;next:			callchain_cursor_advance(cursor);		}	} 	return printed;} int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,			int left_alignment, unsigned int print_opts,			struct callchain_cursor *cursor, FILE *fp){	int printed = 0;	int print_ip = print_opts & EVSEL__PRINT_IP;	int print_sym = print_opts & EVSEL__PRINT_SYM;	int print_dso = print_opts & EVSEL__PRINT_DSO;	int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;	int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;	int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR; 	if (cursor != NULL) {		printed += sample__fprintf_callchain(sample, left_alignment,						     print_opts, cursor, fp);	} else {		printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); 		if (print_ip)			printed += fprintf(fp, "%16" PRIx64, sample->ip); 		if (print_sym) {			printed += fprintf(fp, " ");			if (print_symoffset) {				printed += __symbol__fprintf_symname_offs(al->sym, al,									  print_unknown_as_addr,									  true, fp);			} else {				printed += __symbol__fprintf_symname(al->sym, al,								     print_unknown_as_addr, fp);			}		} 		if (print_dso) {			printed += fprintf(fp, " (");			printed += map__fprintf_dsoname(al->map, fp);			printed += fprintf(fp, ")");		} 		if (print_srcline)			printed += map__fprintf_srcline(al->map, al->addr, "\n  ", fp);	} 	return printed;}