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   int Fileno = fileno(File);
642 
643   /* Determine how much padding is needed before/after the counters and after
644    * the names. */
645   uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
646       PaddingBytesAfterNames;
647   __llvm_profile_get_padding_sizes_for_counters(
648       DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
649       &PaddingBytesAfterCounters, &PaddingBytesAfterNames);
650 
651   uint64_t PageAlignedCountersLength =
652       (CountersSize * sizeof(uint64_t)) + PaddingBytesAfterCounters;
653   uint64_t FileOffsetToCounters =
654       CurrentFileOffset + sizeof(__llvm_profile_header) +
655       (DataSize * sizeof(__llvm_profile_data)) + PaddingBytesBeforeCounters;
656 
657   uint64_t *CounterMmap = (uint64_t *)mmap(
658       (void *)CountersBegin, PageAlignedCountersLength, PROT_READ | PROT_WRITE,
659       MAP_FIXED | MAP_SHARED, Fileno, FileOffsetToCounters);
660   if (CounterMmap != CountersBegin) {
661     PROF_ERR(
662         "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
663         "  - CountersBegin: %p\n"
664         "  - PageAlignedCountersLength: %" PRIu64 "\n"
665         "  - Fileno: %d\n"
666         "  - FileOffsetToCounters: %" PRIu64 "\n",
667         strerror(errno), CountersBegin, PageAlignedCountersLength, Fileno,
668         FileOffsetToCounters);
669   }
670 
671   if (ProfileRequiresUnlock)
672     unlockProfile(&ProfileRequiresUnlock, File);
673 #endif // defined(__Fuchsia__) || defined(_WIN32)
674 }
675 
676 static const char *DefaultProfileName = "default.profraw";
677 static void resetFilenameToDefault(void) {
678   if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
679     free((void *)lprofCurFilename.FilenamePat);
680   }
681   memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
682   lprofCurFilename.FilenamePat = DefaultProfileName;
683   lprofCurFilename.PNS = PNS_default;
684 }
685 
686 static unsigned getMergePoolSize(const char *FilenamePat, int *I) {
687   unsigned J = 0, Num = 0;
688   for (;; ++J) {
689     char C = FilenamePat[*I + J];
690     if (C == 'm') {
691       *I += J;
692       return Num ? Num : 1;
693     }
694     if (C < '0' || C > '9')
695       break;
696     Num = Num * 10 + C - '0';
697 
698     /* If FilenamePat[*I+J] is between '0' and '9', the next byte is guaranteed
699      * to be in-bound as the string is null terminated. */
700   }
701   return 0;
702 }
703 
704 /* Assert that Idx does index past a string null terminator. Return the
705  * result of the check. */
706 static int checkBounds(int Idx, int Strlen) {
707   assert(Idx <= Strlen && "Indexing past string null terminator");
708   return Idx <= Strlen;
709 }
710 
711 /* Parses the pattern string \p FilenamePat and stores the result to
712  * lprofcurFilename structure. */
713 static int parseFilenamePattern(const char *FilenamePat,
714                                 unsigned CopyFilenamePat) {
715   int NumPids = 0, NumHosts = 0, I;
716   char *PidChars = &lprofCurFilename.PidChars[0];
717   char *Hostname = &lprofCurFilename.Hostname[0];
718   int MergingEnabled = 0;
719   int FilenamePatLen = strlen(FilenamePat);
720 
721   /* Clean up cached prefix and filename.  */
722   if (lprofCurFilename.ProfilePathPrefix)
723     free((void *)lprofCurFilename.ProfilePathPrefix);
724 
725   if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
726     free((void *)lprofCurFilename.FilenamePat);
727   }
728 
729   memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
730 
731   if (!CopyFilenamePat)
732     lprofCurFilename.FilenamePat = FilenamePat;
733   else {
734     lprofCurFilename.FilenamePat = strdup(FilenamePat);
735     lprofCurFilename.OwnsFilenamePat = 1;
736   }
737   /* Check the filename for "%p", which indicates a pid-substitution. */
738   for (I = 0; checkBounds(I, FilenamePatLen) && FilenamePat[I]; ++I) {
739     if (FilenamePat[I] == '%') {
740       ++I; /* Advance to the next character. */
741       if (!checkBounds(I, FilenamePatLen))
742         break;
743       if (FilenamePat[I] == 'p') {
744         if (!NumPids++) {
745           if (snprintf(PidChars, MAX_PID_SIZE, "%ld", (long)getpid()) <= 0) {
746             PROF_WARN("Unable to get pid for filename pattern %s. Using the "
747                       "default name.",
748                       FilenamePat);
749             return -1;
750           }
751         }
752       } else if (FilenamePat[I] == 'h') {
753         if (!NumHosts++)
754           if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)) {
755             PROF_WARN("Unable to get hostname for filename pattern %s. Using "
756                       "the default name.",
757                       FilenamePat);
758             return -1;
759           }
760       } else if (FilenamePat[I] == 't') {
761         lprofCurFilename.TmpDir = getenv("TMPDIR");
762         if (!lprofCurFilename.TmpDir) {
763           PROF_WARN("Unable to get the TMPDIR environment variable, referenced "
764                     "in %s. Using the default path.",
765                     FilenamePat);
766           return -1;
767         }
768       } else if (FilenamePat[I] == 'c') {
769         if (__llvm_profile_is_continuous_mode_enabled()) {
770           PROF_WARN("%%c specifier can only be specified once in %s.\n",
771                     FilenamePat);
772           return -1;
773         }
774 
775         __llvm_profile_set_page_size(getpagesize());
776         __llvm_profile_enable_continuous_mode();
777       } else {
778         unsigned MergePoolSize = getMergePoolSize(FilenamePat, &I);
779         if (!MergePoolSize)
780           continue;
781         if (MergingEnabled) {
782           PROF_WARN("%%m specifier can only be specified once in %s.\n",
783                     FilenamePat);
784           return -1;
785         }
786         MergingEnabled = 1;
787         lprofCurFilename.MergePoolSize = MergePoolSize;
788       }
789     }
790   }
791 
792   lprofCurFilename.NumPids = NumPids;
793   lprofCurFilename.NumHosts = NumHosts;
794   return 0;
795 }
796 
797 static void parseAndSetFilename(const char *FilenamePat,
798                                 ProfileNameSpecifier PNS,
799                                 unsigned CopyFilenamePat) {
800 
801   const char *OldFilenamePat = lprofCurFilename.FilenamePat;
802   ProfileNameSpecifier OldPNS = lprofCurFilename.PNS;
803 
804   /* The old profile name specifier takes precedence over the old one. */
805   if (PNS < OldPNS)
806     return;
807 
808   if (!FilenamePat)
809     FilenamePat = DefaultProfileName;
810 
811   if (OldFilenamePat && !strcmp(OldFilenamePat, FilenamePat)) {
812     lprofCurFilename.PNS = PNS;
813     return;
814   }
815 
816   /* When PNS >= OldPNS, the last one wins. */
817   if (!FilenamePat || parseFilenamePattern(FilenamePat, CopyFilenamePat))
818     resetFilenameToDefault();
819   lprofCurFilename.PNS = PNS;
820 
821   if (!OldFilenamePat) {
822     if (getenv("LLVM_PROFILE_VERBOSE"))
823       PROF_NOTE("Set profile file path to \"%s\" via %s.\n",
824                 lprofCurFilename.FilenamePat, getPNSStr(PNS));
825   } else {
826     if (getenv("LLVM_PROFILE_VERBOSE"))
827       PROF_NOTE("Override old profile path \"%s\" via %s to \"%s\" via %s.\n",
828                 OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat,
829                 getPNSStr(PNS));
830   }
831 
832   truncateCurrentFile();
833   if (__llvm_profile_is_continuous_mode_enabled()) {
834     if (lprofRuntimeCounterRelocation())
835       relocateCounters();
836     else
837       initializeProfileForContinuousMode();
838   }
839 }
840 
841 /* Return buffer length that is required to store the current profile
842  * filename with PID and hostname substitutions. */
843 /* The length to hold uint64_t followed by 3 digits pool id including '_' */
844 #define SIGLEN 24
845 static int getCurFilenameLength() {
846   int Len;
847   if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
848     return 0;
849 
850   if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
851         lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize))
852     return strlen(lprofCurFilename.FilenamePat);
853 
854   Len = strlen(lprofCurFilename.FilenamePat) +
855         lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
856         lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2) +
857         (lprofCurFilename.TmpDir ? (strlen(lprofCurFilename.TmpDir) - 1) : 0);
858   if (lprofCurFilename.MergePoolSize)
859     Len += SIGLEN;
860   return Len;
861 }
862 
863 /* Return the pointer to the current profile file name (after substituting
864  * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer
865  * to store the resulting filename. If no substitution is needed, the
866  * current filename pattern string is directly returned, unless ForceUseBuf
867  * is enabled. */
868 static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
869   int I, J, PidLength, HostNameLength, TmpDirLength, FilenamePatLength;
870   const char *FilenamePat = lprofCurFilename.FilenamePat;
871 
872   if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
873     return 0;
874 
875   if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
876         lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize ||
877         __llvm_profile_is_continuous_mode_enabled())) {
878     if (!ForceUseBuf)
879       return lprofCurFilename.FilenamePat;
880 
881     FilenamePatLength = strlen(lprofCurFilename.FilenamePat);
882     memcpy(FilenameBuf, lprofCurFilename.FilenamePat, FilenamePatLength);
883     FilenameBuf[FilenamePatLength] = '\0';
884     return FilenameBuf;
885   }
886 
887   PidLength = strlen(lprofCurFilename.PidChars);
888   HostNameLength = strlen(lprofCurFilename.Hostname);
889   TmpDirLength = lprofCurFilename.TmpDir ? strlen(lprofCurFilename.TmpDir) : 0;
890   /* Construct the new filename. */
891   for (I = 0, J = 0; FilenamePat[I]; ++I)
892     if (FilenamePat[I] == '%') {
893       if (FilenamePat[++I] == 'p') {
894         memcpy(FilenameBuf + J, lprofCurFilename.PidChars, PidLength);
895         J += PidLength;
896       } else if (FilenamePat[I] == 'h') {
897         memcpy(FilenameBuf + J, lprofCurFilename.Hostname, HostNameLength);
898         J += HostNameLength;
899       } else if (FilenamePat[I] == 't') {
900         memcpy(FilenameBuf + J, lprofCurFilename.TmpDir, TmpDirLength);
901         FilenameBuf[J + TmpDirLength] = DIR_SEPARATOR;
902         J += TmpDirLength + 1;
903       } else {
904         if (!getMergePoolSize(FilenamePat, &I))
905           continue;
906         char LoadModuleSignature[SIGLEN + 1];
907         int S;
908         int ProfilePoolId = getpid() % lprofCurFilename.MergePoolSize;
909         S = snprintf(LoadModuleSignature, SIGLEN + 1, "%" PRIu64 "_%d",
910                      lprofGetLoadModuleSignature(), ProfilePoolId);
911         if (S == -1 || S > SIGLEN)
912           S = SIGLEN;
913         memcpy(FilenameBuf + J, LoadModuleSignature, S);
914         J += S;
915       }
916       /* Drop any unknown substitutions. */
917     } else
918       FilenameBuf[J++] = FilenamePat[I];
919   FilenameBuf[J] = 0;
920 
921   return FilenameBuf;
922 }
923 
924 /* Returns the pointer to the environment variable
925  * string. Returns null if the env var is not set. */
926 static const char *getFilenamePatFromEnv(void) {
927   const char *Filename = getenv("LLVM_PROFILE_FILE");
928   if (!Filename || !Filename[0])
929     return 0;
930   return Filename;
931 }
932 
933 COMPILER_RT_VISIBILITY
934 const char *__llvm_profile_get_path_prefix(void) {
935   int Length;
936   char *FilenameBuf, *Prefix;
937   const char *Filename, *PrefixEnd;
938 
939   if (lprofCurFilename.ProfilePathPrefix)
940     return lprofCurFilename.ProfilePathPrefix;
941 
942   Length = getCurFilenameLength();
943   FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
944   Filename = getCurFilename(FilenameBuf, 0);
945   if (!Filename)
946     return "\0";
947 
948   PrefixEnd = lprofFindLastDirSeparator(Filename);
949   if (!PrefixEnd)
950     return "\0";
951 
952   Length = PrefixEnd - Filename + 1;
953   Prefix = (char *)malloc(Length + 1);
954   if (!Prefix) {
955     PROF_ERR("Failed to %s\n", "allocate memory.");
956     return "\0";
957   }
958   memcpy(Prefix, Filename, Length);
959   Prefix[Length] = '\0';
960   lprofCurFilename.ProfilePathPrefix = Prefix;
961   return Prefix;
962 }
963 
964 COMPILER_RT_VISIBILITY
965 const char *__llvm_profile_get_filename(void) {
966   int Length;
967   char *FilenameBuf;
968   const char *Filename;
969 
970   Length = getCurFilenameLength();
971   FilenameBuf = (char *)malloc(Length + 1);
972   if (!FilenameBuf) {
973     PROF_ERR("Failed to %s\n", "allocate memory.");
974     return "\0";
975   }
976   Filename = getCurFilename(FilenameBuf, 1);
977   if (!Filename)
978     return "\0";
979 
980   return FilenameBuf;
981 }
982 
983 /* This API initializes the file handling, both user specified
984  * profile path via -fprofile-instr-generate= and LLVM_PROFILE_FILE
985  * environment variable can override this default value.
986  */
987 COMPILER_RT_VISIBILITY
988 void __llvm_profile_initialize_file(void) {
989   const char *EnvFilenamePat;
990   const char *SelectedPat = NULL;
991   ProfileNameSpecifier PNS = PNS_unknown;
992   int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR[0] != 0);
993 
994   if (__llvm_profile_counter_bias != -1)
995     lprofSetRuntimeCounterRelocation(1);
996 
997   EnvFilenamePat = getFilenamePatFromEnv();
998   if (EnvFilenamePat) {
999     /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
1000        at the  moment when __llvm_profile_write_file() gets executed. */
1001     parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
1002     return;
1003   } else if (hasCommandLineOverrider) {
1004     SelectedPat = INSTR_PROF_PROFILE_NAME_VAR;
1005     PNS = PNS_command_line;
1006   } else {
1007     SelectedPat = NULL;
1008     PNS = PNS_default;
1009   }
1010 
1011   parseAndSetFilename(SelectedPat, PNS, 0);
1012 }
1013 
1014 /* This method is invoked by the runtime initialization hook
1015  * InstrProfilingRuntime.o if it is linked in.
1016  */
1017 COMPILER_RT_VISIBILITY
1018 void __llvm_profile_initialize(void) {
1019   __llvm_profile_initialize_file();
1020   if (!__llvm_profile_is_continuous_mode_enabled())
1021     __llvm_profile_register_write_file_atexit();
1022 }
1023 
1024 /* This API is directly called by the user application code. It has the
1025  * highest precedence compared with LLVM_PROFILE_FILE environment variable
1026  * and command line option -fprofile-instr-generate=<profile_name>.
1027  */
1028 COMPILER_RT_VISIBILITY
1029 void __llvm_profile_set_filename(const char *FilenamePat) {
1030   if (__llvm_profile_is_continuous_mode_enabled())
1031     return;
1032   parseAndSetFilename(FilenamePat, PNS_runtime_api, 1);
1033 }
1034 
1035 /* The public API for writing profile data into the file with name
1036  * set by previous calls to __llvm_profile_set_filename or
1037  * __llvm_profile_override_default_filename or
1038  * __llvm_profile_initialize_file. */
1039 COMPILER_RT_VISIBILITY
1040 int __llvm_profile_write_file(void) {
1041   int rc, Length;
1042   const char *Filename;
1043   char *FilenameBuf;
1044   int PDeathSig = 0;
1045 
1046   if (lprofProfileDumped() || __llvm_profile_is_continuous_mode_enabled()) {
1047     PROF_NOTE("Profile data not written to file: %s.\n", "already written");
1048     return 0;
1049   }
1050 
1051   Length = getCurFilenameLength();
1052   FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
1053   Filename = getCurFilename(FilenameBuf, 0);
1054 
1055   /* Check the filename. */
1056   if (!Filename) {
1057     PROF_ERR("Failed to write file : %s\n", "Filename not set");
1058     return -1;
1059   }
1060 
1061   /* Check if there is llvm/runtime version mismatch.  */
1062   if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
1063     PROF_ERR("Runtime and instrumentation version mismatch : "
1064              "expected %d, but get %d\n",
1065              INSTR_PROF_RAW_VERSION,
1066              (int)GET_VERSION(__llvm_profile_get_version()));
1067     return -1;
1068   }
1069 
1070   // Temporarily suspend getting SIGKILL when the parent exits.
1071   PDeathSig = lprofSuspendSigKill();
1072 
1073   /* Write profile data to the file. */
1074   rc = writeFile(Filename);
1075   if (rc)
1076     PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
1077 
1078   // Restore SIGKILL.
1079   if (PDeathSig == 1)
1080     lprofRestoreSigKill();
1081 
1082   return rc;
1083 }
1084 
1085 COMPILER_RT_VISIBILITY
1086 int __llvm_profile_dump(void) {
1087   if (!doMerging())
1088     PROF_WARN("Later invocation of __llvm_profile_dump can lead to clobbering "
1089               " of previously dumped profile data : %s. Either use %%m "
1090               "in profile name or change profile name before dumping.\n",
1091               "online profile merging is not on");
1092   int rc = __llvm_profile_write_file();
1093   lprofSetProfileDumped(1);
1094   return rc;
1095 }
1096 
1097 /* Order file data will be saved in a file with suffx .order. */
1098 static const char *OrderFileSuffix = ".order";
1099 
1100 COMPILER_RT_VISIBILITY
1101 int __llvm_orderfile_write_file(void) {
1102   int rc, Length, LengthBeforeAppend, SuffixLength;
1103   const char *Filename;
1104   char *FilenameBuf;
1105   int PDeathSig = 0;
1106 
1107   SuffixLength = strlen(OrderFileSuffix);
1108   Length = getCurFilenameLength() + SuffixLength;
1109   FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
1110   Filename = getCurFilename(FilenameBuf, 1);
1111 
1112   /* Check the filename. */
1113   if (!Filename) {
1114     PROF_ERR("Failed to write file : %s\n", "Filename not set");
1115     return -1;
1116   }
1117 
1118   /* Append order file suffix */
1119   LengthBeforeAppend = strlen(Filename);
1120   memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength);
1121   FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0';
1122 
1123   /* Check if there is llvm/runtime version mismatch.  */
1124   if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
1125     PROF_ERR("Runtime and instrumentation version mismatch : "
1126              "expected %d, but get %d\n",
1127              INSTR_PROF_RAW_VERSION,
1128              (int)GET_VERSION(__llvm_profile_get_version()));
1129     return -1;
1130   }
1131 
1132   // Temporarily suspend getting SIGKILL when the parent exits.
1133   PDeathSig = lprofSuspendSigKill();
1134 
1135   /* Write order data to the file. */
1136   rc = writeOrderFile(Filename);
1137   if (rc)
1138     PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
1139 
1140   // Restore SIGKILL.
1141   if (PDeathSig == 1)
1142     lprofRestoreSigKill();
1143 
1144   return rc;
1145 }
1146 
1147 COMPILER_RT_VISIBILITY
1148 int __llvm_orderfile_dump(void) {
1149   int rc = __llvm_orderfile_write_file();
1150   return rc;
1151 }
1152 
1153 static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }
1154 
1155 COMPILER_RT_VISIBILITY
1156 int __llvm_profile_register_write_file_atexit(void) {
1157   static int HasBeenRegistered = 0;
1158 
1159   if (HasBeenRegistered)
1160     return 0;
1161 
1162   lprofSetupValueProfiler();
1163 
1164   HasBeenRegistered = 1;
1165   return atexit(writeFileWithoutReturn);
1166 }
1167 
1168 #endif
1169