13 static const char *profile_filename
;
14 static const char *map_filename
;
15 static int granularity
;
17 static int profile_len
;
18 static Profile_Entry
*functionTable
;
19 static int numFunctions
;
20 static int maxFunctions
;
22 static void read_args(int argc
, const char *argv
[])
26 fprintf(stderr
, "annotate <profile file> <map file>\n");
30 profile_filename
= argv
[1];
31 map_filename
= argv
[2];
34 static void read_profile()
36 FILE *in
= fopen(profile_filename
, "rb");
40 fprintf(stderr
, "Failed to open profile file '%s'\n",
46 fseek(in
, 0, SEEK_END
);
47 profile_len
= (int)ftell(in
)-8;
48 fseek(in
, 0, SEEK_SET
);
50 if ((fgetc(in
) != 'P') ||
56 fprintf(stderr
, "'%s' is not a profile file\n",
62 fread(&granularity
, 4, 1, in
);
63 profile
= malloc(profile_len
);
67 fprintf(stderr
, "Out of memory reading profile\n");
72 fread(profile
, 4, profile_len
>>2, in
);
76 static void addFn(const char *text
, int offset
)
78 if (numFunctions
== maxFunctions
)
80 int newSize
= maxFunctions
*2;
85 functionTable
= realloc(functionTable
,
86 newSize
*sizeof(Profile_Entry
));
87 if (functionTable
== NULL
)
89 fprintf(stderr
, "Out of memory reading mapfile\n");
93 maxFunctions
= newSize
;
96 functionTable
[numFunctions
].name
= malloc(strlen(text
)+1);
97 strcpy(functionTable
[numFunctions
].name
, text
);
98 functionTable
[numFunctions
].offset
= offset
;
99 functionTable
[numFunctions
].count
= 0;
100 functionTable
[numFunctions
].percent
= 0.0;
101 //fprintf(stdout, "%s %x\n", functionTable[numFunctions].name,
102 // functionTable[numFunctions].offset);
106 static void read_map()
108 FILE *in
= fopen(map_filename
, "rb");
113 fprintf(stderr
, "Failed to open map file '%s'\n",
119 functionTable
= NULL
;
123 addFn("Address 0", 0);
131 /* Skip over any whitespace */
136 while (((c
== 32) || (c
== 9)) && (!feof(in
)));
139 /* Try to read an offset */
140 if (fscanf(in
, "0x%x", &offset
) != 1)
144 /* Skip over any whitespace */
149 while ((c
== 32) && (!feof(in
)));
152 /* Names never start with . or (*/
154 ((c
< 'a') || (c
> 'z')) &&
155 ((c
< 'A') || (c
> 'Z')))
168 /* Now there should be nothing left on this line */
169 if ((c
!= 10) && (c
!= 13))
172 /* And put the return back */
181 /* Skip to the end of the line */
186 while ((c
>= 32) && (!feof(in
)));
188 /* Skip over any newlines */
189 while (((c
== 10) || (c
== 13)) && (!feof(in
)))
194 /* And put the first non whitespace/non return char back */
201 static void show_profile()
205 for (i
=0; i
< numFunctions
; i
++)
207 fprintf(stdout
, "%08x (%6.2f%%: %6d) %s\n",
208 functionTable
[i
].offset
,
209 functionTable
[i
].percent
,
210 functionTable
[i
].count
,
211 functionTable
[i
].name
);
215 int byAddress(const void *_e1
, const void *_e2
)
217 const Profile_Entry
*e1
= (const Profile_Entry
*)_e1
;
218 const Profile_Entry
*e2
= (const Profile_Entry
*)_e2
;
220 return e1
->offset
- e2
->offset
;
223 int byTime(const void *_e1
, const void *_e2
)
225 const Profile_Entry
*e1
= (const Profile_Entry
*)_e1
;
226 const Profile_Entry
*e2
= (const Profile_Entry
*)_e2
;
228 return e2
->count
- e1
->count
;
231 static void process_profile()
239 /* Sort into address order */
242 sizeof(Profile_Entry
),
245 /* Run through the profile adding it to the appropriate function */
246 fn
= -1; /* Which function are we looking at */
247 next
= -1; /* At what address should we move to the next function */
248 idx
= 0; /* Where are we in the profile */
249 max
= profile_len
>>2;
251 for (idx
= 0; idx
< max
; idx
++)
253 while ((idx
<<(granularity
+2)) >= next
)
255 /* Move to the next function */
257 //fprintf(stdout, "Will be on fn %s until we pass %x\n",
258 // functionTable[fn].name, functionTable[fn+1].offset);
260 if (fn
+1 < numFunctions
)
262 next
= functionTable
[fn
+1].offset
;
265 //fprintf(stdout, "fn=%d count=%d idx=%d next=%x\n",
266 // fn, functionTable[fn].count, idx, next);
267 functionTable
[fn
].count
+= profile
[idx
];
268 total
+= profile
[idx
];
271 for (fn
= 0; fn
< numFunctions
; fn
++)
273 functionTable
[fn
].percent
= 100.0*functionTable
[fn
].count
/total
;
276 fprintf(stdout
, "Profile by Address\n");
279 /* Sort into time order */
282 sizeof(Profile_Entry
),
285 fprintf(stdout
, "\n\n");
286 fprintf(stdout
, "Profile by Time\n");
290 int main(int argc
, const char *argv
[])
292 read_args(argc
, argv
);