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   /* Only create the profile directory and truncate an existing profile once.
384    * In continuous mode, this is necessary, as the profile is written-to by the
385    * runtime initializer. */
386   int initialized = getenv(LPROF_INIT_ONCE_ENV) != NULL;
387   if (initialized)
388     return;
389 #if defined(_WIN32)
390   _putenv(LPROF_INIT_ONCE_ENV "=" LPROF_INIT_ONCE_ENV);
391 #else
392   setenv(LPROF_INIT_ONCE_ENV, LPROF_INIT_ONCE_ENV, 1);
393 #endif
394 
395   /* Create the profile dir (even if online merging is enabled), so that
396    * the profile file can be set up if continuous mode is enabled. */
397   createProfileDir(Filename);
398 
399   /* By pass file truncation to allow online raw profile merging. */
400   if (lprofCurFilename.MergePoolSize)
401     return;
402 
403   /* Truncate the file.  Later we'll reopen and append. */
404   File = fopen(Filename, "w");
405   if (!File)
406     return;
407   fclose(File);
408 }
409 
410 #ifndef _MSC_VER
411 static void assertIsZero(int *i) {
412   if (*i)
413     PROF_WARN("Expected flag to be 0, but got: %d\n", *i);
414 }
415 #endif
416 
417 #if !defined(__Fuchsia__) && !defined(_WIN32)
418 /* Write a partial profile to \p Filename, which is required to be backed by
419  * the open file object \p File. */
420 static int writeProfileWithFileObject(const char *Filename, FILE *File) {
421   setProfileFile(File);
422   int rc = writeFile(Filename);
423   if (rc)
424     PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
425   setProfileFile(NULL);
426   return rc;
427 }
428 
429 /* Unlock the profile \p File and clear the unlock flag. */
430 static void unlockProfile(int *ProfileRequiresUnlock, FILE *File) {
431   if (!*ProfileRequiresUnlock) {
432     PROF_WARN("%s", "Expected to require profile unlock\n");
433   }
434   lprofUnlockFileHandle(File);
435   *ProfileRequiresUnlock = 0;
436 }
437 #endif // !defined(__Fuchsia__) && !defined(_WIN32)
438 
439 static void initializeProfileForContinuousMode(void) {
440   if (!__llvm_profile_is_continuous_mode_enabled())
441     return;
442 
443 #if defined(__Fuchsia__) || defined(_WIN32)
444   PROF_ERR("%s\n", "Continuous mode not yet supported on Fuchsia or Windows.");
445 #else // defined(__Fuchsia__) || defined(_WIN32)
446   /* Get the sizes of various profile data sections. Taken from
447    * __llvm_profile_get_size_for_buffer(). */
448   const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
449   const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
450   const uint64_t *CountersBegin = __llvm_profile_begin_counters();
451   const uint64_t *CountersEnd = __llvm_profile_end_counters();
452   const char *NamesBegin = __llvm_profile_begin_names();
453   const char *NamesEnd = __llvm_profile_end_names();
454   const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
455   uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
456   uint64_t CountersSize = CountersEnd - CountersBegin;
457 
458   /* Check that the counter and data sections in this image are page-aligned. */
459   unsigned PageSize = getpagesize();
460   if ((intptr_t)CountersBegin % PageSize != 0) {
461     PROF_ERR("Counters section not page-aligned (start = %p, pagesz = %u).\n",
462              CountersBegin, PageSize);
463     return;
464   }
465   if ((intptr_t)DataBegin % PageSize != 0) {
466     PROF_ERR("Data section not page-aligned (start = %p, pagesz = %u).\n",
467              DataBegin, PageSize);
468     return;
469   }
470 
471   int Length = getCurFilenameLength();
472   char *FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
473   const char *Filename = getCurFilename(FilenameBuf, 0);
474   if (!Filename)
475     return;
476 
477   FILE *File = NULL;
478   off_t CurrentFileOffset = 0;
479   off_t OffsetModPage = 0;
480 
481   /* Whether an exclusive lock on the profile must be dropped after init.
482    * Use a cleanup to warn if the unlock does not occur. */
483   COMPILER_RT_CLEANUP(assertIsZero) int ProfileRequiresUnlock = 0;
484 
485   if (!doMerging()) {
486     /* We are not merging profiles, so open the raw profile in append mode. */
487     File = fopen(Filename, "a+b");
488     if (!File)
489       return;
490 
491     /* Check that the offset within the file is page-aligned. */
492     CurrentFileOffset = ftello(File);
493     OffsetModPage = CurrentFileOffset % PageSize;
494     if (OffsetModPage != 0) {
495       PROF_ERR("Continuous counter sync mode is enabled, but raw profile is not"
496                "page-aligned. CurrentFileOffset = %" PRIu64 ", pagesz = %u.\n",
497                (uint64_t)CurrentFileOffset, PageSize);
498       return;
499     }
500 
501     /* Grow the profile so that mmap() can succeed.  Leak the file handle, as
502      * the file should stay open. */
503     if (writeProfileWithFileObject(Filename, File) != 0)
504       return;
505   } else {
506     /* We are merging profiles. Map the counter section as shared memory into
507      * the profile, i.e. into each participating process. An increment in one
508      * process should be visible to every other process with the same counter
509      * section mapped. */
510     File = lprofOpenFileEx(Filename);
511     if (!File)
512       return;
513 
514     ProfileRequiresUnlock = 1;
515 
516     uint64_t ProfileFileSize;
517     if (getProfileFileSizeForMerging(File, &ProfileFileSize) == -1)
518       return unlockProfile(&ProfileRequiresUnlock, File);
519 
520     if (ProfileFileSize == 0) {
521       /* Grow the profile so that mmap() can succeed.  Leak the file handle, as
522        * the file should stay open. */
523       if (writeProfileWithFileObject(Filename, File) != 0)
524         return unlockProfile(&ProfileRequiresUnlock, File);
525     } else {
526       /* The merged profile has a non-zero length. Check that it is compatible
527        * with the data in this process. */
528       char *ProfileBuffer;
529       if (mmapProfileForMerging(File, ProfileFileSize, &ProfileBuffer) == -1 ||
530           munmap(ProfileBuffer, ProfileFileSize) == -1)
531         return unlockProfile(&ProfileRequiresUnlock, File);
532     }
533   }
534 
535   int Fileno = fileno(File);
536 
537   /* Determine how much padding is needed before/after the counters and after
538    * the names. */
539   uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
540       PaddingBytesAfterNames;
541   __llvm_profile_get_padding_sizes_for_counters(
542       DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
543       &PaddingBytesAfterCounters, &PaddingBytesAfterNames);
544 
545   uint64_t PageAlignedCountersLength =
546       (CountersSize * sizeof(uint64_t)) + PaddingBytesAfterCounters;
547   uint64_t FileOffsetToCounters =
548       CurrentFileOffset + sizeof(__llvm_profile_header) +
549       (DataSize * sizeof(__llvm_profile_data)) + PaddingBytesBeforeCounters;
550 
551   uint64_t *CounterMmap = (uint64_t *)mmap(
552       (void *)CountersBegin, PageAlignedCountersLength, PROT_READ | PROT_WRITE,
553       MAP_FIXED | MAP_SHARED, Fileno, FileOffsetToCounters);
554   if (CounterMmap != CountersBegin) {
555     PROF_ERR(
556         "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
557         "  - CountersBegin: %p\n"
558         "  - PageAlignedCountersLength: %" PRIu64 "\n"
559         "  - Fileno: %d\n"
560         "  - FileOffsetToCounters: %" PRIu64 "\n",
561         strerror(errno), CountersBegin, PageAlignedCountersLength, Fileno,
562         FileOffsetToCounters);
563   }
564 
565   unlockProfile(&ProfileRequiresUnlock, File);
566 #endif // defined(__Fuchsia__) || defined(_WIN32)
567 }
568 
569 static const char *DefaultProfileName = "default.profraw";
570 static void resetFilenameToDefault(void) {
571   if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
572     free((void *)lprofCurFilename.FilenamePat);
573   }
574   memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
575   lprofCurFilename.FilenamePat = DefaultProfileName;
576   lprofCurFilename.PNS = PNS_default;
577 }
578 
579 static int containsMergeSpecifier(const char *FilenamePat, int I) {
580   return (FilenamePat[I] == 'm' ||
581           (FilenamePat[I] >= '1' && FilenamePat[I] <= '9' &&
582            /* If FilenamePat[I] is not '\0', the next byte is guaranteed
583             * to be in-bound as the string is null terminated. */
584            FilenamePat[I + 1] == 'm'));
585 }
586 
587 /* Parses the pattern string \p FilenamePat and stores the result to
588  * lprofcurFilename structure. */
589 static int parseFilenamePattern(const char *FilenamePat,
590                                 unsigned CopyFilenamePat) {
591   int NumPids = 0, NumHosts = 0, I;
592   char *PidChars = &lprofCurFilename.PidChars[0];
593   char *Hostname = &lprofCurFilename.Hostname[0];
594   int MergingEnabled = 0;
595 
596   /* Clean up cached prefix and filename.  */
597   if (lprofCurFilename.ProfilePathPrefix)
598     free((void *)lprofCurFilename.ProfilePathPrefix);
599 
600   if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
601     free((void *)lprofCurFilename.FilenamePat);
602   }
603 
604   memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
605 
606   if (!CopyFilenamePat)
607     lprofCurFilename.FilenamePat = FilenamePat;
608   else {
609     lprofCurFilename.FilenamePat = strdup(FilenamePat);
610     lprofCurFilename.OwnsFilenamePat = 1;
611   }
612   /* Check the filename for "%p", which indicates a pid-substitution. */
613   for (I = 0; FilenamePat[I]; ++I)
614     if (FilenamePat[I] == '%') {
615       if (FilenamePat[++I] == 'p') {
616         if (!NumPids++) {
617           if (snprintf(PidChars, MAX_PID_SIZE, "%ld", (long)getpid()) <= 0) {
618             PROF_WARN("Unable to get pid for filename pattern %s. Using the "
619                       "default name.",
620                       FilenamePat);
621             return -1;
622           }
623         }
624       } else if (FilenamePat[I] == 'h') {
625         if (!NumHosts++)
626           if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)) {
627             PROF_WARN("Unable to get hostname for filename pattern %s. Using "
628                       "the default name.",
629                       FilenamePat);
630             return -1;
631           }
632       } else if (FilenamePat[I] == 'c') {
633         if (__llvm_profile_is_continuous_mode_enabled()) {
634           PROF_WARN("%%c specifier can only be specified once in %s.\n",
635                     FilenamePat);
636           return -1;
637         }
638 
639         __llvm_profile_enable_continuous_mode();
640         I++; /* advance to 'c' */
641       } else if (containsMergeSpecifier(FilenamePat, I)) {
642         if (MergingEnabled) {
643           PROF_WARN("%%m specifier can only be specified once in %s.\n",
644                     FilenamePat);
645           return -1;
646         }
647         MergingEnabled = 1;
648         if (FilenamePat[I] == 'm')
649           lprofCurFilename.MergePoolSize = 1;
650         else {
651           lprofCurFilename.MergePoolSize = FilenamePat[I] - '0';
652           I++; /* advance to 'm' */
653         }
654       }
655     }
656 
657   lprofCurFilename.NumPids = NumPids;
658   lprofCurFilename.NumHosts = NumHosts;
659   return 0;
660 }
661 
662 static void parseAndSetFilename(const char *FilenamePat,
663                                 ProfileNameSpecifier PNS,
664                                 unsigned CopyFilenamePat) {
665 
666   const char *OldFilenamePat = lprofCurFilename.FilenamePat;
667   ProfileNameSpecifier OldPNS = lprofCurFilename.PNS;
668 
669   /* The old profile name specifier takes precedence over the old one. */
670   if (PNS < OldPNS)
671     return;
672 
673   if (!FilenamePat)
674     FilenamePat = DefaultProfileName;
675 
676   if (OldFilenamePat && !strcmp(OldFilenamePat, FilenamePat)) {
677     lprofCurFilename.PNS = PNS;
678     return;
679   }
680 
681   /* When PNS >= OldPNS, the last one wins. */
682   if (!FilenamePat || parseFilenamePattern(FilenamePat, CopyFilenamePat))
683     resetFilenameToDefault();
684   lprofCurFilename.PNS = PNS;
685 
686   if (!OldFilenamePat) {
687     if (getenv("LLVM_PROFILE_VERBOSE"))
688       PROF_NOTE("Set profile file path to \"%s\" via %s.\n",
689                 lprofCurFilename.FilenamePat, getPNSStr(PNS));
690   } else {
691     if (getenv("LLVM_PROFILE_VERBOSE"))
692       PROF_NOTE("Override old profile path \"%s\" via %s to \"%s\" via %s.\n",
693                 OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat,
694                 getPNSStr(PNS));
695   }
696 
697   truncateCurrentFile();
698   initializeProfileForContinuousMode();
699 }
700 
701 /* Return buffer length that is required to store the current profile
702  * filename with PID and hostname substitutions. */
703 /* The length to hold uint64_t followed by 2 digit pool id including '_' */
704 #define SIGLEN 24
705 static int getCurFilenameLength() {
706   int Len;
707   if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
708     return 0;
709 
710   if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
711         lprofCurFilename.MergePoolSize))
712     return strlen(lprofCurFilename.FilenamePat);
713 
714   Len = strlen(lprofCurFilename.FilenamePat) +
715         lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
716         lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2);
717   if (lprofCurFilename.MergePoolSize)
718     Len += SIGLEN;
719   return Len;
720 }
721 
722 /* Return the pointer to the current profile file name (after substituting
723  * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer
724  * to store the resulting filename. If no substitution is needed, the
725  * current filename pattern string is directly returned, unless ForceUseBuf
726  * is enabled. */
727 static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
728   int I, J, PidLength, HostNameLength, FilenamePatLength;
729   const char *FilenamePat = lprofCurFilename.FilenamePat;
730 
731   if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
732     return 0;
733 
734   if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
735         lprofCurFilename.MergePoolSize ||
736         __llvm_profile_is_continuous_mode_enabled())) {
737     if (!ForceUseBuf)
738       return lprofCurFilename.FilenamePat;
739 
740     FilenamePatLength = strlen(lprofCurFilename.FilenamePat);
741     memcpy(FilenameBuf, lprofCurFilename.FilenamePat, FilenamePatLength);
742     FilenameBuf[FilenamePatLength] = '\0';
743     return FilenameBuf;
744   }
745 
746   PidLength = strlen(lprofCurFilename.PidChars);
747   HostNameLength = strlen(lprofCurFilename.Hostname);
748   /* Construct the new filename. */
749   for (I = 0, J = 0; FilenamePat[I]; ++I)
750     if (FilenamePat[I] == '%') {
751       if (FilenamePat[++I] == 'p') {
752         memcpy(FilenameBuf + J, lprofCurFilename.PidChars, PidLength);
753         J += PidLength;
754       } else if (FilenamePat[I] == 'h') {
755         memcpy(FilenameBuf + J, lprofCurFilename.Hostname, HostNameLength);
756         J += HostNameLength;
757       } else if (containsMergeSpecifier(FilenamePat, I)) {
758         char LoadModuleSignature[SIGLEN];
759         int S;
760         int ProfilePoolId = getpid() % lprofCurFilename.MergePoolSize;
761         S = snprintf(LoadModuleSignature, SIGLEN, "%" PRIu64 "_%d",
762                      lprofGetLoadModuleSignature(), ProfilePoolId);
763         if (S == -1 || S > SIGLEN)
764           S = SIGLEN;
765         memcpy(FilenameBuf + J, LoadModuleSignature, S);
766         J += S;
767         if (FilenamePat[I] != 'm')
768           I++;
769       }
770       /* Drop any unknown substitutions. */
771     } else
772       FilenameBuf[J++] = FilenamePat[I];
773   FilenameBuf[J] = 0;
774 
775   return FilenameBuf;
776 }
777 
778 /* Returns the pointer to the environment variable
779  * string. Returns null if the env var is not set. */
780 static const char *getFilenamePatFromEnv(void) {
781   const char *Filename = getenv("LLVM_PROFILE_FILE");
782   if (!Filename || !Filename[0])
783     return 0;
784   return Filename;
785 }
786 
787 COMPILER_RT_VISIBILITY
788 const char *__llvm_profile_get_path_prefix(void) {
789   int Length;
790   char *FilenameBuf, *Prefix;
791   const char *Filename, *PrefixEnd;
792 
793   if (lprofCurFilename.ProfilePathPrefix)
794     return lprofCurFilename.ProfilePathPrefix;
795 
796   Length = getCurFilenameLength();
797   FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
798   Filename = getCurFilename(FilenameBuf, 0);
799   if (!Filename)
800     return "\0";
801 
802   PrefixEnd = lprofFindLastDirSeparator(Filename);
803   if (!PrefixEnd)
804     return "\0";
805 
806   Length = PrefixEnd - Filename + 1;
807   Prefix = (char *)malloc(Length + 1);
808   if (!Prefix) {
809     PROF_ERR("Failed to %s\n", "allocate memory.");
810     return "\0";
811   }
812   memcpy(Prefix, Filename, Length);
813   Prefix[Length] = '\0';
814   lprofCurFilename.ProfilePathPrefix = Prefix;
815   return Prefix;
816 }
817 
818 COMPILER_RT_VISIBILITY
819 const char *__llvm_profile_get_filename(void) {
820   int Length;
821   char *FilenameBuf;
822   const char *Filename;
823 
824   Length = getCurFilenameLength();
825   FilenameBuf = (char *)malloc(Length + 1);
826   if (!FilenameBuf) {
827     PROF_ERR("Failed to %s\n", "allocate memory.");
828     return "\0";
829   }
830   Filename = getCurFilename(FilenameBuf, 1);
831   if (!Filename)
832     return "\0";
833 
834   return FilenameBuf;
835 }
836 
837 /* This method is invoked by the runtime initialization hook
838  * InstrProfilingRuntime.o if it is linked in. Both user specified
839  * profile path via -fprofile-instr-generate= and LLVM_PROFILE_FILE
840  * environment variable can override this default value. */
841 COMPILER_RT_VISIBILITY
842 void __llvm_profile_initialize_file(void) {
843   const char *EnvFilenamePat;
844   const char *SelectedPat = NULL;
845   ProfileNameSpecifier PNS = PNS_unknown;
846   int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR[0] != 0);
847 
848   EnvFilenamePat = getFilenamePatFromEnv();
849   if (EnvFilenamePat) {
850     /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
851        at the  moment when __llvm_profile_write_file() gets executed. */
852     parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
853     return;
854   } else if (hasCommandLineOverrider) {
855     SelectedPat = INSTR_PROF_PROFILE_NAME_VAR;
856     PNS = PNS_command_line;
857   } else {
858     SelectedPat = NULL;
859     PNS = PNS_default;
860   }
861 
862   parseAndSetFilename(SelectedPat, PNS, 0);
863 }
864 
865 /* This API is directly called by the user application code. It has the
866  * highest precedence compared with LLVM_PROFILE_FILE environment variable
867  * and command line option -fprofile-instr-generate=<profile_name>.
868  */
869 COMPILER_RT_VISIBILITY
870 void __llvm_profile_set_filename(const char *FilenamePat) {
871   if (__llvm_profile_is_continuous_mode_enabled())
872     return;
873   parseAndSetFilename(FilenamePat, PNS_runtime_api, 1);
874 }
875 
876 /* The public API for writing profile data into the file with name
877  * set by previous calls to __llvm_profile_set_filename or
878  * __llvm_profile_override_default_filename or
879  * __llvm_profile_initialize_file. */
880 COMPILER_RT_VISIBILITY
881 int __llvm_profile_write_file(void) {
882   int rc, Length;
883   const char *Filename;
884   char *FilenameBuf;
885   int PDeathSig = 0;
886 
887   if (lprofProfileDumped() || __llvm_profile_is_continuous_mode_enabled()) {
888     PROF_NOTE("Profile data not written to file: %s.\n", "already written");
889     return 0;
890   }
891 
892   Length = getCurFilenameLength();
893   FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
894   Filename = getCurFilename(FilenameBuf, 0);
895 
896   /* Check the filename. */
897   if (!Filename) {
898     PROF_ERR("Failed to write file : %s\n", "Filename not set");
899     return -1;
900   }
901 
902   /* Check if there is llvm/runtime version mismatch.  */
903   if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
904     PROF_ERR("Runtime and instrumentation version mismatch : "
905              "expected %d, but get %d\n",
906              INSTR_PROF_RAW_VERSION,
907              (int)GET_VERSION(__llvm_profile_get_version()));
908     return -1;
909   }
910 
911   // Temporarily suspend getting SIGKILL when the parent exits.
912   PDeathSig = lprofSuspendSigKill();
913 
914   /* Write profile data to the file. */
915   rc = writeFile(Filename);
916   if (rc)
917     PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
918 
919   // Restore SIGKILL.
920   if (PDeathSig == 1)
921     lprofRestoreSigKill();
922 
923   return rc;
924 }
925 
926 COMPILER_RT_VISIBILITY
927 int __llvm_profile_dump(void) {
928   if (!doMerging())
929     PROF_WARN("Later invocation of __llvm_profile_dump can lead to clobbering "
930               " of previously dumped profile data : %s. Either use %%m "
931               "in profile name or change profile name before dumping.\n",
932               "online profile merging is not on");
933   int rc = __llvm_profile_write_file();
934   lprofSetProfileDumped();
935   return rc;
936 }
937 
938 /* Order file data will be saved in a file with suffx .order. */
939 static const char *OrderFileSuffix = ".order";
940 
941 COMPILER_RT_VISIBILITY
942 int __llvm_orderfile_write_file(void) {
943   int rc, Length, LengthBeforeAppend, SuffixLength;
944   const char *Filename;
945   char *FilenameBuf;
946   int PDeathSig = 0;
947 
948   SuffixLength = strlen(OrderFileSuffix);
949   Length = getCurFilenameLength() + SuffixLength;
950   FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
951   Filename = getCurFilename(FilenameBuf, 1);
952 
953   /* Check the filename. */
954   if (!Filename) {
955     PROF_ERR("Failed to write file : %s\n", "Filename not set");
956     return -1;
957   }
958 
959   /* Append order file suffix */
960   LengthBeforeAppend = strlen(Filename);
961   memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength);
962   FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0';
963 
964   /* Check if there is llvm/runtime version mismatch.  */
965   if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
966     PROF_ERR("Runtime and instrumentation version mismatch : "
967              "expected %d, but get %d\n",
968              INSTR_PROF_RAW_VERSION,
969              (int)GET_VERSION(__llvm_profile_get_version()));
970     return -1;
971   }
972 
973   // Temporarily suspend getting SIGKILL when the parent exits.
974   PDeathSig = lprofSuspendSigKill();
975 
976   /* Write order data to the file. */
977   rc = writeOrderFile(Filename);
978   if (rc)
979     PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
980 
981   // Restore SIGKILL.
982   if (PDeathSig == 1)
983     lprofRestoreSigKill();
984 
985   return rc;
986 }
987 
988 COMPILER_RT_VISIBILITY
989 int __llvm_orderfile_dump(void) {
990   int rc = __llvm_orderfile_write_file();
991   return rc;
992 }
993 
994 static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }
995 
996 COMPILER_RT_VISIBILITY
997 int __llvm_profile_register_write_file_atexit(void) {
998   static int HasBeenRegistered = 0;
999 
1000   if (HasBeenRegistered)
1001     return 0;
1002 
1003   lprofSetupValueProfiler();
1004 
1005   HasBeenRegistered = 1;
1006   return atexit(writeFileWithoutReturn);
1007 }
1008 
1009 #endif
1010