Ehh.. I have a hacked up version of a kprof that was originally written
by ramon@ie3.clubs.etsit.upm.es, but I changed it around quite a bit.
This version shows percent time used etc, and sorts the list in
ascending order.
Hmm.. I haven't used this in a while. Does it still work? The code
isn't pretty, but it's short. Somebody should probably clean it up some
more..
Linus
---------- kprof.c ----------
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <linux/autoconf.h>
#define BUFSIZE 1024
struct entry {
struct entry * next;
unsigned long time;
unsigned long address;
char name[1];
};
struct entry * list = NULL;
void do_symbol(int time, unsigned long address, char * name)
{
struct entry * entry = malloc(sizeof(struct entry) + strlen(name));
struct entry ** tmp;
entry->time = time;
entry->address = address;
strcpy(entry->name, name + (*name == '_'));
tmp = &list;
while (*tmp) {
if ((*tmp)->time > entry->time)
break;
tmp = &(*tmp)->next;
}
entry->next = *tmp;
*tmp = entry;
}
void show_symbols(unsigned long total)
{
struct entry * entry = list;
while (entry) {
printf("%10u %5d.%02d%% %08x %s\n" ,
entry->time,
(entry->time*10000/total) / 100,
(entry->time*10000/total) % 100,
entry->address, entry->name);
entry = entry->next;
}
}
int main(void)
{
int fp;
FILE *kmap;
int current_symbol_value , next_symbol_value;
char current_symbol[80] , next_symbol[80];
int has_read , total = 0, j;
fp = open("/proc/profile", O_RDONLY);
if (fp < 0) {
perror("/proc/profile");
exit(1);
}
kmap = fopen("/System.map","r");
if (!kmap) {
kmap = fopen("/usr/src/linux/System.map","r");
if (!kmap) {
perror("System.map");
exit(1);
}
}
fscanf(kmap , "%x %*s %s\n" , ¤t_symbol_value , current_symbol );
fscanf(kmap , "%x %*s %s\n" , &next_symbol_value , next_symbol );
lseek (fp , sizeof(unsigned int) , SEEK_SET);
/* For old kernels.. */
/* lseek (fp , (current_symbol_value-1)*sizeof(unsigned int) >> CONFIG_PROFILE_SHIFT , SEEK_CUR); */
for (;;) {
unsigned int buffer[(next_symbol_value - current_symbol_value) >> CONFIG_PROFILE_SHIFT];
unsigned int this_time = 0;
if (next_symbol_value == current_symbol_value) {
strcpy(current_symbol, next_symbol);
fscanf(kmap, "%x %*s %s\n", &next_symbol_value, next_symbol);
continue;
}
has_read = read (fp , buffer , sizeof(buffer) );
for ( j = 0 ; j < has_read/sizeof(unsigned int) ; j++)
this_time += buffer[j];
if (this_time != 0) {
do_symbol(this_time, current_symbol_value, current_symbol);
total += this_time;
}
if (has_read < (next_symbol_value -current_symbol_value)
>> CONFIG_PROFILE_SHIFT * sizeof(unsigned long) ||
next_symbol_value == current_symbol_value )
break;
strcpy ( current_symbol , next_symbol );
current_symbol_value = next_symbol_value;
fscanf(kmap , "%x %*s %s\n" , &next_symbol_value , next_symbol );
}
do_symbol(total, 0, "total");
show_symbols(total);
return(0);
}
----------