InstrProfilingFile.c revision 360784
1/*===- InstrProfilingFile.c - Write instrumentation to a file -------------===*\
2|*
3|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4|* See https://llvm.org/LICENSE.txt for license information.
5|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6|*
7\*===----------------------------------------------------------------------===*/
8
9#if !defined(__Fuchsia__)
10
11#include <errno.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#ifdef _MSC_VER
16/* For _alloca. */
17#include <malloc.h>
18#endif
19#if defined(_WIN32)
20#include "WindowsMMap.h"
21/* For _chsize_s */
22#include <io.h>
23#include <process.h>
24#else
25#include <sys/file.h>
26#include <sys/mman.h>
27#include <unistd.h>
28#if defined(__linux__)
29#include <sys/types.h>
30#endif
31#endif
32
33#include "InstrProfiling.h"
34#include "InstrProfilingInternal.h"
35#include "InstrProfilingPort.h"
36#include "InstrProfilingUtil.h"
37
38/* From where is profile name specified.
39 * The order the enumerators define their
40 * precedence. Re-order them may lead to
41 * runtime behavior change. */
42typedef enum ProfileNameSpecifier {
43  PNS_unknown = 0,
44  PNS_default,
45  PNS_command_line,
46  PNS_environment,
47  PNS_runtime_api
48} ProfileNameSpecifier;
49
50static const char *getPNSStr(ProfileNameSpecifier PNS) {
51  switch (PNS) {
52  case PNS_default:
53    return "default setting";
54  case PNS_command_line:
55    return "command line";
56  case PNS_environment:
57    return "environment variable";
58  case PNS_runtime_api:
59    return "runtime API";
60  default:
61    return "Unknown";
62  }
63}
64
65#define MAX_PID_SIZE 16
66/* Data structure holding the result of parsed filename pattern. */
67typedef struct lprofFilename {
68  /* File name string possibly with %p or %h specifiers. */
69  const char *FilenamePat;
70  /* A flag indicating if FilenamePat's memory is allocated
71   * by runtime. */
72  unsigned OwnsFilenamePat;
73  const char *ProfilePathPrefix;
74  char PidChars[MAX_PID_SIZE];
75  char Hostname[COMPILER_RT_MAX_HOSTLEN];
76  unsigned NumPids;
77  unsigned NumHosts;
78  /* When in-process merging is enabled, this parameter specifies
79   * the total number of profile data files shared by all the processes
80   * spawned from the same binary. By default the value is 1. If merging
81   * is not enabled, its value should be 0. This parameter is specified
82   * by the %[0-9]m specifier. For instance %2m enables merging using
83   * 2 profile data files. %1m is equivalent to %m. Also %m specifier
84   * can only appear once at the end of the name pattern. */
85  unsigned MergePoolSize;
86  ProfileNameSpecifier PNS;
87} lprofFilename;
88
89static lprofFilename lprofCurFilename = {0, 0, 0, {0},        {0},
90                                         0, 0, 0, PNS_unknown};
91
92static int ProfileMergeRequested = 0;
93static int isProfileMergeRequested() { return ProfileMergeRequested; }
94static void setProfileMergeRequested(int EnableMerge) {
95  ProfileMergeRequested = EnableMerge;
96}
97
98static FILE *ProfileFile = NULL;
99static FILE *getProfileFile() { return ProfileFile; }
100static void setProfileFile(FILE *File) { ProfileFile = File; }
101
102COMPILER_RT_VISIBILITY void __llvm_profile_set_file_object(FILE *File,
103                                                           int EnableMerge) {
104  if (__llvm_profile_is_continuous_mode_enabled()) {
105    PROF_WARN("__llvm_profile_set_file_object(fd=%d) not supported, because "
106              "continuous sync mode (%%c) is enabled",
107              fileno(File));
108    return;
109  }
110  setProfileFile(File);
111  setProfileMergeRequested(EnableMerge);
112}
113
114static int getCurFilenameLength();
115static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf);
116static unsigned doMerging() {
117  return lprofCurFilename.MergePoolSize || isProfileMergeRequested();
118}
119
120/* Return 1 if there is an error, otherwise return  0.  */
121static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
122                           uint32_t NumIOVecs) {
123  uint32_t I;
124  FILE *File = (FILE *)This->WriterCtx;
125  char Zeroes[sizeof(uint64_t)] = {0};
126  for (I = 0; I < NumIOVecs; I++) {
127    if (IOVecs[I].Data) {
128      if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
129          IOVecs[I].NumElm)
130        return 1;
131    } else if (IOVecs[I].UseZeroPadding) {
132      size_t BytesToWrite = IOVecs[I].ElmSize * IOVecs[I].NumElm;
133      while (BytesToWrite > 0) {
134        size_t PartialWriteLen =
135            (sizeof(uint64_t) > BytesToWrite) ? BytesToWrite : sizeof(uint64_t);
136        if (fwrite(Zeroes, sizeof(uint8_t), PartialWriteLen, File) !=
137            PartialWriteLen) {
138          return 1;
139        }
140        BytesToWrite -= PartialWriteLen;
141      }
142    } else {
143      if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR) == -1)
144        return 1;
145    }
146  }
147  return 0;
148}
149
150/* TODO: make buffer size controllable by an internal option, and compiler can pass the size
151   to runtime via a variable. */
152static uint32_t orderFileWriter(FILE *File, const uint32_t *DataStart) {
153  if (fwrite(DataStart, sizeof(uint32_t), INSTR_ORDER_FILE_BUFFER_SIZE, File) !=
154      INSTR_ORDER_FILE_BUFFER_SIZE)
155    return 1;
156  return 0;
157}
158
159static void initFileWriter(ProfDataWriter *This, FILE *File) {
160  This->Write = fileWriter;
161  This->WriterCtx = File;
162}
163
164COMPILER_RT_VISIBILITY ProfBufferIO *
165lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
166  FreeHook = &free;
167  DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
168  VPBufferSize = BufferSz;
169  ProfDataWriter *fileWriter =
170      (ProfDataWriter *)calloc(sizeof(ProfDataWriter), 1);
171  initFileWriter(fileWriter, File);
172  ProfBufferIO *IO = lprofCreateBufferIO(fileWriter);
173  IO->OwnFileWriter = 1;
174  return IO;
175}
176
177static void setupIOBuffer() {
178  const char *BufferSzStr = 0;
179  BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
180  if (BufferSzStr && BufferSzStr[0]) {
181    VPBufferSize = atoi(BufferSzStr);
182    DynamicBufferIOBuffer = (uint8_t *)calloc(VPBufferSize, 1);
183  }
184}
185
186/* Get the size of the profile file. If there are any errors, print the
187 * message under the assumption that the profile is being read for merging
188 * purposes, and return -1. Otherwise return the file size in the inout param
189 * \p ProfileFileSize. */
190static int getProfileFileSizeForMerging(FILE *ProfileFile,
191                                        uint64_t *ProfileFileSize) {
192  if (fseek(ProfileFile, 0L, SEEK_END) == -1) {
193    PROF_ERR("Unable to merge profile data, unable to get size: %s\n",
194             strerror(errno));
195    return -1;
196  }
197  *ProfileFileSize = ftell(ProfileFile);
198
199  /* Restore file offset.  */
200  if (fseek(ProfileFile, 0L, SEEK_SET) == -1) {
201    PROF_ERR("Unable to merge profile data, unable to rewind: %s\n",
202             strerror(errno));
203    return -1;
204  }
205
206  if (*ProfileFileSize > 0 &&
207      *ProfileFileSize < sizeof(__llvm_profile_header)) {
208    PROF_WARN("Unable to merge profile data: %s\n",
209              "source profile file is too small.");
210    return -1;
211  }
212  return 0;
213}
214
215/* mmap() \p ProfileFile for profile merging purposes, assuming that an
216 * exclusive lock is held on the file and that \p ProfileFileSize is the
217 * length of the file. Return the mmap'd buffer in the inout variable
218 * \p ProfileBuffer. Returns -1 on failure. On success, the caller is
219 * responsible for unmapping the mmap'd buffer in \p ProfileBuffer. */
220static int mmapProfileForMerging(FILE *ProfileFile, uint64_t ProfileFileSize,
221                                 char **ProfileBuffer) {
222  *ProfileBuffer = mmap(NULL, ProfileFileSize, PROT_READ, MAP_SHARED | MAP_FILE,
223                        fileno(ProfileFile), 0);
224  if (*ProfileBuffer == MAP_FAILED) {
225    PROF_ERR("Unable to merge profile data, mmap failed: %s\n",
226             strerror(errno));
227    return -1;
228  }
229
230  if (__llvm_profile_check_compatibility(*ProfileBuffer, ProfileFileSize)) {
231    (void)munmap(*ProfileBuffer, ProfileFileSize);
232    PROF_WARN("Unable to merge profile data: %s\n",
233              "source profile file is not compatible.");
234    return -1;
235  }
236  return 0;
237}
238
239/* Read profile data in \c ProfileFile and merge with in-memory
240   profile counters. Returns -1 if there is fatal error, otheriwse
241   0 is returned. Returning 0 does not mean merge is actually
242   performed. If merge is actually done, *MergeDone is set to 1.
243*/
244static int doProfileMerging(FILE *ProfileFile, int *MergeDone) {
245  uint64_t ProfileFileSize;
246  char *ProfileBuffer;
247
248  /* Get the size of the profile on disk. */
249  if (getProfileFileSizeForMerging(ProfileFile, &ProfileFileSize) == -1)
250    return -1;
251
252  /* Nothing to merge.  */
253  if (!ProfileFileSize)
254    return 0;
255
256  /* mmap() the profile and check that it is compatible with the data in
257   * the current image. */
258  if (mmapProfileForMerging(ProfileFile, ProfileFileSize, &ProfileBuffer) == -1)
259    return -1;
260
261  /* Now start merging */
262  __llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize);
263
264  // Truncate the file in case merging of value profile did not happend to
265  // prevent from leaving garbage data at the end of the profile file.
266  COMPILER_RT_FTRUNCATE(ProfileFile, __llvm_profile_get_size_for_buffer());
267
268  (void)munmap(ProfileBuffer, ProfileFileSize);
269  *MergeDone = 1;
270
271  return 0;
272}
273
274/* Create the directory holding the file, if needed. */
275static void createProfileDir(const char *Filename) {
276  size_t Length = strlen(Filename);
277  if (lprofFindFirstDirSeparator(Filename)) {
278    char *Copy = (char *)COMPILER_RT_ALLOCA(Length + 1);
279    strncpy(Copy, Filename, Length + 1);
280    __llvm_profile_recursive_mkdir(Copy);
281  }
282}
283
284/* Open the profile data for merging. It opens the file in r+b mode with
285 * file locking.  If the file has content which is compatible with the
286 * current process, it also reads in the profile data in the file and merge
287 * it with in-memory counters. After the profile data is merged in memory,
288 * the original profile data is truncated and gets ready for the profile
289 * dumper. With profile merging enabled, each executable as well as any of
290 * its instrumented shared libraries dump profile data into their own data file.
291*/
292static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
293  FILE *ProfileFile = NULL;
294  int rc;
295
296  ProfileFile = getProfileFile();
297  if (ProfileFile) {
298    lprofLockFileHandle(ProfileFile);
299  } else {
300    createProfileDir(ProfileFileName);
301    ProfileFile = lprofOpenFileEx(ProfileFileName);
302  }
303  if (!ProfileFile)
304    return NULL;
305
306  rc = doProfileMerging(ProfileFile, MergeDone);
307  if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)) ||
308      fseek(ProfileFile, 0L, SEEK_SET) == -1) {
309    PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName,
310             strerror(errno));
311    fclose(ProfileFile);
312    return NULL;
313  }
314  return ProfileFile;
315}
316
317static FILE *getFileObject(const char *OutputName) {
318  FILE *File;
319  File = getProfileFile();
320  if (File != NULL) {
321    return File;
322  }
323
324  return fopen(OutputName, "ab");
325}
326
327/* Write profile data to file \c OutputName.  */
328static int writeFile(const char *OutputName) {
329  int RetVal;
330  FILE *OutputFile;
331
332  int MergeDone = 0;
333  VPMergeHook = &lprofMergeValueProfData;
334  if (doMerging())
335    OutputFile = openFileForMerging(OutputName, &MergeDone);
336  else
337    OutputFile = getFileObject(OutputName);
338
339  if (!OutputFile)
340    return -1;
341
342  FreeHook = &free;
343  setupIOBuffer();
344  ProfDataWriter fileWriter;
345  initFileWriter(&fileWriter, OutputFile);
346  RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
347
348  if (OutputFile == getProfileFile()) {
349    fflush(OutputFile);
350    if (doMerging()) {
351      lprofUnlockFileHandle(OutputFile);
352    }
353  } else {
354    fclose(OutputFile);
355  }
356
357  return RetVal;
358}
359
360/* Write order data to file \c OutputName.  */
361static int writeOrderFile(const char *OutputName) {
362  int RetVal;
363  FILE *OutputFile;
364
365  OutputFile = fopen(OutputName, "w");
366
367  if (!OutputFile) {
368    PROF_WARN("can't open file with mode ab: %s\n", OutputName);
369    return -1;
370  }
371
372  FreeHook = &free;
373  setupIOBuffer();
374  const uint32_t *DataBegin = __llvm_profile_begin_orderfile();
375  RetVal = orderFileWriter(OutputFile, DataBegin);
376
377  fclose(OutputFile);
378  return RetVal;
379}
380
381#define LPROF_INIT_ONCE_ENV "__LLVM_PROFILE_RT_INIT_ONCE"
382
383static void truncateCurrentFile(void) {
384  const char *Filename;
385  char *FilenameBuf;
386  FILE *File;
387  int Length;
388
389  Length = getCurFilenameLength();
390  FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
391  Filename = getCurFilename(FilenameBuf, 0);
392  if (!Filename)
393    return;
394
395  /* Only create the profile directory and truncate an existing profile once.
396   * In continuous mode, this is necessary, as the profile is written-to by the
397   * runtime initializer. */
398  int initialized = getenv(LPROF_INIT_ONCE_ENV) != NULL;
399  if (initialized)
400    return;
401#if defined(_WIN32)
402  _putenv(LPROF_INIT_ONCE_ENV "=" LPROF_INIT_ONCE_ENV);
403#else
404  setenv(LPROF_INIT_ONCE_ENV, LPROF_INIT_ONCE_ENV, 1);
405#endif
406
407  /* Create the profile dir (even if online merging is enabled), so that
408   * the profile file can be set up if continuous mode is enabled. */
409  createProfileDir(Filename);
410
411  /* By pass file truncation to allow online raw profile merging. */
412  if (lprofCurFilename.MergePoolSize)
413    return;
414
415  /* Truncate the file.  Later we'll reopen and append. */
416  File = fopen(Filename, "w");
417  if (!File)
418    return;
419  fclose(File);
420}
421
422#ifndef _MSC_VER
423static void assertIsZero(int *i) {
424  if (*i)
425    PROF_WARN("Expected flag to be 0, but got: %d\n", *i);
426}
427#endif
428
429#if !defined(__Fuchsia__) && !defined(_WIN32)
430/* Write a partial profile to \p Filename, which is required to be backed by
431 * the open file object \p File. */
432static int writeProfileWithFileObject(const char *Filename, FILE *File) {
433  setProfileFile(File);
434  int rc = writeFile(Filename);
435  if (rc)
436    PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
437  setProfileFile(NULL);
438  return rc;
439}
440
441/* Unlock the profile \p File and clear the unlock flag. */
442static void unlockProfile(int *ProfileRequiresUnlock, FILE *File) {
443  if (!*ProfileRequiresUnlock) {
444    PROF_WARN("%s", "Expected to require profile unlock\n");
445  }
446  lprofUnlockFileHandle(File);
447  *ProfileRequiresUnlock = 0;
448}
449#endif // !defined(__Fuchsia__) && !defined(_WIN32)
450
451static void initializeProfileForContinuousMode(void) {
452  if (!__llvm_profile_is_continuous_mode_enabled())
453    return;
454
455#if defined(__Fuchsia__) || defined(_WIN32)
456  PROF_ERR("%s\n", "Continuous mode not yet supported on Fuchsia or Windows.");
457#else // defined(__Fuchsia__) || defined(_WIN32)
458  /* Get the sizes of various profile data sections. Taken from
459   * __llvm_profile_get_size_for_buffer(). */
460  const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
461  const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
462  const uint64_t *CountersBegin = __llvm_profile_begin_counters();
463  const uint64_t *CountersEnd = __llvm_profile_end_counters();
464  const char *NamesBegin = __llvm_profile_begin_names();
465  const char *NamesEnd = __llvm_profile_end_names();
466  const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
467  uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
468  uint64_t CountersSize = CountersEnd - CountersBegin;
469
470  /* Check that the counter and data sections in this image are page-aligned. */
471  unsigned PageSize = getpagesize();
472  if ((intptr_t)CountersBegin % PageSize != 0) {
473    PROF_ERR("Counters section not page-aligned (start = %p, pagesz = %u).\n",
474             CountersBegin, PageSize);
475    return;
476  }
477  if ((intptr_t)DataBegin % PageSize != 0) {
478    PROF_ERR("Data section not page-aligned (start = %p, pagesz = %u).\n",
479             DataBegin, PageSize);
480    return;
481  }
482
483  int Length = getCurFilenameLength();
484  char *FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
485  const char *Filename = getCurFilename(FilenameBuf, 0);
486  if (!Filename)
487    return;
488
489  FILE *File = NULL;
490  off_t CurrentFileOffset = 0;
491  off_t OffsetModPage = 0;
492
493  /* Whether an exclusive lock on the profile must be dropped after init.
494   * Use a cleanup to warn if the unlock does not occur. */
495  COMPILER_RT_CLEANUP(assertIsZero) int ProfileRequiresUnlock = 0;
496
497  if (!doMerging()) {
498    /* We are not merging profiles, so open the raw profile in append mode. */
499    File = fopen(Filename, "a+b");
500    if (!File)
501      return;
502
503    /* Check that the offset within the file is page-aligned. */
504    CurrentFileOffset = ftello(File);
505    OffsetModPage = CurrentFileOffset % PageSize;
506    if (OffsetModPage != 0) {
507      PROF_ERR("Continuous counter sync mode is enabled, but raw profile is not"
508               "page-aligned. CurrentFileOffset = %" PRIu64 ", pagesz = %u.\n",
509               (uint64_t)CurrentFileOffset, PageSize);
510      return;
511    }
512
513    /* Grow the profile so that mmap() can succeed.  Leak the file handle, as
514     * the file should stay open. */
515    if (writeProfileWithFileObject(Filename, File) != 0)
516      return;
517  } else {
518    /* We are merging profiles. Map the counter section as shared memory into
519     * the profile, i.e. into each participating process. An increment in one
520     * process should be visible to every other process with the same counter
521     * section mapped. */
522    File = lprofOpenFileEx(Filename);
523    if (!File)
524      return;
525
526    ProfileRequiresUnlock = 1;
527
528    uint64_t ProfileFileSize;
529    if (getProfileFileSizeForMerging(File, &ProfileFileSize) == -1)
530      return unlockProfile(&ProfileRequiresUnlock, File);
531
532    if (ProfileFileSize == 0) {
533      /* Grow the profile so that mmap() can succeed.  Leak the file handle, as
534       * the file should stay open. */
535      if (writeProfileWithFileObject(Filename, File) != 0)
536        return unlockProfile(&ProfileRequiresUnlock, File);
537    } else {
538      /* The merged profile has a non-zero length. Check that it is compatible
539       * with the data in this process. */
540      char *ProfileBuffer;
541      if (mmapProfileForMerging(File, ProfileFileSize, &ProfileBuffer) == -1 ||
542          munmap(ProfileBuffer, ProfileFileSize) == -1)
543        return unlockProfile(&ProfileRequiresUnlock, File);
544    }
545  }
546
547  int Fileno = fileno(File);
548
549  /* Determine how much padding is needed before/after the counters and after
550   * the names. */
551  uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
552      PaddingBytesAfterNames;
553  __llvm_profile_get_padding_sizes_for_counters(
554      DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
555      &PaddingBytesAfterCounters, &PaddingBytesAfterNames);
556
557  uint64_t PageAlignedCountersLength =
558      (CountersSize * sizeof(uint64_t)) + PaddingBytesAfterCounters;
559  uint64_t FileOffsetToCounters =
560      CurrentFileOffset + sizeof(__llvm_profile_header) +
561      (DataSize * sizeof(__llvm_profile_data)) + PaddingBytesBeforeCounters;
562
563  uint64_t *CounterMmap = (uint64_t *)mmap(
564      (void *)CountersBegin, PageAlignedCountersLength, PROT_READ | PROT_WRITE,
565      MAP_FIXED | MAP_SHARED, Fileno, FileOffsetToCounters);
566  if (CounterMmap != CountersBegin) {
567    PROF_ERR(
568        "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
569        "  - CountersBegin: %p\n"
570        "  - PageAlignedCountersLength: %" PRIu64 "\n"
571        "  - Fileno: %d\n"
572        "  - FileOffsetToCounters: %" PRIu64 "\n",
573        strerror(errno), CountersBegin, PageAlignedCountersLength, Fileno,
574        FileOffsetToCounters);
575  }
576
577  unlockProfile(&ProfileRequiresUnlock, File);
578#endif // defined(__Fuchsia__) || defined(_WIN32)
579}
580
581static const char *DefaultProfileName = "default.profraw";
582static void resetFilenameToDefault(void) {
583  if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
584    free((void *)lprofCurFilename.FilenamePat);
585  }
586  memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
587  lprofCurFilename.FilenamePat = DefaultProfileName;
588  lprofCurFilename.PNS = PNS_default;
589}
590
591static unsigned getMergePoolSize(const char *FilenamePat, int *I) {
592  unsigned J = 0, Num = 0;
593  for (;; ++J) {
594    char C = FilenamePat[*I + J];
595    if (C == 'm') {
596      *I += J;
597      return Num ? Num : 1;
598    }
599    if (C < '0' || C > '9')
600      break;
601    Num = Num * 10 + C - '0';
602
603    /* If FilenamePat[*I+J] is between '0' and '9', the next byte is guaranteed
604     * to be in-bound as the string is null terminated. */
605  }
606  return 0;
607}
608
609/* Parses the pattern string \p FilenamePat and stores the result to
610 * lprofcurFilename structure. */
611static int parseFilenamePattern(const char *FilenamePat,
612                                unsigned CopyFilenamePat) {
613  int NumPids = 0, NumHosts = 0, I;
614  char *PidChars = &lprofCurFilename.PidChars[0];
615  char *Hostname = &lprofCurFilename.Hostname[0];
616  int MergingEnabled = 0;
617
618  /* Clean up cached prefix and filename.  */
619  if (lprofCurFilename.ProfilePathPrefix)
620    free((void *)lprofCurFilename.ProfilePathPrefix);
621
622  if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
623    free((void *)lprofCurFilename.FilenamePat);
624  }
625
626  memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
627
628  if (!CopyFilenamePat)
629    lprofCurFilename.FilenamePat = FilenamePat;
630  else {
631    lprofCurFilename.FilenamePat = strdup(FilenamePat);
632    lprofCurFilename.OwnsFilenamePat = 1;
633  }
634  /* Check the filename for "%p", which indicates a pid-substitution. */
635  for (I = 0; FilenamePat[I]; ++I)
636    if (FilenamePat[I] == '%') {
637      if (FilenamePat[++I] == 'p') {
638        if (!NumPids++) {
639          if (snprintf(PidChars, MAX_PID_SIZE, "%ld", (long)getpid()) <= 0) {
640            PROF_WARN("Unable to get pid for filename pattern %s. Using the "
641                      "default name.",
642                      FilenamePat);
643            return -1;
644          }
645        }
646      } else if (FilenamePat[I] == 'h') {
647        if (!NumHosts++)
648          if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)) {
649            PROF_WARN("Unable to get hostname for filename pattern %s. Using "
650                      "the default name.",
651                      FilenamePat);
652            return -1;
653          }
654      } else if (FilenamePat[I] == 'c') {
655        if (__llvm_profile_is_continuous_mode_enabled()) {
656          PROF_WARN("%%c specifier can only be specified once in %s.\n",
657                    FilenamePat);
658          return -1;
659        }
660
661        __llvm_profile_enable_continuous_mode();
662        I++; /* advance to 'c' */
663      } else {
664        unsigned MergePoolSize = getMergePoolSize(FilenamePat, &I);
665        if (!MergePoolSize)
666          continue;
667        if (MergingEnabled) {
668          PROF_WARN("%%m specifier can only be specified once in %s.\n",
669                    FilenamePat);
670          return -1;
671        }
672        MergingEnabled = 1;
673        lprofCurFilename.MergePoolSize = MergePoolSize;
674      }
675    }
676
677  lprofCurFilename.NumPids = NumPids;
678  lprofCurFilename.NumHosts = NumHosts;
679  return 0;
680}
681
682static void parseAndSetFilename(const char *FilenamePat,
683                                ProfileNameSpecifier PNS,
684                                unsigned CopyFilenamePat) {
685
686  const char *OldFilenamePat = lprofCurFilename.FilenamePat;
687  ProfileNameSpecifier OldPNS = lprofCurFilename.PNS;
688
689  /* The old profile name specifier takes precedence over the old one. */
690  if (PNS < OldPNS)
691    return;
692
693  if (!FilenamePat)
694    FilenamePat = DefaultProfileName;
695
696  if (OldFilenamePat && !strcmp(OldFilenamePat, FilenamePat)) {
697    lprofCurFilename.PNS = PNS;
698    return;
699  }
700
701  /* When PNS >= OldPNS, the last one wins. */
702  if (!FilenamePat || parseFilenamePattern(FilenamePat, CopyFilenamePat))
703    resetFilenameToDefault();
704  lprofCurFilename.PNS = PNS;
705
706  if (!OldFilenamePat) {
707    if (getenv("LLVM_PROFILE_VERBOSE"))
708      PROF_NOTE("Set profile file path to \"%s\" via %s.\n",
709                lprofCurFilename.FilenamePat, getPNSStr(PNS));
710  } else {
711    if (getenv("LLVM_PROFILE_VERBOSE"))
712      PROF_NOTE("Override old profile path \"%s\" via %s to \"%s\" via %s.\n",
713                OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat,
714                getPNSStr(PNS));
715  }
716
717  truncateCurrentFile();
718  initializeProfileForContinuousMode();
719}
720
721/* Return buffer length that is required to store the current profile
722 * filename with PID and hostname substitutions. */
723/* The length to hold uint64_t followed by 3 digits pool id including '_' */
724#define SIGLEN 24
725static int getCurFilenameLength() {
726  int Len;
727  if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
728    return 0;
729
730  if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
731        lprofCurFilename.MergePoolSize))
732    return strlen(lprofCurFilename.FilenamePat);
733
734  Len = strlen(lprofCurFilename.FilenamePat) +
735        lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
736        lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2);
737  if (lprofCurFilename.MergePoolSize)
738    Len += SIGLEN;
739  return Len;
740}
741
742/* Return the pointer to the current profile file name (after substituting
743 * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer
744 * to store the resulting filename. If no substitution is needed, the
745 * current filename pattern string is directly returned, unless ForceUseBuf
746 * is enabled. */
747static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
748  int I, J, PidLength, HostNameLength, FilenamePatLength;
749  const char *FilenamePat = lprofCurFilename.FilenamePat;
750
751  if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
752    return 0;
753
754  if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
755        lprofCurFilename.MergePoolSize ||
756        __llvm_profile_is_continuous_mode_enabled())) {
757    if (!ForceUseBuf)
758      return lprofCurFilename.FilenamePat;
759
760    FilenamePatLength = strlen(lprofCurFilename.FilenamePat);
761    memcpy(FilenameBuf, lprofCurFilename.FilenamePat, FilenamePatLength);
762    FilenameBuf[FilenamePatLength] = '\0';
763    return FilenameBuf;
764  }
765
766  PidLength = strlen(lprofCurFilename.PidChars);
767  HostNameLength = strlen(lprofCurFilename.Hostname);
768  /* Construct the new filename. */
769  for (I = 0, J = 0; FilenamePat[I]; ++I)
770    if (FilenamePat[I] == '%') {
771      if (FilenamePat[++I] == 'p') {
772        memcpy(FilenameBuf + J, lprofCurFilename.PidChars, PidLength);
773        J += PidLength;
774      } else if (FilenamePat[I] == 'h') {
775        memcpy(FilenameBuf + J, lprofCurFilename.Hostname, HostNameLength);
776        J += HostNameLength;
777      } else {
778        if (!getMergePoolSize(FilenamePat, &I))
779          continue;
780        char LoadModuleSignature[SIGLEN + 1];
781        int S;
782        int ProfilePoolId = getpid() % lprofCurFilename.MergePoolSize;
783        S = snprintf(LoadModuleSignature, SIGLEN + 1, "%" PRIu64 "_%d",
784                     lprofGetLoadModuleSignature(), ProfilePoolId);
785        if (S == -1 || S > SIGLEN)
786          S = SIGLEN;
787        memcpy(FilenameBuf + J, LoadModuleSignature, S);
788        J += S;
789      }
790      /* Drop any unknown substitutions. */
791    } else
792      FilenameBuf[J++] = FilenamePat[I];
793  FilenameBuf[J] = 0;
794
795  return FilenameBuf;
796}
797
798/* Returns the pointer to the environment variable
799 * string. Returns null if the env var is not set. */
800static const char *getFilenamePatFromEnv(void) {
801  const char *Filename = getenv("LLVM_PROFILE_FILE");
802  if (!Filename || !Filename[0])
803    return 0;
804  return Filename;
805}
806
807COMPILER_RT_VISIBILITY
808const char *__llvm_profile_get_path_prefix(void) {
809  int Length;
810  char *FilenameBuf, *Prefix;
811  const char *Filename, *PrefixEnd;
812
813  if (lprofCurFilename.ProfilePathPrefix)
814    return lprofCurFilename.ProfilePathPrefix;
815
816  Length = getCurFilenameLength();
817  FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
818  Filename = getCurFilename(FilenameBuf, 0);
819  if (!Filename)
820    return "\0";
821
822  PrefixEnd = lprofFindLastDirSeparator(Filename);
823  if (!PrefixEnd)
824    return "\0";
825
826  Length = PrefixEnd - Filename + 1;
827  Prefix = (char *)malloc(Length + 1);
828  if (!Prefix) {
829    PROF_ERR("Failed to %s\n", "allocate memory.");
830    return "\0";
831  }
832  memcpy(Prefix, Filename, Length);
833  Prefix[Length] = '\0';
834  lprofCurFilename.ProfilePathPrefix = Prefix;
835  return Prefix;
836}
837
838COMPILER_RT_VISIBILITY
839const char *__llvm_profile_get_filename(void) {
840  int Length;
841  char *FilenameBuf;
842  const char *Filename;
843
844  Length = getCurFilenameLength();
845  FilenameBuf = (char *)malloc(Length + 1);
846  if (!FilenameBuf) {
847    PROF_ERR("Failed to %s\n", "allocate memory.");
848    return "\0";
849  }
850  Filename = getCurFilename(FilenameBuf, 1);
851  if (!Filename)
852    return "\0";
853
854  return FilenameBuf;
855}
856
857/* This method is invoked by the runtime initialization hook
858 * InstrProfilingRuntime.o if it is linked in. Both user specified
859 * profile path via -fprofile-instr-generate= and LLVM_PROFILE_FILE
860 * environment variable can override this default value. */
861COMPILER_RT_VISIBILITY
862void __llvm_profile_initialize_file(void) {
863  const char *EnvFilenamePat;
864  const char *SelectedPat = NULL;
865  ProfileNameSpecifier PNS = PNS_unknown;
866  int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR[0] != 0);
867
868  EnvFilenamePat = getFilenamePatFromEnv();
869  if (EnvFilenamePat) {
870    /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
871       at the  moment when __llvm_profile_write_file() gets executed. */
872    parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
873    return;
874  } else if (hasCommandLineOverrider) {
875    SelectedPat = INSTR_PROF_PROFILE_NAME_VAR;
876    PNS = PNS_command_line;
877  } else {
878    SelectedPat = NULL;
879    PNS = PNS_default;
880  }
881
882  parseAndSetFilename(SelectedPat, PNS, 0);
883}
884
885/* This API is directly called by the user application code. It has the
886 * highest precedence compared with LLVM_PROFILE_FILE environment variable
887 * and command line option -fprofile-instr-generate=<profile_name>.
888 */
889COMPILER_RT_VISIBILITY
890void __llvm_profile_set_filename(const char *FilenamePat) {
891  if (__llvm_profile_is_continuous_mode_enabled())
892    return;
893  parseAndSetFilename(FilenamePat, PNS_runtime_api, 1);
894}
895
896/* The public API for writing profile data into the file with name
897 * set by previous calls to __llvm_profile_set_filename or
898 * __llvm_profile_override_default_filename or
899 * __llvm_profile_initialize_file. */
900COMPILER_RT_VISIBILITY
901int __llvm_profile_write_file(void) {
902  int rc, Length;
903  const char *Filename;
904  char *FilenameBuf;
905  int PDeathSig = 0;
906
907  if (lprofProfileDumped() || __llvm_profile_is_continuous_mode_enabled()) {
908    PROF_NOTE("Profile data not written to file: %s.\n", "already written");
909    return 0;
910  }
911
912  Length = getCurFilenameLength();
913  FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
914  Filename = getCurFilename(FilenameBuf, 0);
915
916  /* Check the filename. */
917  if (!Filename) {
918    PROF_ERR("Failed to write file : %s\n", "Filename not set");
919    return -1;
920  }
921
922  /* Check if there is llvm/runtime version mismatch.  */
923  if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
924    PROF_ERR("Runtime and instrumentation version mismatch : "
925             "expected %d, but get %d\n",
926             INSTR_PROF_RAW_VERSION,
927             (int)GET_VERSION(__llvm_profile_get_version()));
928    return -1;
929  }
930
931  // Temporarily suspend getting SIGKILL when the parent exits.
932  PDeathSig = lprofSuspendSigKill();
933
934  /* Write profile data to the file. */
935  rc = writeFile(Filename);
936  if (rc)
937    PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
938
939  // Restore SIGKILL.
940  if (PDeathSig == 1)
941    lprofRestoreSigKill();
942
943  return rc;
944}
945
946COMPILER_RT_VISIBILITY
947int __llvm_profile_dump(void) {
948  if (!doMerging())
949    PROF_WARN("Later invocation of __llvm_profile_dump can lead to clobbering "
950              " of previously dumped profile data : %s. Either use %%m "
951              "in profile name or change profile name before dumping.\n",
952              "online profile merging is not on");
953  int rc = __llvm_profile_write_file();
954  lprofSetProfileDumped();
955  return rc;
956}
957
958/* Order file data will be saved in a file with suffx .order. */
959static const char *OrderFileSuffix = ".order";
960
961COMPILER_RT_VISIBILITY
962int __llvm_orderfile_write_file(void) {
963  int rc, Length, LengthBeforeAppend, SuffixLength;
964  const char *Filename;
965  char *FilenameBuf;
966  int PDeathSig = 0;
967
968  SuffixLength = strlen(OrderFileSuffix);
969  Length = getCurFilenameLength() + SuffixLength;
970  FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
971  Filename = getCurFilename(FilenameBuf, 1);
972
973  /* Check the filename. */
974  if (!Filename) {
975    PROF_ERR("Failed to write file : %s\n", "Filename not set");
976    return -1;
977  }
978
979  /* Append order file suffix */
980  LengthBeforeAppend = strlen(Filename);
981  memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength);
982  FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0';
983
984  /* Check if there is llvm/runtime version mismatch.  */
985  if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
986    PROF_ERR("Runtime and instrumentation version mismatch : "
987             "expected %d, but get %d\n",
988             INSTR_PROF_RAW_VERSION,
989             (int)GET_VERSION(__llvm_profile_get_version()));
990    return -1;
991  }
992
993  // Temporarily suspend getting SIGKILL when the parent exits.
994  PDeathSig = lprofSuspendSigKill();
995
996  /* Write order data to the file. */
997  rc = writeOrderFile(Filename);
998  if (rc)
999    PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
1000
1001  // Restore SIGKILL.
1002  if (PDeathSig == 1)
1003    lprofRestoreSigKill();
1004
1005  return rc;
1006}
1007
1008COMPILER_RT_VISIBILITY
1009int __llvm_orderfile_dump(void) {
1010  int rc = __llvm_orderfile_write_file();
1011  return rc;
1012}
1013
1014static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }
1015
1016COMPILER_RT_VISIBILITY
1017int __llvm_profile_register_write_file_atexit(void) {
1018  static int HasBeenRegistered = 0;
1019
1020  if (HasBeenRegistered)
1021    return 0;
1022
1023  lprofSetupValueProfiler();
1024
1025  HasBeenRegistered = 1;
1026  return atexit(writeFileWithoutReturn);
1027}
1028
1029#endif
1030