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/elf.h b/core/deps/libelf/elf.h index 4b574234d..3c56c3b12 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 */ @@ -167,6 +176,9 @@ struct elf_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/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) { 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 96200985b..bb4886fac 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, ...) { @@ -409,6 +412,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 d1609381f..515515d93 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 @@ -34,6 +35,7 @@ #include "hw/sh4/dyna/blockmanager.h" #include #include "deps/libelf/elf.h" +#include "profiler/profiler.h" #include "linux/context.h" @@ -46,14 +48,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 +90,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; @@ -129,23 +132,33 @@ 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); + 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; + 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_type == STT_FUNC && 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); } } } @@ -180,11 +210,10 @@ void elf_syms(FILE* out,const char* libfile) } } +static volatile bool prof_run; - -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 +229,7 @@ int str_ends_with(const char * str, const char * suffix) void sh4_jitsym(FILE* out); -void* prof(void *ptr) +static void* profiler_main(void *ptr) { FILE* prof_out; char line[512]; @@ -263,11 +292,11 @@ 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)) @@ -283,12 +312,24 @@ 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); + 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() @@ -300,4 +341,4 @@ void sample_Stop() } printf("sampling profiler: stopped\n"); } -#endif \ No newline at end of file +#endif 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);