static void* profiler_main(void *ptr) { FILE* prof_out; char line[512]; sprintf(line, "/%d.reprof", tick_count); string logfile=get_writable_data_path(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<string> 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<string>::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"); #if FEAT_SHREC != DYNAREC_NONE sh4_jitsym(prof_out); #endif //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); return 0; }
static 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; int strtab=-1; int symtab=-1; if (elf_checkFile(data)>=0) { int scnt=elf_getNumSections(data); for (int si=0;si<scnt;si++) { uint32_t section_type = elf_getSectionType(data, si); uint64_t section_link = elf_getSectionLink(data, si); switch (section_type) { case SHT_DYNSYM: fprintf(stderr, "DYNSYM"); dynsym = si; if (section_link < scnt) dynstr = section_link; break; case SHT_SYMTAB: fprintf(stderr, "SYMTAB"); symtab = si; if (section_link < scnt) strtab = section_link; break; default: break;; } } } else { printf("Invalid elf file\n"); } // Use SHT_SYMTAB if available insteaf of SHT_DYNSYM // (there is more info here): if (symtab >= 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); elf_symbol* sym=(elf_symbol*)elf_getSection(data,dynsym); elf64_symbol* sym64 = (elf64_symbol*) sym; bool elf32 = ((struct Elf32_Header*)data)->e_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++) { 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, %08" PRIx64 ", % " PRIi64 " bytes\n", // i, name + st_name, st_value, st_size); //PRIx64 & friends not in android ndk (yet?) fprintf(out,"%08x %d %s\n", (int)st_value, (int)st_size, name + st_name); } } } else { printf("No dynsym\n"); } munmap(data,statbuf.st_size); } }
static int do_profile( caddr_t start, unsigned long plength, unsigned scale, int thresh, int bucket, unsigned int mask ) { int i, retval; unsigned long blength; int num_buckets,j=0; int num_bufs = num_events; int event = num_events; int events[MAX_TEST_EVENTS]; char header[BUFSIZ]; strncpy(header,"address\t\t",BUFSIZ); //= "address\t\t\tcyc\tins\tfp_ins\n"; for(i=0;i<MAX_TEST_EVENTS;i++) { if (mask & test_events[i].mask) { events[j]=test_events[i].event; if (events[j]==PAPI_TOT_CYC) { strncat(header,"\tcyc",BUFSIZ-1); } if (events[j]==PAPI_TOT_INS) { strncat(header,"\tins",BUFSIZ-1); } if (events[j]==PAPI_FP_INS) { strncat(header,"\tfp_ins",BUFSIZ-1); } if (events[j]==PAPI_FP_OPS) { strncat(header,"\tfp_ops",BUFSIZ-1); } if (events[j]==PAPI_L2_TCM) { strncat(header,"\tl2_tcm",BUFSIZ-1); } j++; } } strncat(header,"\n",BUFSIZ-1); blength = prof_size( plength, scale, bucket, &num_buckets ); prof_alloc( num_bufs, blength ); if ( !TESTS_QUIET ) printf( "Overall event counts:\n" ); for ( i = 0; i < num_events; i++ ) { if ( ( retval = PAPI_profil( profbuf[i], ( unsigned int ) blength, start, scale, EventSet, events[i], thresh, PAPI_PROFIL_POSIX | bucket ) ) != PAPI_OK ) { if (retval == PAPI_EINVAL) { test_warn( __FILE__, __LINE__, "Trying to profile with derived event", 1); num_events=i; break; } else { printf("Failed with event %d 0x%x\n",i,events[i]); test_fail( __FILE__, __LINE__, "PAPI_profil", retval ); } } } if ( ( retval = PAPI_start( EventSet ) ) != PAPI_OK ) test_fail( __FILE__, __LINE__, "PAPI_start", retval ); my_main( ); if ( ( retval = PAPI_stop( EventSet, values[0] ) ) != PAPI_OK ) test_fail( __FILE__, __LINE__, "PAPI_stop", retval ); if ( !TESTS_QUIET ) { printf( TAB1, "PAPI_TOT_CYC:", ( values[0] )[--event] ); if ( strcmp( hw_info->model_string, "POWER6" ) != 0 ) { printf( TAB1, "PAPI_TOT_INS:", ( values[0] )[--event] ); } #if defined(__powerpc__) printf( TAB1, "PAPI_FP_INS", ( values[0] )[--event] ); #else if ( strcmp( hw_info->model_string, "Intel Pentium III" ) != 0 ) { printf( TAB1, "PAPI_FP_OPS:", ( values[0] )[--event] ); printf( TAB1, "PAPI_L2_TCM:", ( values[0] )[--event] ); } #endif } for ( i = 0; i < num_events; i++ ) { if ( ( retval = PAPI_profil( profbuf[i], ( unsigned int ) blength, start, scale, EventSet, events[i], 0, PAPI_PROFIL_POSIX ) ) != PAPI_OK ) test_fail( __FILE__, __LINE__, "PAPI_profil", retval ); } prof_head( blength, bucket, num_buckets, header ); prof_out( start, num_events, bucket, num_buckets, scale ); retval = prof_check( num_bufs, bucket, num_buckets ); for ( i = 0; i < num_bufs; i++ ) { free( profbuf[i] ); } return retval; }
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<scnt;si++) { if (strcmp(".dynsym",elf_getSectionName(data,si))==0) dynsym=si; if (strcmp(".dynstr",elf_getSectionName(data,si))==0) dynstr=si; } } else { printf("Invalid elf file\n"); } if (dynsym >= 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<symcnt;i++) { if (sym[i].st_value && sym[i].st_name && sym[i].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); } } } else { printf("No dynsym\n"); } munmap(data,statbuf.st_size); } }
static int do_profile(caddr_t start, unsigned long plength, unsigned scale, int thresh, int bucket) { int i, retval; unsigned long blength; int num_buckets; char *profstr[5] = {"PAPI_PROFIL_POSIX", "PAPI_PROFIL_RANDOM", "PAPI_PROFIL_WEIGHTED", "PAPI_PROFIL_COMPRESS", "PAPI_PROFIL_<all>" }; int profflags[5] = {PAPI_PROFIL_POSIX, PAPI_PROFIL_POSIX | PAPI_PROFIL_RANDOM, PAPI_PROFIL_POSIX | PAPI_PROFIL_WEIGHTED, PAPI_PROFIL_POSIX | PAPI_PROFIL_COMPRESS, PAPI_PROFIL_POSIX | PAPI_PROFIL_WEIGHTED | PAPI_PROFIL_RANDOM | PAPI_PROFIL_COMPRESS }; do_no_profile(); blength = prof_size(plength, scale, bucket, &num_buckets); prof_alloc(5, blength); for (i=0;i<5;i++) { if (!TESTS_QUIET) printf("Test type : \t%s\n", profstr[i]); #ifndef SWPROFILE if ((retval = PAPI_profil(profbuf[i], blength, start, scale, EventSet, PAPI_event, thresh, profflags[i] | bucket)) != PAPI_OK) { test_fail(__FILE__, __LINE__, "PAPI_profil", retval); } #else if ((retval = PAPI_profil(profbuf[i], blength, start, scale, EventSet, PAPI_event, thresh, profflags[i] | bucket | PAPI_PROFIL_FORCE_SW)) != PAPI_OK) { test_fail(__FILE__, __LINE__, "PAPI_profil", retval); } #endif if ((retval = PAPI_start(EventSet)) != PAPI_OK) test_fail(__FILE__, __LINE__, "PAPI_start", retval); do_flops(getenv("NUM_FLOPS") ? atoi(getenv("NUM_FLOPS")) : NUM_FLOPS); if ((retval = PAPI_stop(EventSet, values[1])) != PAPI_OK) test_fail(__FILE__, __LINE__, "PAPI_stop", retval); if (!TESTS_QUIET) { printf(TAB1, event_name, (values[1])[0]); printf(TAB1, "PAPI_TOT_CYC", (values[1])[1]); } if ((retval = PAPI_profil(profbuf[i], blength, start, scale, EventSet, PAPI_event, 0, profflags[i])) != PAPI_OK) test_fail(__FILE__, __LINE__, "PAPI_profil", retval); } prof_head(blength, bucket, num_buckets, "address\t\t\tflat\trandom\tweight\tcomprs\tall\n"); prof_out(start, 5, bucket, num_buckets, scale); retval = prof_check(5, bucket, num_buckets); for (i=0;i<5;i++) { free(profbuf[i]); } return(retval); }