From 4ad6db345b6aea4b8ef99d308659178d8123f141 Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Mon, 24 Aug 2015 23:24:30 +0200 Subject: [PATCH 1/7] nixprof: make private stuff static --- core/linux/nixprof/nixprof.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/core/linux/nixprof/nixprof.cpp b/core/linux/nixprof/nixprof.cpp index 3bd110094..74eb4c283 100644 --- a/core/linux/nixprof/nixprof.cpp +++ b/core/linux/nixprof/nixprof.cpp @@ -46,14 +46,14 @@ #include #include -int tick_count=0; -pthread_t proft; -pthread_t thread[2]; -void* prof_address[2]; -u32 prof_wait; +static int tick_count=0; +static pthread_t proft; +static pthread_t thread[2]; +static void* prof_address[2]; +static u32 prof_wait; -u8* syms_ptr; -int syms_len; +static u8* syms_ptr; +static int syms_len; void sample_Syms(u8* data,u32 len) { @@ -88,16 +88,17 @@ void install_prof_handler(int id) thread[id]=pthread_self(); } -void prof_head(FILE* out, const char* type, const char* name) +static void prof_head(FILE* out, const char* type, const char* name) { fprintf(out,"==xx==xx==\n%s:%s\n",type,name); } -void prof_head(FILE* out, const char* type, int d) + +static void prof_head(FILE* out, const char* type, int d) { fprintf(out,"==xx==xx==\n%s:%d\n",type,d); } -void elf_syms(FILE* out,const char* libfile) +static void elf_syms(FILE* out,const char* libfile) { struct stat statbuf; @@ -182,9 +183,10 @@ void elf_syms(FILE* out,const char* libfile) -volatile bool prof_run; +static volatile bool prof_run; -int str_ends_with(const char * str, const char * suffix) +// This is not used: +static int str_ends_with(const char * str, const char * suffix) { if (str == NULL || suffix == NULL) return 0; @@ -200,7 +202,7 @@ int str_ends_with(const char * str, const char * suffix) void sh4_jitsym(FILE* out); -void* prof(void *ptr) +static void* prof(void *ptr) { FILE* prof_out; char line[512]; @@ -300,4 +302,4 @@ void sample_Stop() } printf("sampling profiler: stopped\n"); } -#endif \ No newline at end of file +#endif From ad068dcff29d3b56e142aa86ae8cf5204ab1a3db Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Tue, 25 Aug 2015 00:54:23 +0200 Subject: [PATCH 2/7] Bind profiling in X11 to F10 --- core/hw/pvr/Renderer_if.cpp | 8 ++++++++ core/linux-dist/main.cpp | 6 ++++++ core/linux-dist/x11.cpp | 14 ++++++++++++++ core/linux/nixprof/nixprof.cpp | 23 ++++++++++++++++++----- core/profiler/profiler.h | 3 ++- 5 files changed, 48 insertions(+), 6 deletions(-) diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index 5dc8183b5..e84ad1103 100644 --- a/core/hw/pvr/Renderer_if.cpp +++ b/core/hw/pvr/Renderer_if.cpp @@ -5,6 +5,10 @@ #include "deps/zlib/zlib.h" +#if FEAT_HAS_NIXPROF +#include "profiler/profiler.h" +#endif + /* rendv3 ideas @@ -221,6 +225,10 @@ bool rend_single_frame() void* rend_thread(void* p) { +#if FEAT_HAS_NIXPROF + install_prof_handler(1); +#endif + #if SET_AFNT cpu_set_t mask; diff --git a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp index 71c197743..21c70e094 100755 --- a/core/linux-dist/main.cpp +++ b/core/linux-dist/main.cpp @@ -41,6 +41,9 @@ #include #endif +#if FEAT_HAS_NIXPROF +#include "profiler/profiler.h" +#endif int msgboxf(const wchar* text, unsigned int type, ...) { @@ -267,6 +270,9 @@ int main(int argc, wchar* argv[]) SetupInput(); #if !defined(TARGET_EMSCRIPTEN) + #if FEAT_HAS_NIXPROF + install_prof_handler(0); + #endif dc_run(); #else emscripten_set_main_loop(&dc_run, 100, false); diff --git a/core/linux-dist/x11.cpp b/core/linux-dist/x11.cpp index 9e629efa8..8981fea59 100644 --- a/core/linux-dist/x11.cpp +++ b/core/linux-dist/x11.cpp @@ -14,6 +14,10 @@ #include "linux-dist/x11.h" #include "linux-dist/main.h" +#if FEAT_HAS_NIXPROF +#include "profiler/profiler.h" +#endif + #if defined(TARGET_PANDORA) #define DEFAULT_FULLSCREEN 1 #define DEFAULT_WINDOW_WIDTH 800 @@ -72,6 +76,16 @@ void input_x11_handle() { die("death by escape key"); } +#if FEAT_HAS_NIXPROF + else if (e.type == KeyRelease && e.xkey.keycode == 76) // F10 button + { + if (sample_Switch(3000)) { + printf("Starting profiling\n"); + } else { + printf("Stopping profiling\n"); + } + } +#endif else if (e.type == KeyRelease && e.xkey.keycode == 95) // F11 button { x11_fullscreen = !x11_fullscreen; diff --git a/core/linux/nixprof/nixprof.cpp b/core/linux/nixprof/nixprof.cpp index 74eb4c283..517013e00 100644 --- a/core/linux/nixprof/nixprof.cpp +++ b/core/linux/nixprof/nixprof.cpp @@ -34,6 +34,7 @@ #include "hw/sh4/dyna/blockmanager.h" #include #include "deps/libelf/elf.h" +#include "profiler/profiler.h" #include "linux/context.h" @@ -202,7 +203,7 @@ static int str_ends_with(const char * str, const char * suffix) void sh4_jitsym(FILE* out); -static void* prof(void *ptr) +static void* profiler_main(void *ptr) { FILE* prof_out; char line[512]; @@ -265,11 +266,11 @@ static void* prof(void *ptr) do { tick_count++; - //printf("Sending SIGPROF %08X %08X\n",thread[0],thread[1]); + // printf("Sending SIGPROF %08X %08X\n",thread[0],thread[1]); for (int i = 0; i < 2; i++) pthread_kill(thread[i], SIGPROF); - //printf("Sent SIGPROF\n"); + // printf("Sent SIGPROF\n"); usleep(prof_wait); - //fwrite(&prof_address[0],1,sizeof(prof_address[0])*2,prof_out); + // fwrite(&prof_address[0],1,sizeof(prof_address[0])*2,prof_out); fprintf(prof_out, "%p %p\n", prof_address[0], prof_address[1]); if (!(tick_count % 10000)) @@ -285,12 +286,24 @@ static void* prof(void *ptr) return 0; } +bool sample_Switch(int freq) +{ + if (prof_run) { + sample_Stop(); + } else { + sample_Start(freq); + } + return prof_run; +} + void sample_Start(int freq) { + if (prof_run) + return; prof_wait = 1000000 / freq; printf("sampling profiler: starting %d hz %d wait\n", freq, prof_wait); prof_run = true; - pthread_create(&proft, NULL, prof, 0); + pthread_create(&proft, NULL, profiler_main, 0); } void sample_Stop() diff --git a/core/profiler/profiler.h b/core/profiler/profiler.h index cf825010b..eb5ead2fe 100644 --- a/core/profiler/profiler.h +++ b/core/profiler/profiler.h @@ -149,4 +149,5 @@ extern profiler_cfg prof; void install_prof_handler(int id); void sample_Start(int freq); void sample_Stop(); -void sample_Syms(u8* data,u32 len); \ No newline at end of file +bool sample_Switch(int freq); +void sample_Syms(u8* data,u32 len); From a34a4d6f387a42cb62a0b312c79358146b539bc1 Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Tue, 25 Aug 2015 01:25:50 +0200 Subject: [PATCH 3/7] libelf: get section link for ELF64 --- core/deps/libelf/elf.cpp | 2 +- core/deps/libelf/elf64.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/core/deps/libelf/elf.cpp b/core/deps/libelf/elf.cpp index e1bc8ca90..7f82bc91b 100644 --- a/core/deps/libelf/elf.cpp +++ b/core/deps/libelf/elf.cpp @@ -229,7 +229,7 @@ elf_getSectionLink(void *elfFile, int i) { return ISELF32 (elfFile) ? elf32_getSectionLink((Elf32_Header*)elfFile, i) - : 0; + : elf64_getSectionLink((Elf64_Header*)elfFile, i); } uint64_t diff --git a/core/deps/libelf/elf64.h b/core/deps/libelf/elf64.h index d839e3215..d9a745c08 100644 --- a/core/deps/libelf/elf64.h +++ b/core/deps/libelf/elf64.h @@ -165,6 +165,12 @@ elf64_getSectionType(struct Elf64_Header *file, uint16_t s) return elf64_getSectionTable(file)[s].sh_type; } +static inline +uint32_t elf64_getSectionLink(struct Elf64_Header *file, int s) +{ + return elf64_getSectionTable(file)[s].sh_link; +} + static inline uint32_t elf64_getSectionFlags(struct Elf64_Header *file, uint16_t s) { From c87307162dff396ab6c86adc92536508686b3935 Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Tue, 25 Aug 2015 01:27:36 +0200 Subject: [PATCH 4/7] nixprof: Use sh_type insteaf of sh_name for section identification and use SHT_SYMTAB --- core/linux/nixprof/nixprof.cpp | 44 +++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/core/linux/nixprof/nixprof.cpp b/core/linux/nixprof/nixprof.cpp index 517013e00..c5eb4e9c6 100644 --- a/core/linux/nixprof/nixprof.cpp +++ b/core/linux/nixprof/nixprof.cpp @@ -131,23 +131,33 @@ static void elf_syms(FILE* out,const char* libfile) int dynsym=-1; int dynstr=-1; + int strtab=-1; + int symtab=-1; - /* - Section: 2 -> .dynsym - Section: 3 -> .dynstr - */ if (elf_checkFile(data)>=0) { int scnt=elf_getNumSections(data); for (int si=0;si= 0 && strtab >= 0) + { + dynsym = symtab; + dynstr = strtab; + } + if (dynsym >= 0) { prof_head(out,"libsym",libfile); - // printf("Found dymsym %d, and dynstr %d!\n",dynsym,dynstr); + // printf("Found dymsym %d, and dynstr %d!\n",dynsym,dynstr); elf_symbol* sym=(elf_symbol*)elf_getSection(data,dynsym); int symcnt=elf_getSectionSize(data,dynsym)/sizeof(elf_symbol); @@ -168,7 +186,7 @@ static void elf_syms(FILE* out,const char* libfile) { char* name=(char*)elf_getSection(data,dynstr);// sym[i].st_shndx - // printf("Symbol %d: %s, %08X, %d bytes\n",i,name+sym[i].st_name,sym[i].st_value,sym[i].st_size); + // printf("Symbol %d: %s, %08X, %d bytes\n",i,name+sym[i].st_name,sym[i].st_value,sym[i].st_size); fprintf(out,"%08X %d %s\n",sym[i].st_value,sym[i].st_size,name+sym[i].st_name); } } @@ -182,8 +200,6 @@ static void elf_syms(FILE* out,const char* libfile) } } - - static volatile bool prof_run; // This is not used: From ceca8c72bfc921bdfc339ad82bcbb56affa10b2d Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Tue, 25 Aug 2015 01:49:09 +0200 Subject: [PATCH 5/7] nixprof: make it work with ELF64 --- core/deps/libelf/elf.h | 9 +++++++++ core/linux/nixprof/nixprof.cpp | 21 +++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/core/deps/libelf/elf.h b/core/deps/libelf/elf.h index 4b574234d..5c1e79256 100644 --- a/core/deps/libelf/elf.h +++ b/core/deps/libelf/elf.h @@ -116,6 +116,15 @@ struct elf_symbol { uint16_t st_shndx; // Section index }; +struct elf64_symbol { + uint32_t st_name; + unsigned char st_info; + unsigned char st_other; + uint16_t st_shndx; + uint64_t st_value; + uint64_t st_size; +}; + /* * constants for Elf32_Phdr.p_flags */ diff --git a/core/linux/nixprof/nixprof.cpp b/core/linux/nixprof/nixprof.cpp index c5eb4e9c6..7b2934a36 100644 --- a/core/linux/nixprof/nixprof.cpp +++ b/core/linux/nixprof/nixprof.cpp @@ -3,6 +3,7 @@ #if FEAT_HAS_NIXPROF #include "cfg/cfg.h" +#include #include #include @@ -178,16 +179,24 @@ static void elf_syms(FILE* out,const char* libfile) prof_head(out,"libsym",libfile); // printf("Found dymsym %d, and dynstr %d!\n",dynsym,dynstr); elf_symbol* sym=(elf_symbol*)elf_getSection(data,dynsym); - int symcnt=elf_getSectionSize(data,dynsym)/sizeof(elf_symbol); + elf64_symbol* sym64 = (elf64_symbol*) sym; - for (int i=0;ie_ident[EI_CLASS] == ELFCLASS32; + size_t symbol_size = elf32 ? sizeof(elf_symbol) : sizeof(elf64_symbol); + int symcnt = elf_getSectionSize(data,dynsym) / symbol_size; + + for (int i=0; i < symcnt; i++) { - if (sym[i].st_value && sym[i].st_name && sym[i].st_shndx) + uint64_t st_value = elf32 ? sym[i].st_value : sym64[i].st_value; + uint32_t st_name = elf32 ? sym[i].st_name : sym64[i].st_name; + uint16_t st_shndx = elf32 ? sym[i].st_shndx : sym64[i].st_shndx; + uint64_t st_size = elf32 ? sym[i].st_size : sym64[i].st_size; + if (st_value && st_name && st_shndx) { char* name=(char*)elf_getSection(data,dynstr);// sym[i].st_shndx - - // printf("Symbol %d: %s, %08X, %d bytes\n",i,name+sym[i].st_name,sym[i].st_value,sym[i].st_size); - fprintf(out,"%08X %d %s\n",sym[i].st_value,sym[i].st_size,name+sym[i].st_name); + // printf("Symbol %d: %s, %08" PRIx64 ", % " PRIi64 " bytes\n", + // i, name + st_name, st_value, st_size); + fprintf(out,"%08" PRIX64 "%" PRIi64 " %s\n", st_value, st_size, name + st_name); } } } From 8fc2d5d0690a48c20e743572deba3413e106dd5e Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Tue, 25 Aug 2015 01:56:04 +0200 Subject: [PATCH 6/7] nixprof: only save STT_FUNC --- core/deps/libelf/elf.h | 3 +++ core/linux/nixprof/nixprof.cpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/deps/libelf/elf.h b/core/deps/libelf/elf.h index 5c1e79256..3c56c3b12 100644 --- a/core/deps/libelf/elf.h +++ b/core/deps/libelf/elf.h @@ -176,6 +176,9 @@ struct elf64_symbol { #define ELF_PRINT_SECTIONS 2 #define ELF_PRINT_ALL (ELF_PRINT_PROGRAM_HEADERS | ELF_PRINT_SECTIONS) +/* Symbol types */ +#define STT_FUNC 2 /* Function, code */ + /** * Checks that elfFile points to a valid elf file. * diff --git a/core/linux/nixprof/nixprof.cpp b/core/linux/nixprof/nixprof.cpp index 7b2934a36..166a77d07 100644 --- a/core/linux/nixprof/nixprof.cpp +++ b/core/linux/nixprof/nixprof.cpp @@ -190,8 +190,9 @@ static void elf_syms(FILE* out,const char* libfile) uint64_t st_value = elf32 ? sym[i].st_value : sym64[i].st_value; uint32_t st_name = elf32 ? sym[i].st_name : sym64[i].st_name; uint16_t st_shndx = elf32 ? sym[i].st_shndx : sym64[i].st_shndx; + uint16_t st_type = (elf32 ? sym[i].st_info : sym64[i].st_info) & 0xf; uint64_t st_size = elf32 ? sym[i].st_size : sym64[i].st_size; - if (st_value && st_name && st_shndx) + if (st_type == STT_FUNC && st_value && st_name && st_shndx) { char* name=(char*)elf_getSection(data,dynstr);// sym[i].st_shndx // printf("Symbol %d: %s, %08" PRIx64 ", % " PRIi64 " bytes\n", From 2a469b1def2f51f06d60a93d7f2fd88997d99d6f Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Wed, 26 Aug 2015 13:30:26 +0200 Subject: [PATCH 7/7] nixprof: fix notation for Hz --- core/linux/nixprof/nixprof.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/linux/nixprof/nixprof.cpp b/core/linux/nixprof/nixprof.cpp index 166a77d07..5ce5c88d4 100644 --- a/core/linux/nixprof/nixprof.cpp +++ b/core/linux/nixprof/nixprof.cpp @@ -327,7 +327,7 @@ void sample_Start(int freq) if (prof_run) return; prof_wait = 1000000 / freq; - printf("sampling profiler: starting %d hz %d wait\n", freq, prof_wait); + printf("sampling profiler: starting %d Hz %d wait\n", freq, prof_wait); prof_run = true; pthread_create(&proft, NULL, profiler_main, 0); }