115 lines
2.3 KiB
C
115 lines
2.3 KiB
C
|
#include <stdio.h>
|
||
|
#include <uthash.h>
|
||
|
#include <sys/gmon_out.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#define GMON_SEC "seconds s"
|
||
|
uint32_t mineip = 0xffffffff;
|
||
|
uint32_t maxeip = 0;
|
||
|
|
||
|
/* a hash structure to hold the arc */
|
||
|
struct arec {
|
||
|
uint32_t eip;
|
||
|
uint32_t from;
|
||
|
uint32_t count;
|
||
|
UT_hash_handle hh;
|
||
|
};
|
||
|
|
||
|
struct arec *arc = NULL;
|
||
|
|
||
|
void note_arc(uint32_t eip, uint32_t from)
|
||
|
{
|
||
|
struct arec *s;
|
||
|
|
||
|
HASH_FIND_INT(arc, &eip, s);
|
||
|
if (s == NULL) {
|
||
|
s = malloc(sizeof(struct arec));
|
||
|
s->eip = eip;
|
||
|
s->from = from;
|
||
|
s->count = 1;
|
||
|
if (eip > maxeip)
|
||
|
maxeip = eip;
|
||
|
if (eip < mineip)
|
||
|
maxeip = eip;
|
||
|
|
||
|
HASH_ADD_INT(arc, eip, s);
|
||
|
} else {
|
||
|
s->count++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int main(int argc, char* argv[])
|
||
|
{
|
||
|
FILE *f, *fo;
|
||
|
struct arec *s;
|
||
|
uint32_t eip, from, tmp;
|
||
|
uint8_t tag;
|
||
|
uint16_t hit;
|
||
|
|
||
|
if (argc != 2) {
|
||
|
fprintf(stderr, "Please specify the coreboot trace log as parameter\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
f = fopen(argv[1], "r");
|
||
|
if (f == NULL) {
|
||
|
perror("Unable to open the input file");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
fo = fopen("gmon.out", "w+");
|
||
|
if (fo == NULL) {
|
||
|
perror("Unable to open the output file");
|
||
|
fclose(f);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
while (!feof(f)) {
|
||
|
if (fscanf(f, "~%x(%x)%*[^\n]\n", &eip, &from) == 2) {
|
||
|
note_arc(eip, from);
|
||
|
} else if (fscanf(f, "%*c~%x(%x)%*[^\n]\n", &eip, &from) == 2) {
|
||
|
note_arc(eip, from);
|
||
|
} else {
|
||
|
/* just drop a line */
|
||
|
tmp = fscanf(f, "%*[^\n]\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* write gprof header */
|
||
|
fwrite(GMON_MAGIC, 1, sizeof(GMON_MAGIC) - 1, fo);
|
||
|
tmp = GMON_VERSION;
|
||
|
fwrite(&tmp, 1, sizeof(tmp), fo);
|
||
|
tmp = 0;
|
||
|
fwrite(&tmp, 1, sizeof(tmp), fo);
|
||
|
fwrite(&tmp, 1, sizeof(tmp), fo);
|
||
|
fwrite(&tmp, 1, sizeof(tmp), fo);
|
||
|
/* write fake histogram */
|
||
|
tag = GMON_TAG_TIME_HIST;
|
||
|
fwrite(&tag, 1, sizeof(tag), fo);
|
||
|
fwrite(&mineip, 1, sizeof(mineip), fo);
|
||
|
fwrite(&maxeip, 1, sizeof(maxeip), fo);
|
||
|
/* size of histogram */
|
||
|
tmp = 1;
|
||
|
fwrite(&tmp, 1, sizeof(tmp), fo);
|
||
|
/* prof rate */
|
||
|
tmp = 1000;
|
||
|
fwrite(&tmp, 1, sizeof(tmp), fo);
|
||
|
fwrite(GMON_SEC, 1, sizeof(GMON_SEC) - 1, fo);
|
||
|
hit = 1;
|
||
|
fwrite(&hit, 1, sizeof(hit), fo);
|
||
|
|
||
|
/* write call graph data */
|
||
|
tag = GMON_TAG_CG_ARC;
|
||
|
for (s = arc; s != NULL; s = s->hh.next) {
|
||
|
fwrite(&tag, 1, sizeof(tag), fo);
|
||
|
fwrite(&s->from, 1, sizeof(s->from), fo);
|
||
|
fwrite(&s->eip, 1, sizeof(s->eip), fo);
|
||
|
fwrite(&s->count, 1, sizeof(s->count), fo);
|
||
|
}
|
||
|
|
||
|
fclose(fo);
|
||
|
fclose(f);
|
||
|
|
||
|
return 0;
|
||
|
}
|