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