| #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"); |
| fo = fopen("gmon.out", "w+"); |
| |
| if ((f == NULL) || (fo == NULL)) { |
| fprintf(stderr, "Unable to manipulate with the input file\n"); |
| 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); |
| return 0; |
| } |