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