Merge pull request #807 from randomstuff/nixprof

Nixprof: some enchancements
This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis 2015-09-04 19:55:19 +02:00
commit 56f8ffac0e
8 changed files with 128 additions and 40 deletions

View File

@ -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

View File

@ -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.
*

View File

@ -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)
{

View File

@ -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;

View File

@ -41,6 +41,9 @@
#include <sys/soundcard.h>
#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);

View File

@ -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;

View File

@ -3,6 +3,7 @@
#if FEAT_HAS_NIXPROF
#include "cfg/cfg.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
@ -34,6 +35,7 @@
#include "hw/sh4/dyna/blockmanager.h"
#include <set>
#include "deps/libelf/elf.h"
#include "profiler/profiler.h"
#include "linux/context.h"
@ -46,14 +48,14 @@
#include <stdio.h>
#include <string.h>
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<scnt;si++)
{
if (strcmp(".dynsym",elf_getSectionName(data,si))==0)
dynsym=si;
if (strcmp(".dynstr",elf_getSectionName(data,si))==0)
dynstr=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
@ -153,21 +166,38 @@ void elf_syms(FILE* out,const char* libfile)
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);
// 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;i<symcnt;i++)
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++)
{
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
#endif

View File

@ -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);
bool sample_Switch(int freq);
void sample_Syms(u8* data,u32 len);