2010-08-10 15:37:34 -03:00
# include "../libslang.h"
# include <elf.h>
2011-01-22 20:37:02 -02:00
# include <inttypes.h>
2010-08-10 15:37:34 -03:00
# include <sys/ttydefaults.h>
# include <string.h>
# include <linux/bitops.h>
2012-04-04 00:14:26 -07:00
# include "../../util/util.h"
# include "../../util/debug.h"
# include "../../util/symbol.h"
2010-08-10 15:37:34 -03:00
# include "../browser.h"
# include "../helpline.h"
2013-03-28 11:07:37 -03:00
# include "../keysyms.h"
2010-08-10 15:37:34 -03:00
# include "map.h"
struct map_browser {
struct ui_browser b ;
struct map * map ;
u8 addrlen ;
} ;
2013-11-05 15:32:36 -03:00
static void map_browser__write ( struct ui_browser * browser , void * nd , int row )
2010-08-10 15:37:34 -03:00
{
struct symbol * sym = rb_entry ( nd , struct symbol , rb_node ) ;
2013-11-05 15:32:36 -03:00
struct map_browser * mb = container_of ( browser , struct map_browser , b ) ;
bool current_entry = ui_browser__is_current_entry ( browser , row ) ;
2010-09-13 10:25:04 -03:00
int width ;
2010-08-10 15:37:34 -03:00
2013-11-05 15:32:36 -03:00
ui_browser__set_percent_color ( browser , 0 , current_entry ) ;
2011-01-22 20:37:02 -02:00
slsmg_printf ( " %* " PRIx64 " %* " PRIx64 " %c " ,
2010-08-10 15:37:34 -03:00
mb - > addrlen , sym - > start , mb - > addrlen , sym - > end ,
sym - > binding = = STB_GLOBAL ? ' g ' :
sym - > binding = = STB_LOCAL ? ' l ' : ' w ' ) ;
2013-11-05 15:32:36 -03:00
width = browser - > width - ( ( mb - > addrlen * 2 ) + 4 ) ;
2010-09-13 10:25:04 -03:00
if ( width > 0 )
slsmg_write_nstring ( sym - > name , width ) ;
2010-08-10 15:37:34 -03:00
}
/* FIXME uber-kludgy, see comment on cmd_report... */
2013-11-05 15:32:36 -03:00
static u32 * symbol__browser_index ( struct symbol * browser )
2010-08-10 15:37:34 -03:00
{
2013-11-05 15:32:36 -03:00
return ( ( void * ) browser ) - sizeof ( struct rb_node ) - sizeof ( u32 ) ;
2010-08-10 15:37:34 -03:00
}
2013-11-05 15:32:36 -03:00
static int map_browser__search ( struct map_browser * browser )
2010-08-10 15:37:34 -03:00
{
char target [ 512 ] ;
struct symbol * sym ;
2013-03-28 11:07:37 -03:00
int err = ui_browser__input_window ( " Search by name/addr " ,
" Prefix with 0x to search by address " ,
target , " ENTER: OK, ESC: Cancel " , 0 ) ;
if ( err ! = K_ENTER )
return - 1 ;
2010-08-10 15:37:34 -03:00
if ( target [ 0 ] = = ' 0 ' & & tolower ( target [ 1 ] ) = = ' x ' ) {
u64 addr = strtoull ( target , NULL , 16 ) ;
2013-11-05 15:32:36 -03:00
sym = map__find_symbol ( browser - > map , addr , NULL ) ;
2010-08-10 15:37:34 -03:00
} else
2013-11-05 15:32:36 -03:00
sym = map__find_symbol_by_name ( browser - > map , target , NULL ) ;
2010-08-10 15:37:34 -03:00
if ( sym ! = NULL ) {
u32 * idx = symbol__browser_index ( sym ) ;
2013-11-05 15:32:36 -03:00
browser - > b . top = & sym - > rb_node ;
browser - > b . index = browser - > b . top_idx = * idx ;
2010-08-10 15:37:34 -03:00
} else
ui_helpline__fpush ( " %s not found! " , target ) ;
return 0 ;
}
2013-11-05 15:32:36 -03:00
static int map_browser__run ( struct map_browser * browser )
2010-08-10 15:37:34 -03:00
{
2010-08-11 10:07:43 -03:00
int key ;
2013-11-05 15:32:36 -03:00
if ( ui_browser__show ( & browser - > b , browser - > map - > dso - > long_name ,
2010-08-10 15:44:20 -03:00
" Press <- or ESC to exit, %s / to search " ,
verbose ? " " : " restart with -v to use " ) < 0 )
2010-08-10 15:37:34 -03:00
return - 1 ;
while ( 1 ) {
2013-11-05 15:32:36 -03:00
key = ui_browser__run ( & browser - > b , 0 ) ;
2010-08-10 15:37:34 -03:00
2013-03-28 11:47:17 -03:00
switch ( key ) {
case ' / ' :
if ( verbose )
2013-11-05 15:32:36 -03:00
map_browser__search ( browser ) ;
2013-03-28 11:47:17 -03:00
default :
2010-08-10 15:37:34 -03:00
break ;
2013-03-28 11:47:17 -03:00
case K_LEFT :
case K_ESC :
case ' q ' :
case CTRL ( ' c ' ) :
goto out ;
}
2010-08-10 15:37:34 -03:00
}
2013-03-28 11:47:17 -03:00
out :
2013-11-05 15:32:36 -03:00
ui_browser__hide ( & browser - > b ) ;
2010-08-11 10:07:43 -03:00
return key ;
2010-08-10 15:37:34 -03:00
}
2013-11-05 15:32:36 -03:00
int map__browse ( struct map * map )
2010-08-10 15:37:34 -03:00
{
struct map_browser mb = {
. b = {
2013-11-05 15:32:36 -03:00
. entries = & map - > dso - > symbols [ map - > type ] ,
2010-08-10 15:37:34 -03:00
. refresh = ui_browser__rb_tree_refresh ,
. seek = ui_browser__rb_tree_seek ,
. write = map_browser__write ,
} ,
2013-11-05 15:32:36 -03:00
. map = map ,
2010-08-10 15:37:34 -03:00
} ;
struct rb_node * nd ;
char tmp [ BITS_PER_LONG / 4 ] ;
u64 maxaddr = 0 ;
for ( nd = rb_first ( mb . b . entries ) ; nd ; nd = rb_next ( nd ) ) {
struct symbol * pos = rb_entry ( nd , struct symbol , rb_node ) ;
if ( maxaddr < pos - > end )
maxaddr = pos - > end ;
if ( verbose ) {
u32 * idx = symbol__browser_index ( pos ) ;
* idx = mb . b . nr_entries ;
}
+ + mb . b . nr_entries ;
}
2011-01-22 20:37:02 -02:00
mb . addrlen = snprintf ( tmp , sizeof ( tmp ) , " % " PRIx64 , maxaddr ) ;
2010-08-11 10:07:43 -03:00
return map_browser__run ( & mb ) ;
2010-08-10 15:37:34 -03:00
}