#include "types.h" #include "cfg/cfg.h" #include #include #include #include #include #include #include #include #include #include //#include #include #include //#include #include #include #include #include //#include #include #include #include #include #include #include #include #include "hw/sh4/dyna/blockmanager.h" #include #include "deps/libelf/elf.h" #if defined(_ANDROID) #include typedef struct ucontext_t { unsigned long uc_flags; struct ucontext_t *uc_link; struct { void *p; int flags; size_t size; } sstack_data; struct sigcontext uc_mcontext; /* some 2.6.x kernel has fp data here after a few other fields * we don't use them for now... */ } ucontext_t; #include #endif #if HOST_CPU == CPU_ARM #define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.arm_pc) #else #define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.pc) #endif /** @file CallStack_Android.h @brief Getting the callstack under Android @author Peter Holtwick */ #include #include #include int tick_count=0; pthread_t proft; pthread_t thread[2]; void* prof_address[2]; u32 prof_wait; u8* syms_ptr; int syms_len; void sample_Syms(u8* data,u32 len) { syms_ptr=data; syms_len=len; } void prof_handler (int sn, siginfo_t * si, void *ctxr) { ucontext_t* ctx=(ucontext_t*)ctxr; int thd=-1; if (pthread_self()==thread[0]) thd=0; else if (pthread_self()==thread[1]) thd=1; else return; prof_address[thd]=(void*)GET_PC_FROM_CONTEXT(ctx); } void install_prof_handler(int id) { struct sigaction act, segv_oact; memset(&act, 0, sizeof(act)); act.sa_sigaction = prof_handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO | SA_RESTART; sigaction(SIGPROF, &act, &segv_oact); thread[id]=pthread_self(); } 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) { fprintf(out,"==xx==xx==\n%s:%d\n",type,d); } void elf_syms(FILE* out,const char* libfile) { struct stat statbuf; printf("LIBFILE \"%s\"\n", libfile); int fd = open(libfile, O_RDONLY, 0); if (!fd) { printf("Failed to open file \"%s\"\n", libfile); return; } if (fstat(fd, &statbuf) < 0) { printf("Failed to fstat file \"%s\"\n", libfile); return; } { void* data = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); close(fd); if (data == (void*)-1) { printf("Failed to mmap file \"%s\"\n", libfile); return; } //printf("MMap: %08p, %08X\n",data,statbuf.st_size); int dynsym=-1; int dynstr=-1; /* Section: 2 -> .dynsym Section: 3 -> .dynstr */ if (elf_checkFile(data)>=0) { int scnt=elf_getNumSections(data); for (int si=0;si= 0) { 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); for (int i=0;i str_len) return 0; return 0 == strncmp(str + str_len - suffix_len, suffix, suffix_len); } void sh4_jitsym(FILE* out); void* prof(void *ptr) { FILE* prof_out; char line[512]; sprintf(line, "/%d.reprof", tick_count); string logfile=GetPath(line); printf("Profiler thread logging to -> %s\n", logfile.c_str()); prof_out = fopen(logfile.c_str(), "wb"); if (!prof_out) { printf("Failed to open profiler file\n"); return 0; } set libs; prof_head(prof_out, "vaddr", ""); FILE* maps = fopen("/proc/self/maps", "r"); while (!feof(maps)) { fgets(line, 512, maps); fputs(line, prof_out); if (strstr(line, ".so")) { char file[512]; file[0] = 0; sscanf(line, "%*x-%*x %*s %*x %*x:%*x %*d %s\n", file); if (strlen(file)) libs.insert(file); } } //Write map file prof_head(prof_out, ".map", ""); fwrite(syms_ptr, 1, syms_len, prof_out); //write exports from .so's for (set::iterator it = libs.begin(); it != libs.end(); it++) { elf_syms(prof_out, it->c_str()); } //Write shrec syms file ! prof_head(prof_out, "jitsym", "SH4"); sh4_jitsym(prof_out); //Write arm7rec syms file ! -> to do //prof_head(prof_out,"jitsym","ARM7"); prof_head(prof_out, "samples", prof_wait); do { tick_count++; //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"); usleep(prof_wait); //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)) { printf("Profiler: %d ticks, flusing ..\n", tick_count); fflush(prof_out); } } while (prof_run); fclose(maps); fclose(prof_out); } void sample_Start(int freq) { 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); } void sample_Stop() { if (prof_run) { prof_run = false; pthread_join(proft, NULL); } printf("sampling profiler: stopped\n"); }