From 52bdcbae856b07d3a793615b98dff338d26302ec Mon Sep 17 00:00:00 2001 From: Michael Giacomelli Date: Mon, 28 Jul 2008 22:43:41 +0000 Subject: Commit FS#9170 by Dave Hooper. Adds support for profiling on ARM, and fixes various issues with compiling profile builds. Also, note that profile_reader.pl syntax has changed. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18142 a1c6a512-1295-4272-9138-f99709370657 --- apps/codecs.c | 4 ++-- apps/codecs/SOURCES | 2 ++ apps/plugin.c | 4 ++-- apps/plugins/SUBDIRS | 4 ++++ firmware/export/profile.h | 4 ++-- firmware/profile.c | 23 +++++++++++--------- tools/profile_reader/profile_reader.pl | 39 +++++++++++++++++++++++----------- 7 files changed, 52 insertions(+), 28 deletions(-) diff --git a/apps/codecs.c b/apps/codecs.c index c31fd843b3..24490dd04b 100644 --- a/apps/codecs.c +++ b/apps/codecs.c @@ -138,8 +138,8 @@ struct codec_api ci = { #ifdef RB_PROFILE profile_thread, profstop, - profile_func_enter, - profile_func_exit, + __cyg_profile_func_enter, + __cyg_profile_func_exit, #endif #if defined(HAVE_RECORDING) && !defined(SIMULATOR) diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES index 25ca5490d4..3038903f9e 100644 --- a/apps/codecs/SOURCES +++ b/apps/codecs/SOURCES @@ -7,7 +7,9 @@ wav.c a52.c mpc.c wavpack.c +#ifndef RB_PROFILE alac.c +#endif wma.c #if MEMORYSIZE > 1 aac.c diff --git a/apps/plugin.c b/apps/plugin.c index a220e8c429..24082de637 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -335,8 +335,8 @@ static const struct plugin_api rockbox_api = { #ifdef RB_PROFILE profile_thread, profstop, - profile_func_enter, - profile_func_exit, + __cyg_profile_func_enter, + __cyg_profile_func_exit, #endif #ifdef SIMULATOR diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS index 94614e2f12..1b3e2af252 100644 --- a/apps/plugins/SUBDIRS +++ b/apps/plugins/SUBDIRS @@ -33,14 +33,18 @@ pacbox /* For all the color targets */ #if defined(HAVE_LCD_COLOR) || defined(MROBE_100) || \ (LCD_DEPTH == 2) && !defined(ARCHOS_AV300) +#ifndef RB_PROFILE doom #endif +#endif /* For all the swcodec targets */ #if CONFIG_CODEC == SWCODEC midi /* beatbox */ +#ifndef RB_PROFILE mpegplayer #endif +#endif #endif /* IRIVER_IFP7XX_SERIES */ diff --git a/firmware/export/profile.h b/firmware/export/profile.h index d173f4b6e0..18a6f8679f 100644 --- a/firmware/export/profile.h +++ b/firmware/export/profile.h @@ -39,9 +39,9 @@ void profile_thread_stopped(int current_thread) void profile_thread_started(int current_thread) NO_PROF_ATTR; -void profile_func_exit(void *this_fn, void *call_site) +void __cyg_profile_func_exit(void *this_fn, void *call_site) NO_PROF_ATTR ICODE_ATTR; -void profile_func_enter(void *this_fn, void *call_site) +void __cyg_profile_func_enter(void *this_fn, void *call_site) NO_PROF_ATTR ICODE_ATTR; #endif /*_SYS_PROFILE_H*/ diff --git a/firmware/profile.c b/firmware/profile.c index f84eebe3f1..cb68f18d8e 100644 --- a/firmware/profile.c +++ b/firmware/profile.c @@ -62,7 +62,6 @@ #include #include "profile.h" - /* PFD is Profiled Function Data */ /* Indices are shorts which means that we use 4k of RAM */ @@ -75,7 +74,7 @@ * for profiling, and allows for profiling sections of code with up-to * 1024 function caller->callee pairs */ -#define NUMPFDS 1024 +#define NUMPFDS 512 struct pfd_struct { void *self_pc; @@ -141,7 +140,7 @@ void profile_thread_started(int current_thread) { if (profiling < PROF_ERROR) { /* After we de-mask, if profiling is active, reactivate the timer */ timer_register(0, profile_timer_unregister, - TIMER_FREQ/10000, 0, profile_timer_tick); + TIMER_FREQ/10000, 0, profile_timer_tick IF_COP(, 0 ) ); } } } @@ -168,9 +167,9 @@ void profstart(int current_thread) { last_pfd = (struct pfd_struct*)0; pfds[0].link = 0; pfds[0].self_pc = 0; - memset(&indices,0,INDEX_SIZE * sizeof(unsigned short)); + memset(indices,0,INDEX_SIZE * sizeof(unsigned short)); timer_register( - 0, profile_timer_unregister, TIMER_FREQ/10000, 0, profile_timer_tick); + 0, profile_timer_unregister, TIMER_FREQ/10000, 0, profile_timer_tick IF_COP(, 0 ) ); profiling = PROF_ON; } @@ -179,7 +178,7 @@ static void write_function_recursive(int fd, struct pfd_struct *pfd, int depth){ fdprintf(fd,"0x%08lX\t%08ld\t%08ld\t%04d\n", (size_t)pfd->self_pc, pfd->count, pfd->time, depth); if (link > 0 && link < NUMPFDS) { - write_function_recursive(fd, &pfds[link], depth++); + write_function_recursive(fd, &pfds[link], ++depth); } } @@ -206,7 +205,7 @@ void profstop() { } } fdprintf(fd,"DEBUG PROFILE DATA FOLLOWS\n"); - fdprintf(fd,"INDEX\tLOCATION\tSELF_PC\t\tCOUNT\t\tTIME\t\tLINK\tCALLER\n"); + fdprintf(fd,"INDEX\tLOCATION\tSELF_PC\t\tCOUNT\t\tTIME\t\tLINK\tCALLER_IDX\n"); for (i = 0; i < NUMPFDS; i++) { struct pfd_struct *my_last_pfd = &pfds[i]; if (my_last_pfd->self_pc != 0) { @@ -214,7 +213,7 @@ void profstop() { "%04d\t0x%08lX\t0x%08lX\t0x%08lX\t0x%08lX\t%04d\t0x%08lX\n", i, (size_t)my_last_pfd, (size_t)my_last_pfd->self_pc, my_last_pfd->count, my_last_pfd->time, my_last_pfd->link, - (size_t)my_last_pfd->caller); + (size_t)my_last_pfd->caller ); } } fdprintf(fd,"INDEX_ADDRESS=INDEX\n"); @@ -224,7 +223,7 @@ void profstop() { close(fd); } -void profile_func_exit(void *self_pc, void *call_site) { +void __cyg_profile_func_exit(void *self_pc, void *call_site) { (void)call_site; (void)self_pc; /* When we started timing, we set the time to the tick at that time @@ -255,7 +254,7 @@ void profile_func_exit(void *self_pc, void *call_site) { pfd = &pfds[temp];\ pfd->self_pc = self_pc; pfd->count = 1; pfd->time = 0 -void profile_func_enter(void *self_pc, void *from_pc) { +void __cyg_profile_func_enter(void *self_pc, void *from_pc) { struct pfd_struct *pfd; struct pfd_struct *prev_pfd; unsigned short *pfd_index_pointer; @@ -339,3 +338,7 @@ overflow: profiling = PROF_ERROR; return; } + + + + diff --git a/tools/profile_reader/profile_reader.pl b/tools/profile_reader/profile_reader.pl index 6a45ddef02..ca40a901d8 100755 --- a/tools/profile_reader/profile_reader.pl +++ b/tools/profile_reader/profile_reader.pl @@ -36,11 +36,11 @@ sub read_map { return %retval; } -# string (filename.[ao]), hash(string:number) +# string (filename.(a|o|elf)), hash(number:string), string(objdump_tool) # return hash(number:string) sub read_library { - open(OBJECT_FILE,"objdump -t $_[0] |") || - error("Couldn't pipe objdump for $_[0]"); + open(OBJECT_FILE,"$_[2] -t $_[0] |") || + error("Couldn't pipe objdump for $_[0]\nCommand was: $_[2] -t $_[0]"); my $library = $_[1]; my %library = %$library; my %retval; @@ -62,7 +62,7 @@ sub read_library { if ($parts[3] eq $parts[5]) { next; } - if ($parts[3] =~ m/\.(text|data|rodata|bss|icode|idata|irodata|ibss)/) { + if ($parts[3] =~ m/\.(text|data|rodata|bss|icode|idata|irodata|ibss|iram)/) { my $region = $parts[3]; my $symbolOffset = hex("0x" . $parts[0]); my $sectionOffset = hex($library{$object . $region}); @@ -139,8 +139,16 @@ sub print_sorted { my $totalCalls = 0; my $totalTicks = 0; $pfds = 0; + + # we use a key sort, which means numerical fields need to be + # numerically sortable by an alphanumeric sort - we can simply + # do this by giving the numeric keys trailing zeros. Note that + # simple string concatenation (what this used to do) would not do this foreach $element(@pfds) { - $elements{@$element[$sort_index] . @$element[2]} = $element; + $ne = $element; + @$ne[0] = sprintf( "%08d", @$element[0]); + @$ne[1] = sprintf( "%08d", @$element[1]); + $elements{@$ne[$sort_index] . @$element[2]} = $element; $pfds++; $totalCalls += @$element[0]; $totalTicks += @$element[1]; @@ -174,13 +182,17 @@ sub usage { print STDERR ("Error: @_\n"); } print STDERR ("USAGE:\n"); - print STDERR ("$0 profile.out map obj[...] [map obj[...]...] sort[...]\n"); + print STDERR ("$0 profile.out objdump_tool map obj[...] [map obj[...]...] sort[...]\n"); print STDERR ("\tprofile.out output from the profiler, extension is .out\n"); + print STDERR + ("\tobjdump_tool name of objdump executable for this platform\n"); + print STDERR + ("\t e.g. arm-elf-objdump\n"); print STDERR ("\tmap map file, extension is .map\n"); print STDERR - ("\tobj library or object file, extension is .a or .o\n"); + ("\tobj library or object file, extension is .a or .o or .elf\n"); print STDERR ("\tformat 0-2[_p] 0: by calls, 1: by ticks, 2: by name\n"); print STDERR @@ -195,13 +207,13 @@ sub usage { if ($ARGV[0] =~ m/-(h|help|-help)/) { usage(); } -if (@ARGV < 2) { - usage("Requires at least 2 arguments"); +if (@ARGV < 3) { + usage("Requires at least 3 arguments"); } if ($ARGV[0] !~ m/\.out$/) { usage("Profile file must end in .out"); } -my $i = 1; +my $i = 2; my %symbols; { my %map; @@ -209,12 +221,12 @@ my %symbols; my $file = $ARGV[$i]; if ($file =~ m/\.map$/) { %map = read_map($file); - } elsif ($file =~ m/\.[ao]$/) { + } elsif ($file =~ m/\.(a|o|elf)$/) { if (!%map) { usage("No map file found before first object file"); } my @parts = split(/\//,$file); - my %new_symbols = read_library($file,$map{$parts[$#parts]}); + my %new_symbols = read_library($file,$map{$parts[$#parts]},$ARGV[1]); %symbols = merge_hashes(\%symbols,\%new_symbols); } else { last; @@ -224,6 +236,9 @@ my %symbols; if (!%symbols) { warning("No symbols found"); } +if ($i >= @ARGV) { + error("You forgot to specify any sort ordering on output (e.g. 0, 1_p, 2)"); +} my @pfds = create_list($ARGV[0],\%symbols); for (; $i < @ARGV; $i++) { print_sorted(\@pfds,split("_",$ARGV[$i])); -- cgit v1.2.3