Home | History | Annotate | Download | only in reader
      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 
     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 
     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 
    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