Compare commits
No commits in common. "a2cc7e8b0303d1a1c423994f477d5c9d181dd837" and "41a7eccad30dd7609751bff3ebc061d3db4516c2" have entirely different histories.
a2cc7e8b03
...
41a7eccad3
|
@ -1,23 +1,5 @@
|
||||||
#include "rvprof_internal.h"
|
#include "rvprof_internal.h"
|
||||||
|
|
||||||
// initialize with basic defaults - environment variables will override these
|
|
||||||
rvprof_context_t g_rvprof = {
|
|
||||||
.config = {
|
|
||||||
.enable_hooks = 1, // Default: enable hooks
|
|
||||||
.merge_regions = 1, // Default: merge regions
|
|
||||||
.output_filename = NULL, // Auto-generate
|
|
||||||
.program_name = NULL // Auto-detect
|
|
||||||
},
|
|
||||||
.use_cycles = 1, // Try cycle counter first
|
|
||||||
.stack_ptr = -1, // No active regions
|
|
||||||
.initialized = 0, // Not initialized
|
|
||||||
.auto_initialized = 0, // Not auto-initialized
|
|
||||||
.symbols_loaded = 0, // No symbols loaded
|
|
||||||
.total_program_time = 0,
|
|
||||||
.total_program_cycles = 0,
|
|
||||||
.total_memory_allocated = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
void rvprof_context_cleanup(void){
|
void rvprof_context_cleanup(void){
|
||||||
if (!g_rvprof.initialized) {
|
if (!g_rvprof.initialized) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -179,6 +179,11 @@ char* rvprof_utils_get_program_name(void);
|
||||||
char* rvprof_utils_generate_output_filename(void);
|
char* rvprof_utils_generate_output_filename(void);
|
||||||
int rvprof_utils_is_main_function(const char* func_name);
|
int rvprof_utils_is_main_function(const char* func_name);
|
||||||
|
|
||||||
|
// function stats
|
||||||
|
int rvprof_stats_find_or_create_function(const char* name, const char* caller);
|
||||||
|
int rvprof_stats_get_or_create_stack_id(void);
|
||||||
|
void rvprof_stats_add_stack_id_to_function(int func_id, int stack_id);
|
||||||
|
void rvprof_stats_add_caller_to_function(int func_id, const char* caller);
|
||||||
|
|
||||||
// context management
|
// context management
|
||||||
void rvprof_context_cleanup(void);
|
void rvprof_context_cleanup(void);
|
||||||
|
|
|
@ -71,16 +71,3 @@ int rvprof_stats_get_or_create_stack_id(void) {
|
||||||
|
|
||||||
return stack_id;
|
return stack_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// function metadata
|
|
||||||
void rvprof_stats_add_stack_id_to_function(int func_id, int stack_id) {
|
|
||||||
if (rvprof_memory_add_stack_id_to_function(func_id, stack_id) != RVPROF_SUCCESS) {
|
|
||||||
fprintf(stderr, "rvprof: Failed to add stack ID to function\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void rvprof_stats_add_caller_to_function(int func_id, const char* caller) {
|
|
||||||
if (rvprof_memory_add_caller_to_function(func_id, caller) != RVPROF_SUCCESS) {
|
|
||||||
fprintf(stderr, "rvprof: Failed to add caller to function\n");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,7 +12,8 @@ __thread char g_tmp_func_name[128];
|
||||||
static uintptr_t g_base_address_offset = 0;
|
static uintptr_t g_base_address_offset = 0;
|
||||||
static int g_base_address_calculated = 0;
|
static int g_base_address_calculated = 0;
|
||||||
|
|
||||||
// base address calculation
|
|
||||||
|
// base address calculatiion
|
||||||
static void calculate_base_address_offset(void* known_runtime_addr, uintptr_t known_elf_addr){
|
static void calculate_base_address_offset(void* known_runtime_addr, uintptr_t known_elf_addr){
|
||||||
if (g_base_address_calculated) return;
|
if (g_base_address_calculated) return;
|
||||||
|
|
||||||
|
@ -52,11 +53,6 @@ static int add_symbol(uintptr_t addr, const char* name, size_t size){
|
||||||
// skip versioned symbols
|
// skip versioned symbols
|
||||||
if (strstr(name, "@") != NULL) return 0;
|
if (strstr(name, "@") != NULL) return 0;
|
||||||
|
|
||||||
// ensure capacity before accessing array
|
|
||||||
if (symbol_array_ensure_capacity(&g_rvprof.symbols, g_rvprof.symbols.size) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add interesting symbols
|
// add interesting symbols
|
||||||
size_t name_len = strlen(name);
|
size_t name_len = strlen(name);
|
||||||
char* tmp_name = rvprof_malloc(name_len+1);
|
char* tmp_name = rvprof_malloc(name_len+1);
|
||||||
|
@ -74,7 +70,7 @@ static int add_symbol(uintptr_t addr, const char* name, size_t size){
|
||||||
// ELF symbol parsing
|
// ELF symbol parsing
|
||||||
static int parse_elf_symbols(const char* filepath){
|
static int parse_elf_symbols(const char* filepath){
|
||||||
int fp = open(filepath, O_RDONLY);
|
int fp = open(filepath, O_RDONLY);
|
||||||
if (fp < 0) return -1;
|
if (fp< 0) return -1;
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (fstat(fp, &st) < 0){
|
if (fstat(fp, &st) < 0){
|
||||||
|
@ -82,7 +78,7 @@ static int parse_elf_symbols(const char* filepath){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sanity check: file size, max for executables defined here: 1 GiB
|
// sanity check: file size, max fort executables defined here: 1 GiB
|
||||||
if (st.st_size < (off_t)sizeof(Elf64_Ehdr) || st.st_size > 1024*1024*1024){
|
if (st.st_size < (off_t)sizeof(Elf64_Ehdr) || st.st_size > 1024*1024*1024){
|
||||||
close(fp);
|
close(fp);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -91,11 +87,7 @@ static int parse_elf_symbols(const char* filepath){
|
||||||
void* mapped = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fp, 0);
|
void* mapped = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fp, 0);
|
||||||
close(fp);
|
close(fp);
|
||||||
|
|
||||||
if (mapped == MAP_FAILED) {
|
// check ELF magic with bounds checkuing
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check ELF magic with bounds checking
|
|
||||||
if (st.st_size < 16){
|
if (st.st_size < 16){
|
||||||
munmap(mapped, st.st_size);
|
munmap(mapped, st.st_size);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -168,6 +160,7 @@ static int parse_elf_symbols(const char* filepath){
|
||||||
|
|
||||||
add_symbol(sym->st_value, name, sym->st_size);
|
add_symbol(sym->st_value, name, sym->st_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,9 +330,6 @@ const char* rvprof_symbols_lookup(void* addr){
|
||||||
|
|
||||||
// public API
|
// public API
|
||||||
rvprof_error_t rvprof_symbols_init(const char* program_path){
|
rvprof_error_t rvprof_symbols_init(const char* program_path){
|
||||||
// initialize symbols array first
|
|
||||||
memset(&g_rvprof.symbols, 0, sizeof(g_rvprof.symbols));
|
|
||||||
|
|
||||||
// option 1: provided path
|
// option 1: provided path
|
||||||
if (program_path && parse_elf_symbols(program_path) == 0){
|
if (program_path && parse_elf_symbols(program_path) == 0){
|
||||||
return RVPROF_SUCCESS;
|
return RVPROF_SUCCESS;
|
||||||
|
|
|
@ -11,14 +11,11 @@ Maybe replace with a library call in the future
|
||||||
// global flag for cycle counter availability
|
// global flag for cycle counter availability
|
||||||
static volatile int g_cycle_counter_available = 0;
|
static volatile int g_cycle_counter_available = 0;
|
||||||
static volatile jmp_buf g_cycle_test_jmpbuf;
|
static volatile jmp_buf g_cycle_test_jmpbuf;
|
||||||
static volatile int g_signal_handler_active = 0;
|
|
||||||
|
|
||||||
// signal handler for illegal instructions
|
// signal handler for illegal instructions
|
||||||
static void sigill_handler(int sig){
|
static void sigkill_handler(int sig){
|
||||||
if (g_signal_handler_active) {
|
g_cycle_counter_available = 0;
|
||||||
g_cycle_counter_available = 0;
|
longjmp(g_cycle_test_jmpbuf, 1);
|
||||||
longjmp(g_cycle_test_jmpbuf, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t read_cycles(void){
|
static inline uint64_t read_cycles(void){
|
||||||
|
@ -27,6 +24,8 @@ static inline uint64_t read_cycles(void){
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t cycles;
|
uint64_t cycles;
|
||||||
|
|
||||||
|
|
||||||
__asm__ volatile("csrr %0, cycle" : "=r"(cycles));
|
__asm__ volatile("csrr %0, cycle" : "=r"(cycles));
|
||||||
return cycles;
|
return cycles;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +40,7 @@ static inline uint64_t read_time_ns(void){
|
||||||
int rvprof_timing_test_cycle_counter(void){
|
int rvprof_timing_test_cycle_counter(void){
|
||||||
// set up signal handler for illegal instruction
|
// set up signal handler for illegal instruction
|
||||||
struct sigaction old_action, new_action;
|
struct sigaction old_action, new_action;
|
||||||
new_action.sa_handler = sigill_handler;
|
new_action.sa_handler = sigkill_handler;
|
||||||
sigemptyset(&new_action.sa_mask);
|
sigemptyset(&new_action.sa_mask);
|
||||||
new_action.sa_flags = 0;
|
new_action.sa_flags = 0;
|
||||||
|
|
||||||
|
@ -51,10 +50,6 @@ int rvprof_timing_test_cycle_counter(void){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize state
|
|
||||||
g_cycle_counter_available = 0;
|
|
||||||
g_signal_handler_active = 1;
|
|
||||||
|
|
||||||
// test cycle counter access
|
// test cycle counter access
|
||||||
if (setjmp(g_cycle_test_jmpbuf) == 0) {
|
if (setjmp(g_cycle_test_jmpbuf) == 0) {
|
||||||
uint64_t cycles1, cycles2;
|
uint64_t cycles1, cycles2;
|
||||||
|
@ -71,13 +66,11 @@ int rvprof_timing_test_cycle_counter(void){
|
||||||
} else {
|
} else {
|
||||||
g_cycle_counter_available = 0;
|
g_cycle_counter_available = 0;
|
||||||
}
|
}
|
||||||
} else {
|
}else{
|
||||||
// illegal instruction occurred - handler already set g_cycle_counter_available = 0
|
// illegal instruction occurred
|
||||||
|
g_cycle_counter_available = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable signal handler before restoring
|
|
||||||
g_signal_handler_active = 0;
|
|
||||||
|
|
||||||
// restore original signal handler
|
// restore original signal handler
|
||||||
sigaction(SIGILL, &old_action, NULL);
|
sigaction(SIGILL, &old_action, NULL);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue