Add support utils for tracing
[coreboot.git] / util / genprof / genprof.c
1 #include <stdio.h>
2 #include <uthash.h>
3 #include <sys/gmon_out.h>
4 #include <stdlib.h>
5
6 #define GMON_SEC "seconds        s"
7 uint32_t mineip = 0xffffffff;
8 uint32_t maxeip = 0;
9
10 /* a hash structure to hold the arc */
11 struct arec {
12         uint32_t eip;
13         uint32_t from;
14         uint32_t count;
15         UT_hash_handle hh;
16 };
17
18 struct arec *arc = NULL;
19
20 void note_arc(uint32_t eip, uint32_t from)
21 {
22         struct arec *s;
23
24         HASH_FIND_INT(arc, &eip, s);
25         if (s == NULL) {
26                 s = malloc(sizeof(struct arec));
27                 s->eip = eip;
28                 s->from = from;
29                 s->count = 1;
30                 if (eip > maxeip)
31                         maxeip = eip;
32                 if (eip < mineip)
33                         maxeip = eip;
34
35                 HASH_ADD_INT(arc, eip, s);
36         } else {
37                 s->count++;
38         }
39 }
40
41 int main(int argc, char* argv[])
42 {
43         FILE *f, *fo;
44         struct arec *s;
45         uint32_t eip, from, tmp;
46         uint8_t tag;
47         uint16_t hit;
48
49         if ( argc < 2 )
50         {
51                 fprintf(stderr, "Please specify the coreboot trace log as parameter\n");
52                 return 1;
53         }
54
55         f = fopen(argv[1], "r");
56         fo = fopen("gmon.out", "w+");
57
58         if ((f == NULL) || (fo == NULL)) {
59                 fprintf(stderr, "Unable to manipulate with the input file\n");
60                 return 1;
61         }
62
63         while (!feof(f)) {
64                 if (fscanf(f, "~%x(%x)%*[^\n]\n", &eip, &from) == 2) {
65                         note_arc(eip, from);
66                 } else if (fscanf(f, "%*c~%x(%x)%*[^\n]\n", &eip, &from) == 2) {
67                         note_arc(eip, from);
68                 } else {
69                         /* just drop a line */
70                         tmp = fscanf(f, "%*[^\n]\n");
71                 }
72         }
73
74         /* write gprof header */
75         fwrite(GMON_MAGIC, 1, sizeof(GMON_MAGIC) - 1, fo);
76         tmp = GMON_VERSION;
77         fwrite(&tmp, 1, sizeof(tmp), fo);
78         tmp = 0;
79         fwrite(&tmp, 1, sizeof(tmp), fo);
80         fwrite(&tmp, 1, sizeof(tmp), fo);
81         fwrite(&tmp, 1, sizeof(tmp), fo);
82         /* write fake histogram */
83         tag = GMON_TAG_TIME_HIST;
84         fwrite(&tag, 1, sizeof(tag), fo);
85         fwrite(&mineip, 1, sizeof(mineip), fo);
86         fwrite(&maxeip, 1, sizeof(maxeip), fo);
87         /* size of histogram */
88         tmp = 1;
89         fwrite(&tmp, 1, sizeof(tmp), fo);
90         /* prof rate */
91         tmp = 1000;
92         fwrite(&tmp, 1, sizeof(tmp), fo);
93         fwrite(GMON_SEC, 1, sizeof(GMON_SEC) - 1, fo);
94         hit = 1;
95         fwrite(&hit, 1, sizeof(hit), fo);
96
97         /* write call graph data */
98         tag = GMON_TAG_CG_ARC;
99         for (s = arc; s != NULL; s = s->hh.next) {
100                 fwrite(&tag, 1, sizeof(tag), fo);
101                 fwrite(&s->from, 1, sizeof(s->from), fo);
102                 fwrite(&s->eip, 1, sizeof(s->eip), fo);
103                 fwrite(&s->count, 1, sizeof(s->count), fo);
104         }
105
106         fclose(fo);
107         return 0;
108 }