1
2 /*
3 * Copyright (C) Texas Instruments - http://www.ti.com/
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21 #ifdef __PERF_READER__
22
23 #define __DECODE(c) (((c) < 0 || (c) > 63) ? '#' : ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789./_" [c]))
24
25 #include "perf.h"
26 /*=============================================================================
27 DEFINITIONS
28 =============================================================================*/
29
30 /* minimum and maximum time-correction handled */
31 #define MIN_DELTA 1U
32 #define MAX_DELTA 4292967295U
33
34
35 /** __PERF_CUSTOMIZABLE__ must be enabled, as we are using the
36 * standard PERF module for printing */
37 #ifndef __PERF_CUSTOMIZABLE__
38 #error "Must define __PERF_CUSTOMIZABLE__ to enable printing for reader"
39 #else
40
41 #include "perf_config.h"
42 #include "perf.h"
43
44 #include <errno.h>
45
46 typedef unsigned long U32;
47
48 /*=============================================================================
49 GLOBALS
50 =============================================================================*/
51
read_U32(FILE * fLog)52 static U32 read_U32(FILE *fLog)
53 {
54 U32 data;
55 fread(&data, sizeof(U32), 1, fLog);
56 return(data);
57 }
58
59 PERF_OBJHANDLE __PERF_common_Create(struct PERF_Config *config,
60 unsigned long ulID,
61 PERF_MODULETYPE eModule);
62 void __PERF_CUSTOM_create(PERF_OBJHANDLE hObject,
63 struct PERF_Config *config,
64 PERF_MODULETYPE eModule);
65
PERF_Replay(FILE * fLog,PERF_Config * pConfig)66 void PERF_Replay(FILE *fLog, PERF_Config *pConfig)
67 {
68 U32 ulData0, ulData1, ulData2, ulData3, ulData4, ulData5, ulData6, ulData7, operation;
69 char szFile[21], szFunc[21];
70 U32 sending, multiple, frame, size;
71 PERF_OBJHANDLE hObject = NULL;
72 PERF_Private *me = NULL;
73 long time_correction = 0;
74 union __PERF_float_long uA, uV;
75
76 /* logging is disabled during replay because the __log_ API-s get the
77 time on their own, and are not feasible to be modified to work with
78 replayed times */
79 if (pConfig->trace_file)
80 {
81 free(pConfig->trace_file);
82 pConfig->trace_file = NULL;
83 }
84
85 /* read initialization info */
86
87 /* we support having multiple log files concatenated into one log file */
88 /* read through each log file */
89 /* we have to pre-read to detect end of file */
90 while ((ulData0 = read_U32(fLog)), !feof(fLog))
91 {
92
93 /* if there is no object, create one */
94 if (!hObject)
95 {
96 /* create PERF replay object */
97 /* pre-read word is the eModuleType */
98 ulData1 = read_U32(fLog); /* ID */
99
100 hObject = __PERF_common_Create(pConfig, ulData1, ulData0);
101 if (!hObject)
102 {
103 fprintf(stderr, "error: could not create PERF replay object\n");
104 exit(1);
105 }
106
107 me = get_Private(hObject);
108
109 /* set up initial state */
110 me->ulPID = read_U32(fLog); /* PID */
111 ulData1 = read_U32(fLog); /* startTime.sec */
112 ulData2 = read_U32(fLog); /* startTime.usec */
113 TIME_SET(me->time, ulData1, ulData2);
114 time_correction = 0;
115
116 /* continue setting up the PERF object */
117 __PERF_CUSTOM_create(hObject, pConfig, ulData0);
118 if (me->uMode == PERF_Mode_Replay)
119 {
120 fprintf(stderr, "Only replay mode is selected. Aborting...\n");
121 PERF_Done(hObject);
122 }
123 }
124 else
125 {
126 /* pre-read word is replay time difference, except for PERF_LOG_Location logs */
127 /* get operation */
128 ulData1 = read_U32(fLog);
129 operation = ulData1 & PERF_LOG_Mask;
130
131 if (operation != PERF_LOG_Location)
132 {
133 /* invariant: time_replayed = time_logged + time_correction */
134
135 /* if a negative or too-small time-stamp is encountered */
136 if (ulData0 > MAX_DELTA || ulData0 < MIN_DELTA ||
137 /* or if we cannot completely correct a prior time correction */
138 (time_correction && ulData0 < MIN_DELTA + (U32) (-time_correction)))
139 { /* store the time difference than cannot be replayed in the
140 time_correction variable, and replay a MIN_DELTA time
141 difference */
142 time_correction += (long) ulData0 - (long) MIN_DELTA;
143 ulData0 = MIN_DELTA;
144 }
145 else if (time_correction)
146 {
147 ulData0 = ulData0 + (U32) time_correction;
148 time_correction = 0;
149 }
150 TIME_INCREASE(me->time, ulData0);
151 ulData0 = ulData1;
152 }
153
154 /* Check for buffer operations */
155 if (operation & PERF_LOG_Buffer)
156 {
157 /* Buffer operation */
158 if (operation & PERF_LOG_Xfering) {
159 sending = PERF_FlagXfering;
160 size = PERF_bits(ulData0, 2 * PERF_ModuleBits,
161 30 - 2 * PERF_ModuleBits) << 3;
162 } else {
163 sending = operation & PERF_LOG_Sending;
164 size = PERF_bits(ulData0, PERF_ModuleBits,
165 28 - PERF_ModuleBits);
166 ulData0 &= PERF_ModuleMask;
167 }
168
169 /* read address */
170 ulData1 = read_U32(fLog);
171 multiple = (ulData1 & PERF_LOG_Multiple) ? PERF_FlagMultiple : PERF_FlagSingle;
172 frame = (ulData1 & PERF_LOG_Frame) ? PERF_FlagFrame : PERF_FlagBuffer;
173
174 /* read 2nd address if logged multiple buffers */
175 ulData2 = PERF_IsMultiple(multiple) ? read_U32(fLog) : 0;
176
177 __PERF_CUSTOM_Buffer(hObject,
178 sending,
179 multiple,
180 frame,
181 ulData1 & ~3,
182 ulData2,
183 size,
184 PERF_bits(ulData0, 0, PERF_ModuleBits),
185 PERF_bits(ulData0, PERF_ModuleBits, PERF_ModuleBits) );
186 }
187 /* Check for command operations */
188 else if (operation & PERF_LOG_Command)
189 {
190 ulData1 = read_U32(fLog);
191 ulData2 = read_U32(fLog);
192 __PERF_CUSTOM_Command(hObject,
193 operation & PERF_LOG_Sending,
194 ulData1,
195 ulData2,
196 ulData0 & PERF_LOG_NotMask);
197 }
198 else switch (operation)
199 {
200 /* Log operation */
201 case PERF_LOG_Log:
202 ulData1 = read_U32(fLog);
203 ulData2 = read_U32(fLog);
204
205 __PERF_CUSTOM_Log(hObject,
206 ulData0 & PERF_LOG_NotMask,
207 ulData1,
208 ulData2);
209 break;
210
211 /* SyncAV operation */
212 case PERF_LOG_Sync:
213 uA.l = read_U32(fLog);
214 uV.l = read_U32(fLog);
215
216 __PERF_CUSTOM_SyncAV(hObject, uA.f, uV.f,
217 ulData0 & PERF_LOG_NotMask);
218 break;
219
220 case PERF_LOG_Done:
221 /* This can be also PERF_Thread, PERF_Boundary */
222 operation = ulData0 & PERF_LOG_Mask2;
223 switch (operation)
224 {
225 /* Thread Creation operation */
226 case PERF_LOG_Thread:
227 ulData1 = read_U32(fLog);
228
229 __PERF_CUSTOM_ThreadCreated(hObject,
230 ulData0 & PERF_LOG_NotMask2,
231 ulData1);
232 break;
233
234 /* Boundary operation */
235 case PERF_LOG_Boundary:
236 __PERF_CUSTOM_Boundary(hObject,
237 ulData0 & PERF_LOG_NotMask2);
238 break;
239
240 case PERF_LOG_Done:
241 __PERF_Done(hObject);
242
243 break;
244 }
245 break;
246
247 /* location log */
248 case PERF_LOG_Location:
249 ulData2 = read_U32(fLog);
250 ulData3 = read_U32(fLog);
251 ulData4 = read_U32(fLog);
252 ulData5 = read_U32(fLog);
253 ulData6 = read_U32(fLog);
254 ulData7 = read_U32(fLog);
255
256 /* decode szFile */
257 szFile[19] = __DECODE(ulData2 & 0x3f);
258 szFile[18] = __DECODE((ulData2 >> 6) & 0x3f);
259 szFile[17] = __DECODE((ulData2 >> 12) & 0x3f);
260 szFile[16] = __DECODE((ulData2 >> 18) & 0x3f);
261 szFile[15] = __DECODE((ulData2 >> 24) & 0x3f);
262 szFile[14] = __DECODE(((ulData2 >> 26) & 0x30) | ((ulData0 >> 24) & 0x0f));
263 szFile[13] = __DECODE(ulData3 & 0x3f);
264 szFile[12] = __DECODE((ulData3 >> 6) & 0x3f);
265 szFile[11] = __DECODE((ulData3 >> 12) & 0x3f);
266 szFile[10] = __DECODE((ulData3 >> 18) & 0x3f);
267 szFile[9] = __DECODE((ulData3 >> 24) & 0x3f);
268 szFile[8] = __DECODE(((ulData3 >> 26) & 0x30) | ((ulData0 >> 28) & 0x0f));
269 szFile[7] = __DECODE(ulData4 & 0x3f);
270 szFile[6] = __DECODE((ulData4 >> 6) & 0x3f);
271 szFile[5] = __DECODE((ulData4 >> 12) & 0x3f);
272 szFile[4] = __DECODE((ulData4 >> 18) & 0x3f);
273 szFile[3] = __DECODE((ulData4 >> 24) & 0x3f);
274 szFile[2] = __DECODE(((ulData4 >> 26) & 0x30) | (ulData1 & 0x0f));
275 szFile[1] = __DECODE(ulData0 & 0x3f);
276 szFile[0] = __DECODE((ulData0 >> 6) & 0x3f);
277 szFile[20] = '\0';
278
279 szFunc[19] = __DECODE(ulData5 & 0x3f);
280 szFunc[18] = __DECODE((ulData5 >> 6) & 0x3f);
281 szFunc[17] = __DECODE((ulData5 >> 12) & 0x3f);
282 szFunc[16] = __DECODE((ulData5 >> 18) & 0x3f);
283 szFunc[15] = __DECODE((ulData5 >> 24) & 0x3f);
284 szFunc[14] = __DECODE(((ulData5 >> 26) & 0x30) | ((ulData1 >> 4) & 0x0f));
285 szFunc[13] = __DECODE(ulData6 & 0x3f);
286 szFunc[12] = __DECODE((ulData6 >> 6) & 0x3f);
287 szFunc[11] = __DECODE((ulData6 >> 12) & 0x3f);
288 szFunc[10] = __DECODE((ulData6 >> 18) & 0x3f);
289 szFunc[9] = __DECODE((ulData6 >> 24) & 0x3f);
290 szFunc[8] = __DECODE(((ulData6 >> 26) & 0x30) | ((ulData1 >> 8) & 0x0f));
291 szFunc[7] = __DECODE(ulData7 & 0x3f);
292 szFunc[6] = __DECODE((ulData7 >> 6) & 0x3f);
293 szFunc[5] = __DECODE((ulData7 >> 12) & 0x3f);
294 szFunc[4] = __DECODE((ulData7 >> 18) & 0x3f);
295 szFunc[3] = __DECODE((ulData7 >> 24) & 0x3f);
296 szFunc[2] = __DECODE(((ulData7 >> 26) & 0x30) | ((ulData1 >> 12) & 0x0f));
297 szFunc[1] = __DECODE((ulData0 >> 12) & 0x3f);
298 szFunc[0] = __DECODE((ulData0 >> 18) & 0x3f);
299 szFunc[20] = '\0';
300
301 /* skip leading /-s */
302 for (ulData2 = 0; szFile[ulData2] == '/'; ulData2++);
303 for (ulData3 = 0; szFunc[ulData3] == '/'; ulData3++);
304
305 ulData1 = (ulData1 >> 16) & 0xfff;
306 __PERF_CUSTOM_Location(hObject,szFile + ulData2, ulData1,
307 szFunc + ulData3);
308
309 break;
310
311 default:
312 fprintf(stderr, "Unknown operation recorded: %lx\n", ulData0);
313 exit(1);
314 break;
315 }
316 }
317 }
318
319 if (hObject)
320 {
321 fprintf(stderr, "Incomplete log ended...\n");
322 PERF_Done(hObject);
323 }
324 }
325
main(int argc,char ** argv)326 int main(int argc, char **argv)
327 {
328 int i;
329 FILE *log = NULL;
330 PERF_Config config;
331
332
333 for (i = 1; i < argc; i++)
334 {
335 /* replay file */
336
337 /* open input, or stdin if '-' is specified */
338 log = strcmp(argv [i], "-") ? fopen(argv [i], "rb") : stdin;
339
340 if (log)
341 {
342 /* read config file */
343 PERF_Config_Init(&config);
344 PERF_Config_Read(&config, "replay");
345 config.mask = 0xFFFFFFFF;
346
347 /* note config gets modified during Replay */
348 PERF_Replay(log, &config);
349
350 PERF_Config_Release(&config);
351
352 /* don't close stdin! */
353 if (log != stdin) fclose(log);
354 }
355 else
356 {
357 fprintf(stderr, "Could not open log file %s: %d\n",
358 argv [i], errno);
359 }
360 }
361
362 return (0);
363 }
364
365 #endif /* __PERF_CUSTOMIZABLE__ */
366
367 #endif /* __PERF_READER__ */
368
369