| 
									
										
										
										
											2011-10-26 08:00:55 -02:00
										 |  |  | #include "../../util.h"
 | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | #include "../browser.h"
 | 
					
						
							|  |  |  | #include "../helpline.h"
 | 
					
						
							|  |  |  | #include "../libslang.h"
 | 
					
						
							| 
									
										
										
										
											2011-10-26 08:00:55 -02:00
										 |  |  | #include "../ui.h"
 | 
					
						
							|  |  |  | #include "../util.h"
 | 
					
						
							| 
									
										
										
										
											2011-02-04 09:45:46 -02:00
										 |  |  | #include "../../annotate.h"
 | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | #include "../../hist.h"
 | 
					
						
							|  |  |  | #include "../../sort.h"
 | 
					
						
							|  |  |  | #include "../../symbol.h"
 | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | #include <pthread.h>
 | 
					
						
							| 
									
										
										
										
											2011-10-20 16:59:15 -02:00
										 |  |  | #include <newt.h>
 | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | struct annotate_browser { | 
					
						
							|  |  |  | 	struct ui_browser b; | 
					
						
							|  |  |  | 	struct rb_root	  entries; | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | 	struct rb_node	  *curr_hot; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 	struct objdump_line *selection; | 
					
						
							| 
									
										
										
										
											2011-10-14 12:31:21 -03:00
										 |  |  | 	int		    nr_asm_entries; | 
					
						
							|  |  |  | 	int		    nr_entries; | 
					
						
							|  |  |  | 	bool		    hide_src_code; | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct objdump_line_rb_node { | 
					
						
							|  |  |  | 	struct rb_node	rb_node; | 
					
						
							|  |  |  | 	double		percent; | 
					
						
							|  |  |  | 	u32		idx; | 
					
						
							| 
									
										
										
										
											2011-10-14 12:31:21 -03:00
										 |  |  | 	int		idx_asm; | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline | 
					
						
							|  |  |  | struct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (struct objdump_line_rb_node *)(self + 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-14 12:31:21 -03:00
										 |  |  | static bool objdump_line__filter(struct ui_browser *browser, void *entry) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ab->hide_src_code) { | 
					
						
							|  |  |  | 		struct objdump_line *ol = list_entry(entry, struct objdump_line, node); | 
					
						
							|  |  |  | 		return ol->offset == -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | static void annotate_browser__write(struct ui_browser *self, void *entry, int row) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 	struct annotate_browser *ab = container_of(self, struct annotate_browser, b); | 
					
						
							| 
									
										
										
										
											2011-10-14 12:31:21 -03:00
										 |  |  | 	struct objdump_line *ol = list_entry(entry, struct objdump_line, node); | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 	bool current_entry = ui_browser__is_current_entry(self, row); | 
					
						
							|  |  |  | 	int width = self->width; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ol->offset != -1) { | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 		struct objdump_line_rb_node *olrb = objdump_line__rb(ol); | 
					
						
							| 
									
										
										
										
											2010-08-11 14:51:47 -03:00
										 |  |  | 		ui_browser__set_percent_color(self, olrb->percent, current_entry); | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 		slsmg_printf(" %7.2f ", olrb->percent); | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2010-08-11 14:51:47 -03:00
										 |  |  | 		ui_browser__set_percent_color(self, 0, current_entry); | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 		slsmg_write_nstring(" ", 9); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SLsmg_write_char(':'); | 
					
						
							|  |  |  | 	slsmg_write_nstring(" ", 8); | 
					
						
							| 
									
										
										
										
											2011-10-18 14:31:35 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* The scroll bar isn't being used */ | 
					
						
							|  |  |  | 	if (!self->navkeypressed) | 
					
						
							|  |  |  | 		width += 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-23 17:46:20 +09:00
										 |  |  | 	if (!ab->hide_src_code && ol->offset != -1) | 
					
						
							|  |  |  | 		if (!current_entry || (self->use_navkeypressed && | 
					
						
							|  |  |  | 				       !self->navkeypressed)) | 
					
						
							|  |  |  | 			ui_browser__set_color(self, HE_COLORSET_CODE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 	if (!*ol->line) | 
					
						
							|  |  |  | 		slsmg_write_nstring(" ", width - 18); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		slsmg_write_nstring(ol->line, width - 18); | 
					
						
							| 
									
										
										
										
											2011-02-09 13:59:14 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-23 17:46:20 +09:00
										 |  |  | 	if (current_entry) | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 		ab->selection = ol; | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static double objdump_line__calc_percent(struct objdump_line *self, | 
					
						
							| 
									
										
										
										
											2011-02-04 13:43:24 -02:00
										 |  |  | 					 struct symbol *sym, int evidx) | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	double percent = 0.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (self->offset != -1) { | 
					
						
							|  |  |  | 		int len = sym->end - sym->start; | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 		unsigned int hits = 0; | 
					
						
							| 
									
										
										
										
											2011-02-04 09:45:46 -02:00
										 |  |  | 		struct annotation *notes = symbol__annotation(sym); | 
					
						
							| 
									
										
										
										
											2011-02-08 13:27:39 -02:00
										 |  |  | 		struct source_line *src_line = notes->src->lines; | 
					
						
							| 
									
										
										
										
											2011-02-04 13:43:24 -02:00
										 |  |  | 		struct sym_hist *h = annotation__histogram(notes, evidx); | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 		s64 offset = self->offset; | 
					
						
							| 
									
										
										
										
											2011-02-08 13:27:39 -02:00
										 |  |  | 		struct objdump_line *next; | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-08 13:27:39 -02:00
										 |  |  | 		next = objdump__get_next_ip_line(¬es->src->source, self); | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 		while (offset < (s64)len && | 
					
						
							|  |  |  | 		       (next == NULL || offset < next->offset)) { | 
					
						
							| 
									
										
										
										
											2011-02-04 09:45:46 -02:00
										 |  |  | 			if (src_line) { | 
					
						
							|  |  |  | 				percent += src_line[offset].percent; | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 			} else | 
					
						
							| 
									
										
										
										
											2011-02-04 09:45:46 -02:00
										 |  |  | 				hits += h->addr[offset]; | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			++offset; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-02-04 09:45:46 -02:00
										 |  |  | 		/*
 | 
					
						
							|  |  |  |  		 * If the percentage wasn't already calculated in | 
					
						
							|  |  |  |  		 * symbol__get_source_line, do it now: | 
					
						
							|  |  |  |  		 */ | 
					
						
							|  |  |  | 		if (src_line == NULL && h->sum) | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 			percent = 100.0 * hits / h->sum; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 	return percent; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void objdump__insert_line(struct rb_root *self, | 
					
						
							|  |  |  | 				 struct objdump_line_rb_node *line) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct rb_node **p = &self->rb_node; | 
					
						
							|  |  |  | 	struct rb_node *parent = NULL; | 
					
						
							|  |  |  | 	struct objdump_line_rb_node *l; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (*p != NULL) { | 
					
						
							|  |  |  | 		parent = *p; | 
					
						
							|  |  |  | 		l = rb_entry(parent, struct objdump_line_rb_node, rb_node); | 
					
						
							|  |  |  | 		if (line->percent < l->percent) | 
					
						
							|  |  |  | 			p = &(*p)->rb_left; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			p = &(*p)->rb_right; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	rb_link_node(&line->rb_node, parent, p); | 
					
						
							|  |  |  | 	rb_insert_color(&line->rb_node, self); | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | static void annotate_browser__set_top(struct annotate_browser *self, | 
					
						
							|  |  |  | 				      struct rb_node *nd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct objdump_line_rb_node *rbpos; | 
					
						
							|  |  |  | 	struct objdump_line *pos; | 
					
						
							|  |  |  | 	unsigned back; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ui_browser__refresh_dimensions(&self->b); | 
					
						
							|  |  |  | 	back = self->b.height / 2; | 
					
						
							|  |  |  | 	rbpos = rb_entry(nd, struct objdump_line_rb_node, rb_node); | 
					
						
							|  |  |  | 	pos = ((struct objdump_line *)rbpos) - 1; | 
					
						
							|  |  |  | 	self->b.top_idx = self->b.index = rbpos->idx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (self->b.top_idx != 0 && back != 0) { | 
					
						
							|  |  |  | 		pos = list_entry(pos->node.prev, struct objdump_line, node); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		--self->b.top_idx; | 
					
						
							|  |  |  | 		--back; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	self->b.top = pos; | 
					
						
							|  |  |  | 	self->curr_hot = nd; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | static void annotate_browser__calc_percent(struct annotate_browser *browser, | 
					
						
							|  |  |  | 					   int evidx) | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 	struct map_symbol *ms = browser->b.priv; | 
					
						
							|  |  |  | 	struct symbol *sym = ms->sym; | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 	struct annotation *notes = symbol__annotation(sym); | 
					
						
							|  |  |  | 	struct objdump_line *pos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	browser->entries = RB_ROOT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pthread_mutex_lock(¬es->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list_for_each_entry(pos, ¬es->src->source, node) { | 
					
						
							|  |  |  | 		struct objdump_line_rb_node *rbpos = objdump_line__rb(pos); | 
					
						
							|  |  |  | 		rbpos->percent = objdump_line__calc_percent(pos, sym, evidx); | 
					
						
							|  |  |  | 		if (rbpos->percent < 0.01) { | 
					
						
							|  |  |  | 			RB_CLEAR_NODE(&rbpos->rb_node); | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		objdump__insert_line(&browser->entries, rbpos); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	pthread_mutex_unlock(¬es->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	browser->curr_hot = rb_last(&browser->entries); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-14 12:31:21 -03:00
										 |  |  | static bool annotate_browser__toggle_source(struct annotate_browser *browser) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct objdump_line *ol; | 
					
						
							|  |  |  | 	struct objdump_line_rb_node *olrb; | 
					
						
							|  |  |  | 	off_t offset = browser->b.index - browser->b.top_idx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	browser->b.seek(&browser->b, offset, SEEK_CUR); | 
					
						
							|  |  |  | 	ol = list_entry(browser->b.top, struct objdump_line, node); | 
					
						
							|  |  |  | 	olrb = objdump_line__rb(ol); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (browser->hide_src_code) { | 
					
						
							|  |  |  | 		if (olrb->idx_asm < offset) | 
					
						
							|  |  |  | 			offset = olrb->idx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		browser->b.nr_entries = browser->nr_entries; | 
					
						
							|  |  |  | 		browser->hide_src_code = false; | 
					
						
							|  |  |  | 		browser->b.seek(&browser->b, -offset, SEEK_CUR); | 
					
						
							|  |  |  | 		browser->b.top_idx = olrb->idx - offset; | 
					
						
							|  |  |  | 		browser->b.index = olrb->idx; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if (olrb->idx_asm < 0) { | 
					
						
							|  |  |  | 			ui_helpline__puts("Only available for assembly lines."); | 
					
						
							|  |  |  | 			browser->b.seek(&browser->b, -offset, SEEK_CUR); | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (olrb->idx_asm < offset) | 
					
						
							|  |  |  | 			offset = olrb->idx_asm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		browser->b.nr_entries = browser->nr_asm_entries; | 
					
						
							|  |  |  | 		browser->hide_src_code = true; | 
					
						
							|  |  |  | 		browser->b.seek(&browser->b, -offset, SEEK_CUR); | 
					
						
							|  |  |  | 		browser->b.top_idx = olrb->idx_asm - offset; | 
					
						
							|  |  |  | 		browser->b.index = olrb->idx_asm; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | static int annotate_browser__run(struct annotate_browser *self, int evidx, | 
					
						
							| 
									
										
										
										
											2011-11-11 22:17:32 -02:00
										 |  |  | 				 void(*timer)(void *arg), | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 				 void *arg, int delay_secs) | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct rb_node *nd = NULL; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 	struct map_symbol *ms = self->b.priv; | 
					
						
							|  |  |  | 	struct symbol *sym = ms->sym; | 
					
						
							| 
									
										
										
										
											2012-02-23 17:46:23 +09:00
										 |  |  | 	const char *help = "<-/ESC: Exit, TAB/shift+TAB: Cycle hot lines, " | 
					
						
							|  |  |  | 			   "H: Go to hottest line, ->/ENTER: Line action, " | 
					
						
							|  |  |  | 			   "S: Toggle source code view"; | 
					
						
							| 
									
										
										
										
											2010-08-11 10:07:43 -03:00
										 |  |  | 	int key; | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-14 12:31:21 -03:00
										 |  |  | 	if (ui_browser__show(&self->b, sym->name, help) < 0) | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	annotate_browser__calc_percent(self, evidx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (self->curr_hot) | 
					
						
							|  |  |  | 		annotate_browser__set_top(self, self->curr_hot); | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	nd = self->curr_hot; | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | 	while (1) { | 
					
						
							| 
									
										
										
										
											2011-10-13 08:52:46 -03:00
										 |  |  | 		key = ui_browser__run(&self->b, delay_secs); | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 19:11:32 -03:00
										 |  |  | 		if (delay_secs != 0) { | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 			annotate_browser__calc_percent(self, evidx); | 
					
						
							|  |  |  | 			/*
 | 
					
						
							|  |  |  | 			 * Current line focus got out of the list of most active | 
					
						
							|  |  |  | 			 * lines, NULL it so that if TAB|UNTAB is pressed, we | 
					
						
							|  |  |  | 			 * move to curr_hot (current hottest line). | 
					
						
							|  |  |  | 			 */ | 
					
						
							|  |  |  | 			if (nd != NULL && RB_EMPTY_NODE(nd)) | 
					
						
							|  |  |  | 				nd = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 10:07:43 -03:00
										 |  |  | 		switch (key) { | 
					
						
							| 
									
										
										
										
											2011-10-20 16:59:15 -02:00
										 |  |  | 		case K_TIMER: | 
					
						
							| 
									
										
										
										
											2011-10-05 19:11:32 -03:00
										 |  |  | 			if (timer != NULL) | 
					
						
							|  |  |  | 				timer(arg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (delay_secs != 0) | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 				symbol__annotate_decay_histogram(sym, evidx); | 
					
						
							|  |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2011-10-20 16:59:15 -02:00
										 |  |  | 		case K_TAB: | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 			if (nd != NULL) { | 
					
						
							|  |  |  | 				nd = rb_prev(nd); | 
					
						
							|  |  |  | 				if (nd == NULL) | 
					
						
							|  |  |  | 					nd = rb_last(&self->entries); | 
					
						
							|  |  |  | 			} else | 
					
						
							|  |  |  | 				nd = self->curr_hot; | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2011-10-20 16:59:15 -02:00
										 |  |  | 		case K_UNTAB: | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 			if (nd != NULL) | 
					
						
							|  |  |  | 				nd = rb_next(nd); | 
					
						
							|  |  |  | 				if (nd == NULL) | 
					
						
							|  |  |  | 					nd = rb_first(&self->entries); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				nd = self->curr_hot; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 'H': | 
					
						
							| 
									
										
										
										
											2012-02-23 17:46:21 +09:00
										 |  |  | 		case 'h': | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 			nd = self->curr_hot; | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2011-10-14 12:31:21 -03:00
										 |  |  | 		case 'S': | 
					
						
							| 
									
										
										
										
											2012-02-23 17:46:21 +09:00
										 |  |  | 		case 's': | 
					
						
							| 
									
										
										
										
											2011-10-14 12:31:21 -03:00
										 |  |  | 			if (annotate_browser__toggle_source(self)) | 
					
						
							|  |  |  | 				ui_helpline__puts(help); | 
					
						
							|  |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2011-10-20 16:59:15 -02:00
										 |  |  | 		case K_ENTER: | 
					
						
							|  |  |  | 		case K_RIGHT: | 
					
						
							| 
									
										
										
										
											2011-10-06 09:45:29 -03:00
										 |  |  | 			if (self->selection == NULL) { | 
					
						
							|  |  |  | 				ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (self->selection->offset == -1) { | 
					
						
							|  |  |  | 				ui_helpline__puts("Actions are only available for assembly lines."); | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 				char *s = strstr(self->selection->line, "callq "); | 
					
						
							|  |  |  | 				struct annotation *notes; | 
					
						
							|  |  |  | 				struct symbol *target; | 
					
						
							|  |  |  | 				u64 ip; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-06 09:45:29 -03:00
										 |  |  | 				if (s == NULL) { | 
					
						
							|  |  |  | 					ui_helpline__puts("Actions are only available for the 'callq' instruction."); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 					continue; | 
					
						
							| 
									
										
										
										
											2011-10-06 09:45:29 -03:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				s = strchr(s, ' '); | 
					
						
							| 
									
										
										
										
											2011-10-06 09:45:29 -03:00
										 |  |  | 				if (s++ == NULL) { | 
					
						
							|  |  |  | 					ui_helpline__puts("Invallid callq instruction."); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 					continue; | 
					
						
							| 
									
										
										
										
											2011-10-06 09:45:29 -03:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				ip = strtoull(s, NULL, 16); | 
					
						
							|  |  |  | 				ip = ms->map->map_ip(ms->map, ip); | 
					
						
							|  |  |  | 				target = map__find_symbol(ms->map, ip, NULL); | 
					
						
							| 
									
										
										
										
											2011-10-06 09:45:29 -03:00
										 |  |  | 				if (target == NULL) { | 
					
						
							|  |  |  | 					ui_helpline__puts("The called function was not found."); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 					continue; | 
					
						
							| 
									
										
										
										
											2011-10-06 09:45:29 -03:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				notes = symbol__annotation(target); | 
					
						
							|  |  |  | 				pthread_mutex_lock(¬es->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-11 22:17:32 -02:00
										 |  |  | 				if (notes->src == NULL && symbol__alloc_hist(target) < 0) { | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 					pthread_mutex_unlock(¬es->lock); | 
					
						
							|  |  |  | 					ui__warning("Not enough memory for annotating '%s' symbol!\n", | 
					
						
							|  |  |  | 						    target->name); | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				pthread_mutex_unlock(¬es->lock); | 
					
						
							| 
									
										
										
										
											2011-11-11 22:17:32 -02:00
										 |  |  | 				symbol__tui_annotate(target, ms->map, evidx, | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 						     timer, arg, delay_secs); | 
					
						
							| 
									
										
										
										
											2012-02-23 17:46:22 +09:00
										 |  |  | 				ui_browser__show_title(&self->b, sym->name); | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-10-19 13:18:13 -02:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2011-10-20 16:59:15 -02:00
										 |  |  | 		case K_LEFT: | 
					
						
							|  |  |  | 		case K_ESC: | 
					
						
							| 
									
										
										
										
											2011-10-13 08:31:22 -03:00
										 |  |  | 		case 'q': | 
					
						
							|  |  |  | 		case CTRL('c'): | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | 			goto out; | 
					
						
							| 
									
										
										
										
											2011-10-13 08:31:22 -03:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (nd != NULL) | 
					
						
							|  |  |  | 			annotate_browser__set_top(self, nd); | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | out: | 
					
						
							| 
									
										
										
										
											2010-08-10 15:44:20 -03:00
										 |  |  | 	ui_browser__hide(&self->b); | 
					
						
							| 
									
										
										
										
											2010-08-11 10:07:43 -03:00
										 |  |  | 	return key; | 
					
						
							| 
									
										
										
										
											2010-08-10 15:14:53 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-11 22:17:32 -02:00
										 |  |  | int hist_entry__tui_annotate(struct hist_entry *he, int evidx, | 
					
						
							| 
									
										
										
										
											2011-10-05 19:11:32 -03:00
										 |  |  | 			     void(*timer)(void *arg), void *arg, int delay_secs) | 
					
						
							| 
									
										
										
										
											2011-02-04 09:45:46 -02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-11-11 22:17:32 -02:00
										 |  |  | 	return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, | 
					
						
							| 
									
										
										
										
											2011-10-05 19:11:32 -03:00
										 |  |  | 				    timer, arg, delay_secs); | 
					
						
							| 
									
										
										
										
											2011-02-04 09:45:46 -02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, | 
					
						
							| 
									
										
										
										
											2011-11-11 22:17:32 -02:00
										 |  |  | 			 void(*timer)(void *arg), void *arg, | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 			 int delay_secs) | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct objdump_line *pos, *n; | 
					
						
							| 
									
										
										
										
											2011-04-08 14:31:26 +08:00
										 |  |  | 	struct annotation *notes; | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 	struct map_symbol ms = { | 
					
						
							|  |  |  | 		.map = map, | 
					
						
							|  |  |  | 		.sym = sym, | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 	struct annotate_browser browser = { | 
					
						
							|  |  |  | 		.b = { | 
					
						
							|  |  |  | 			.refresh = ui_browser__list_head_refresh, | 
					
						
							|  |  |  | 			.seek	 = ui_browser__list_head_seek, | 
					
						
							|  |  |  | 			.write	 = annotate_browser__write, | 
					
						
							| 
									
										
										
										
											2011-10-14 12:31:21 -03:00
										 |  |  | 			.filter  = objdump_line__filter, | 
					
						
							| 
									
										
										
										
											2011-10-05 19:35:54 -03:00
										 |  |  | 			.priv	 = &ms, | 
					
						
							| 
									
										
										
										
											2011-10-18 14:31:35 -02:00
										 |  |  | 			.use_navkeypressed = true, | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-04 09:45:46 -02:00
										 |  |  | 	if (sym == NULL) | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-04 09:45:46 -02:00
										 |  |  | 	if (map->dso->annotate_warned) | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 	if (symbol__annotate(sym, map, sizeof(struct objdump_line_rb_node)) < 0) { | 
					
						
							| 
									
										
										
										
											2011-10-26 08:00:55 -02:00
										 |  |  | 		ui__error("%s", ui_helpline__last_msg); | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ui_helpline__push("Press <- or ESC to exit"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-08 14:31:26 +08:00
										 |  |  | 	notes = symbol__annotation(sym); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-08 13:27:39 -02:00
										 |  |  | 	list_for_each_entry(pos, ¬es->src->source, node) { | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 		struct objdump_line_rb_node *rbpos; | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 		size_t line_len = strlen(pos->line); | 
					
						
							| 
									
										
										
										
											2011-02-22 12:02:07 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 		if (browser.b.width < line_len) | 
					
						
							|  |  |  | 			browser.b.width = line_len; | 
					
						
							|  |  |  | 		rbpos = objdump_line__rb(pos); | 
					
						
							| 
									
										
										
										
											2011-10-14 12:31:21 -03:00
										 |  |  | 		rbpos->idx = browser.nr_entries++; | 
					
						
							|  |  |  | 		if (pos->offset != -1) | 
					
						
							|  |  |  | 			rbpos->idx_asm = browser.nr_asm_entries++; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			rbpos->idx_asm = -1; | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-14 12:31:21 -03:00
										 |  |  | 	browser.b.nr_entries = browser.nr_entries; | 
					
						
							| 
									
										
										
										
											2011-04-08 14:31:26 +08:00
										 |  |  | 	browser.b.entries = ¬es->src->source, | 
					
						
							| 
									
										
										
										
											2010-08-09 15:30:40 -03:00
										 |  |  | 	browser.b.width += 18; /* Percentage */ | 
					
						
							| 
									
										
										
										
											2011-11-11 22:17:32 -02:00
										 |  |  | 	ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs); | 
					
						
							| 
									
										
										
										
											2011-02-08 13:27:39 -02:00
										 |  |  | 	list_for_each_entry_safe(pos, n, ¬es->src->source, node) { | 
					
						
							| 
									
										
										
										
											2010-08-10 14:54:09 -03:00
										 |  |  | 		list_del(&pos->node); | 
					
						
							|  |  |  | 		objdump_line__free(pos); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } |