Home | History | Annotate | Line # | Download | only in profile
InstrProfilingFile.c revision 1.1.1.1.2.2
      1 /*===- InstrProfilingFile.c - Write instrumentation to a file -------------===*\
      2 |*
      3 |*                     The LLVM Compiler Infrastructure
      4 |*
      5 |* This file is distributed under the University of Illinois Open Source
      6 |* License. See LICENSE.TXT for details.
      7 |*
      8 \*===----------------------------------------------------------------------===*/
      9 
     10 #include "InstrProfiling.h"
     11 #include <stdio.h>
     12 #include <stdlib.h>
     13 #include <string.h>
     14 
     15 static int writeFile(FILE *File) {
     16   /* Match logic in __llvm_profile_write_buffer(). */
     17   const __llvm_profile_data *DataBegin = __llvm_profile_data_begin();
     18   const __llvm_profile_data *DataEnd = __llvm_profile_data_end();
     19   const uint64_t *CountersBegin = __llvm_profile_counters_begin();
     20   const uint64_t *CountersEnd   = __llvm_profile_counters_end();
     21   const char *NamesBegin = __llvm_profile_names_begin();
     22   const char *NamesEnd   = __llvm_profile_names_end();
     23 
     24   /* Calculate size of sections. */
     25   const uint64_t DataSize = DataEnd - DataBegin;
     26   const uint64_t CountersSize = CountersEnd - CountersBegin;
     27   const uint64_t NamesSize = NamesEnd - NamesBegin;
     28 
     29   /* Create the header. */
     30   uint64_t Header[PROFILE_HEADER_SIZE];
     31   Header[0] = __llvm_profile_get_magic();
     32   Header[1] = __llvm_profile_get_version();
     33   Header[2] = DataSize;
     34   Header[3] = CountersSize;
     35   Header[4] = NamesSize;
     36   Header[5] = (uintptr_t)CountersBegin;
     37   Header[6] = (uintptr_t)NamesBegin;
     38 
     39   /* Write the data. */
     40 #define CHECK_fwrite(Data, Size, Length, File) \
     41   do { if (fwrite(Data, Size, Length, File) != Length) return -1; } while (0)
     42   CHECK_fwrite(Header,        sizeof(uint64_t), PROFILE_HEADER_SIZE, File);
     43   CHECK_fwrite(DataBegin,     sizeof(__llvm_profile_data), DataSize, File);
     44   CHECK_fwrite(CountersBegin, sizeof(uint64_t), CountersSize, File);
     45   CHECK_fwrite(NamesBegin,    sizeof(char), NamesSize, File);
     46 #undef CHECK_fwrite
     47 
     48    return 0;
     49 }
     50 
     51 static int writeFileWithName(const char *OutputName) {
     52   int RetVal;
     53   FILE *OutputFile;
     54   if (!OutputName || !OutputName[0])
     55     return -1;
     56   OutputFile = fopen(OutputName, "w");
     57   if (!OutputFile)
     58     return -1;
     59 
     60   RetVal = writeFile(OutputFile);
     61 
     62   fclose(OutputFile);
     63   return RetVal;
     64 }
     65 
     66 static const char *CurrentFilename = NULL;
     67 void __llvm_profile_set_filename(const char *Filename) {
     68   CurrentFilename = Filename;
     69 }
     70 
     71 int getpid(void);
     72 int __llvm_profile_write_file(void) {
     73   char *AllocatedFilename = NULL;
     74   int I, J;
     75   int RetVal;
     76 
     77 #define MAX_PID_SIZE 16
     78   char PidChars[MAX_PID_SIZE] = { 0 };
     79   int PidLength = 0;
     80   int NumPids = 0;
     81 
     82   /* Get the filename. */
     83   const char *Filename = CurrentFilename;
     84 #define UPDATE_FILENAME(NextFilename) \
     85   if (!Filename || !Filename[0]) Filename = NextFilename
     86   UPDATE_FILENAME(getenv("LLVM_PROFILE_FILE"));
     87   UPDATE_FILENAME("default.profraw");
     88 #undef UPDATE_FILENAME
     89 
     90   /* Check the filename for "%p", which indicates a pid-substitution. */
     91   for (I = 0; Filename[I]; ++I)
     92     if (Filename[I] == '%' && Filename[++I] == 'p')
     93       if (!NumPids++) {
     94         PidLength = snprintf(PidChars, MAX_PID_SIZE, "%d", getpid());
     95         if (PidLength <= 0)
     96           return -1;
     97       }
     98   if (NumPids) {
     99     /* Allocate enough space for the substituted filename. */
    100     AllocatedFilename = (char*)malloc(I + NumPids*(PidLength - 2) + 1);
    101     if (!AllocatedFilename)
    102       return -1;
    103 
    104     /* Construct the new filename. */
    105     for (I = 0, J = 0; Filename[I]; ++I)
    106       if (Filename[I] == '%') {
    107         if (Filename[++I] == 'p') {
    108           memcpy(AllocatedFilename + J, PidChars, PidLength);
    109           J += PidLength;
    110         }
    111         /* Drop any unknown substitutions. */
    112       } else
    113         AllocatedFilename[J++] = Filename[I];
    114     AllocatedFilename[J] = 0;
    115 
    116     /* Actually use the computed name. */
    117     Filename = AllocatedFilename;
    118   }
    119 
    120   /* Write the file. */
    121   RetVal = writeFileWithName(Filename);
    122 
    123   /* Free the filename. */
    124   if (AllocatedFilename)
    125     free(AllocatedFilename);
    126 
    127   return RetVal;
    128 }
    129 
    130 static void writeFileWithoutReturn(void) {
    131   __llvm_profile_write_file();
    132 }
    133 
    134 int __llvm_profile_register_write_file_atexit(void) {
    135   static int HasBeenRegistered = 0;
    136 
    137   if (HasBeenRegistered)
    138     return 0;
    139 
    140   HasBeenRegistered = 1;
    141   return atexit(writeFileWithoutReturn);
    142 }
    143