1188 lines · 28.2 KB · C
RawDownload
#include "sort.h"#include "hist.h"#include "comm.h"#include "symbol.h" regex_t		parent_regex;const char	default_parent_pattern[] = "^sys_|^do_page_fault";const char	*parent_pattern = default_parent_pattern;const char	default_sort_order[] = "comm,dso,symbol";const char	*sort_order = default_sort_order;regex_t		ignore_callees_regex;int		have_ignore_callees = 0;int		sort__need_collapse = 0;int		sort__has_parent = 0;int		sort__has_sym = 0;enum sort_mode	sort__mode = SORT_MODE__NORMAL; enum sort_type	sort__first_dimension; LIST_HEAD(hist_entry__sort_list); static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...){	int n;	va_list ap; 	va_start(ap, fmt);	n = vsnprintf(bf, size, fmt, ap);	if (symbol_conf.field_sep && n > 0) {		char *sep = bf; 		while (1) {			sep = strchr(sep, *symbol_conf.field_sep);			if (sep == NULL)				break;			*sep = '.';		}	}	va_end(ap); 	if (n >= (int)size)		return size - 1;	return n;} static int64_t cmp_null(const void *l, const void *r){	if (!l && !r)		return 0;	else if (!l)		return -1;	else		return 1;} /* --sort pid */ static int64_tsort__thread_cmp(struct hist_entry *left, struct hist_entry *right){	return right->thread->tid - left->thread->tid;} static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,				       size_t size, unsigned int width){	const char *comm = thread__comm_str(he->thread);	return repsep_snprintf(bf, size, "%*s:%5d", width - 6,			       comm ?: "", he->thread->tid);} struct sort_entry sort_thread = {	.se_header	= "Command:  Pid",	.se_cmp		= sort__thread_cmp,	.se_snprintf	= hist_entry__thread_snprintf,	.se_width_idx	= HISTC_THREAD,}; /* --sort comm */ static int64_tsort__comm_cmp(struct hist_entry *left, struct hist_entry *right){	/* Compare the addr that should be unique among comm */	return comm__str(right->comm) - comm__str(left->comm);} static int64_tsort__comm_collapse(struct hist_entry *left, struct hist_entry *right){	/* Compare the addr that should be unique among comm */	return comm__str(right->comm) - comm__str(left->comm);} static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,				     size_t size, unsigned int width){	return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm));} struct sort_entry sort_comm = {	.se_header	= "Command",	.se_cmp		= sort__comm_cmp,	.se_collapse	= sort__comm_collapse,	.se_snprintf	= hist_entry__comm_snprintf,	.se_width_idx	= HISTC_COMM,}; /* --sort dso */ static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r){	struct dso *dso_l = map_l ? map_l->dso : NULL;	struct dso *dso_r = map_r ? map_r->dso : NULL;	const char *dso_name_l, *dso_name_r; 	if (!dso_l || !dso_r)		return cmp_null(dso_l, dso_r); 	if (verbose) {		dso_name_l = dso_l->long_name;		dso_name_r = dso_r->long_name;	} else {		dso_name_l = dso_l->short_name;		dso_name_r = dso_r->short_name;	} 	return strcmp(dso_name_l, dso_name_r);} static int64_tsort__dso_cmp(struct hist_entry *left, struct hist_entry *right){	return _sort__dso_cmp(left->ms.map, right->ms.map);} static int _hist_entry__dso_snprintf(struct map *map, char *bf,				     size_t size, unsigned int width){	if (map && map->dso) {		const char *dso_name = !verbose ? map->dso->short_name :			map->dso->long_name;		return repsep_snprintf(bf, size, "%-*s", width, dso_name);	} 	return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");} static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,				    size_t size, unsigned int width){	return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);} struct sort_entry sort_dso = {	.se_header	= "Shared Object",	.se_cmp		= sort__dso_cmp,	.se_snprintf	= hist_entry__dso_snprintf,	.se_width_idx	= HISTC_DSO,}; /* --sort symbol */ static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r){	u64 ip_l, ip_r; 	if (!sym_l || !sym_r)		return cmp_null(sym_l, sym_r); 	if (sym_l == sym_r)		return 0; 	ip_l = sym_l->start;	ip_r = sym_r->start; 	return (int64_t)(ip_r - ip_l);} static int64_tsort__sym_cmp(struct hist_entry *left, struct hist_entry *right){	int64_t ret; 	if (!left->ms.sym && !right->ms.sym)		return right->level - left->level; 	/*	 * comparing symbol address alone is not enough since it's a	 * relative address within a dso.	 */	ret = sort__dso_cmp(left, right);	if (ret != 0)		return ret; 	return _sort__sym_cmp(left->ms.sym, right->ms.sym);} static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,				     u64 ip, char level, char *bf, size_t size,				     unsigned int width){	size_t ret = 0; 	if (verbose) {		char o = map ? dso__symtab_origin(map->dso) : '!';		ret += repsep_snprintf(bf, size, "%-#*llx %c ",				       BITS_PER_LONG / 4 + 2, ip, o);	} 	ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);	if (sym && map) {		if (map->type == MAP__VARIABLE) {			ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);			ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",					ip - map->unmap_ip(map, sym->start));			ret += repsep_snprintf(bf + ret, size - ret, "%-*s",				       width - ret, "");		} else {			ret += repsep_snprintf(bf + ret, size - ret, "%-*s",					       width - ret,					       sym->name);		}	} else {		size_t len = BITS_PER_LONG / 4;		ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",				       len, ip);		ret += repsep_snprintf(bf + ret, size - ret, "%-*s",				       width - ret, "");	} 	return ret;} static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,				    size_t size, unsigned int width){	return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,					 he->level, bf, size, width);} struct sort_entry sort_sym = {	.se_header	= "Symbol",	.se_cmp		= sort__sym_cmp,	.se_snprintf	= hist_entry__sym_snprintf,	.se_width_idx	= HISTC_SYMBOL,}; /* --sort srcline */ static int64_tsort__srcline_cmp(struct hist_entry *left, struct hist_entry *right){	if (!left->srcline) {		if (!left->ms.map)			left->srcline = SRCLINE_UNKNOWN;		else {			struct map *map = left->ms.map;			left->srcline = get_srcline(map->dso,					    map__rip_2objdump(map, left->ip));		}	}	if (!right->srcline) {		if (!right->ms.map)			right->srcline = SRCLINE_UNKNOWN;		else {			struct map *map = right->ms.map;			right->srcline = get_srcline(map->dso,					    map__rip_2objdump(map, right->ip));		}	}	return strcmp(left->srcline, right->srcline);} static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,					size_t size,					unsigned int width __maybe_unused){	return repsep_snprintf(bf, size, "%s", he->srcline);} struct sort_entry sort_srcline = {	.se_header	= "Source:Line",	.se_cmp		= sort__srcline_cmp,	.se_snprintf	= hist_entry__srcline_snprintf,	.se_width_idx	= HISTC_SRCLINE,}; /* --sort parent */ static int64_tsort__parent_cmp(struct hist_entry *left, struct hist_entry *right){	struct symbol *sym_l = left->parent;	struct symbol *sym_r = right->parent; 	if (!sym_l || !sym_r)		return cmp_null(sym_l, sym_r); 	return strcmp(sym_l->name, sym_r->name);} static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,				       size_t size, unsigned int width){	return repsep_snprintf(bf, size, "%-*s", width,			      he->parent ? he->parent->name : "[other]");} struct sort_entry sort_parent = {	.se_header	= "Parent symbol",	.se_cmp		= sort__parent_cmp,	.se_snprintf	= hist_entry__parent_snprintf,	.se_width_idx	= HISTC_PARENT,}; /* --sort cpu */ static int64_tsort__cpu_cmp(struct hist_entry *left, struct hist_entry *right){	return right->cpu - left->cpu;} static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,				    size_t size, unsigned int width){	return repsep_snprintf(bf, size, "%*d", width, he->cpu);} struct sort_entry sort_cpu = {	.se_header      = "CPU",	.se_cmp	        = sort__cpu_cmp,	.se_snprintf    = hist_entry__cpu_snprintf,	.se_width_idx	= HISTC_CPU,}; /* sort keys for branch stacks */ static int64_tsort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right){	return _sort__dso_cmp(left->branch_info->from.map,			      right->branch_info->from.map);} static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,				    size_t size, unsigned int width){	return _hist_entry__dso_snprintf(he->branch_info->from.map,					 bf, size, width);} static int64_tsort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right){	return _sort__dso_cmp(left->branch_info->to.map,			      right->branch_info->to.map);} static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,				       size_t size, unsigned int width){	return _hist_entry__dso_snprintf(he->branch_info->to.map,					 bf, size, width);} static int64_tsort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right){	struct addr_map_symbol *from_l = &left->branch_info->from;	struct addr_map_symbol *from_r = &right->branch_info->from; 	if (!from_l->sym && !from_r->sym)		return right->level - left->level; 	return _sort__sym_cmp(from_l->sym, from_r->sym);} static int64_tsort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right){	struct addr_map_symbol *to_l = &left->branch_info->to;	struct addr_map_symbol *to_r = &right->branch_info->to; 	if (!to_l->sym && !to_r->sym)		return right->level - left->level; 	return _sort__sym_cmp(to_l->sym, to_r->sym);} static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,					 size_t size, unsigned int width){	struct addr_map_symbol *from = &he->branch_info->from;	return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,					 he->level, bf, size, width); } static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,				       size_t size, unsigned int width){	struct addr_map_symbol *to = &he->branch_info->to;	return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,					 he->level, bf, size, width); } struct sort_entry sort_dso_from = {	.se_header	= "Source Shared Object",	.se_cmp		= sort__dso_from_cmp,	.se_snprintf	= hist_entry__dso_from_snprintf,	.se_width_idx	= HISTC_DSO_FROM,}; struct sort_entry sort_dso_to = {	.se_header	= "Target Shared Object",	.se_cmp		= sort__dso_to_cmp,	.se_snprintf	= hist_entry__dso_to_snprintf,	.se_width_idx	= HISTC_DSO_TO,}; struct sort_entry sort_sym_from = {	.se_header	= "Source Symbol",	.se_cmp		= sort__sym_from_cmp,	.se_snprintf	= hist_entry__sym_from_snprintf,	.se_width_idx	= HISTC_SYMBOL_FROM,}; struct sort_entry sort_sym_to = {	.se_header	= "Target Symbol",	.se_cmp		= sort__sym_to_cmp,	.se_snprintf	= hist_entry__sym_to_snprintf,	.se_width_idx	= HISTC_SYMBOL_TO,}; static int64_tsort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right){	const unsigned char mp = left->branch_info->flags.mispred !=					right->branch_info->flags.mispred;	const unsigned char p = left->branch_info->flags.predicted !=					right->branch_info->flags.predicted; 	return mp || p;} static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,				    size_t size, unsigned int width){	static const char *out = "N/A"; 	if (he->branch_info->flags.predicted)		out = "N";	else if (he->branch_info->flags.mispred)		out = "Y"; 	return repsep_snprintf(bf, size, "%-*s", width, out);} /* --sort daddr_sym */static int64_tsort__daddr_cmp(struct hist_entry *left, struct hist_entry *right){	uint64_t l = 0, r = 0; 	if (left->mem_info)		l = left->mem_info->daddr.addr;	if (right->mem_info)		r = right->mem_info->daddr.addr; 	return (int64_t)(r - l);} static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,				    size_t size, unsigned int width){	uint64_t addr = 0;	struct map *map = NULL;	struct symbol *sym = NULL; 	if (he->mem_info) {		addr = he->mem_info->daddr.addr;		map = he->mem_info->daddr.map;		sym = he->mem_info->daddr.sym;	}	return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,					 width);} static int64_tsort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right){	struct map *map_l = NULL;	struct map *map_r = NULL; 	if (left->mem_info)		map_l = left->mem_info->daddr.map;	if (right->mem_info)		map_r = right->mem_info->daddr.map;

Lines 1–500 of 1188.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t