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 *TmpDir;
76   char Hostname[COMPILER_RT_MAX_HOSTLEN];
77   unsigned NumPids;
78   unsigned NumHosts;
79   /* When in-process merging is enabled, this parameter specifies
80    * the total number of profile data files shared by all the processes
81    * spawned from the same binary. By default the value is 1. If merging
82    * is not enabled, its value should be 0. This parameter is specified
83    * by the %[0-9]m specifier. For instance %2m enables merging using
84    * 2 profile data files. %1m is equivalent to %m. Also %m specifier
85    * can only appear once at the end of the name pattern. */
86   unsigned MergePoolSize;
87   ProfileNameSpecifier PNS;
88 } lprofFilename;
89 
90 static lprofFilename lprofCurFilename = {0,   0, 0, {0}, NULL,
91                                          {0}, 0, 0, 0,   PNS_unknown};
92 
93 static int ProfileMergeRequested = 0;
94 static int isProfileMergeRequested() { return ProfileMergeRequested; }
95 static void setProfileMergeRequested(int EnableMerge) {
96   ProfileMergeRequested = EnableMerge;
97 }
98 
99 static FILE *ProfileFile = NULL;
100 static FILE *getProfileFile() { return ProfileFile; }
101 static void setProfileFile(FILE *File) { ProfileFile = File; }
102 
103 COMPILER_RT_VISIBILITY void __llvm_profile_set_file_object(FILE *File,
104                                                            int EnableMerge) {
105   if (__llvm_profile_is_continuous_mode_enabled()) {
106     PROF_WARN("__llvm_profile_set_file_object(fd=%d) not supported, because "
107               "continuous sync mode (%%c) is enabled",
108               fileno(File));
109     return;
110   }
111   setProfileFile(File);
112   setProfileMergeRequested(EnableMerge);
113 }
114 
115 static int getCurFilenameLength();
116 static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf);
117 static unsigned doMerging() {
118   return lprofCurFilename.MergePoolSize || isProfileMergeRequested();
119 }
120 
121 /* Return 1 if there is an error, otherwise return  0.  */
122 static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
123                            uint32_t NumIOVecs) {
124   uint32_t I;
125   FILE *File = (FILE *)This->WriterCtx;
126   char Zeroes[sizeof(uint64_t)] = {0};
127   for (I = 0; I < NumIOVecs; I++) {
128     if (IOVecs[I].Data) {
129       if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
130           IOVecs[I].NumElm)
131         return 1;
132     } else if (IOVecs[I].UseZeroPadding) {
133       size_t BytesToWrite = IOVecs[I].ElmSize * IOVecs[I].NumElm;
134       while (BytesToWrite > 0) {
135         size_t PartialWriteLen =
136             (sizeof(uint64_t) > BytesToWrite) ? BytesToWrite : sizeof(uint64_t);
137         if (fwrite(Zeroes, sizeof(uint8_t), PartialWriteLen, File) !=
138             PartialWriteLen) {
139           return 1;
140         }
141         BytesToWrite -= PartialWriteLen;
142       }
143     } else {
144       if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR) == -1)
145         return 1;
146     }
147   }
148   return 0;
149 }
150 
151 /* TODO: make buffer size controllable by an internal option, and compiler can pass the size
152    to runtime via a variable. */
153 static uint32_t orderFileWriter(FILE *File, const uint32_t *DataStart) {
154   if (fwrite(DataStart, sizeof(uint32_t), INSTR_ORDER_FILE_BUFFER_SIZE, File) !=
155       INSTR_ORDER_FILE_BUFFER_SIZE)
156     return 1;
157   return 0;
158 }
159 
160 static void initFileWriter(ProfDataWriter *This, FILE *File) {
161   This->Write = fileWriter;
162   This->WriterCtx = File;
163 }
164 
165 COMPILER_RT_VISIBILITY ProfBufferIO *
166 lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
167   FreeHook = &free;
168   DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
169   VPBufferSize = BufferSz;
170   ProfDataWriter *fileWriter =
171       (ProfDataWriter *)calloc(sizeof(ProfDataWriter), 1);
172   initFileWriter(fileWriter, File);
173   ProfBufferIO *IO = lprofCreateBufferIO(fileWriter);
174   IO->OwnFileWriter = 1;
175   return IO;
176 }
177 
178 static void setupIOBuffer() {
179   const char *BufferSzStr = 0;
180   BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
181   if (BufferSzStr && BufferSzStr[0]) {
182     VPBufferSize = atoi(BufferSzStr);
183     DynamicBufferIOBuffer = (uint8_t *)calloc(VPBufferSize, 1);
184   }
185 }
186 
187 /* Get the size of the profile file. If there are any errors, print the
188  * message under the assumption that the profile is being read for merging
189  * purposes, and return -1. Otherwise return the file size in the inout param
190  * \p ProfileFileSize. */
191 static int getProfileFileSizeForMerging(FILE *ProfileFile,
192                                         uint64_t *ProfileFileSize) {
193   if (fseek(ProfileFile, 0L, SEEK_END) == -1) {
194     PROF_ERR("Unable to merge profile data, unable to get size: %s\n",
195              strerror(errno));
196     return -1;
197   }
198   *ProfileFileSize = ftell(ProfileFile);
199 
200   /* Restore file offset.  */
201   if (fseek(ProfileFile, 0L, SEEK_SET) == -1) {
202     PROF_ERR("Unable to merge profile data, unable to rewind: %s\n",
203              strerror(errno));
204     return -1;
205   }
206 
207   if (*ProfileFileSize > 0 &&
208       *ProfileFileSize < sizeof(__llvm_profile_header)) {
209     PROF_WARN("Unable to merge profile data: %s\n",
210               "source profile file is too small.");
211     return -1;
212   }
213   return 0;
214 }
215 
216 /* mmap() \p ProfileFile for profile merging purposes, assuming that an
217  * exclusive lock is held on the file and that \p ProfileFileSize is the
218  * length of the file. Return the mmap'd buffer in the inout variable
219  * \p ProfileBuffer. Returns -1 on failure. On success, the caller is
220  * responsible for unmapping the mmap'd buffer in \p ProfileBuffer. */
221 static int mmapProfileForMerging(FILE *ProfileFile, uint64_t ProfileFileSize,
222                                  char **ProfileBuffer) {
223   *ProfileBuffer = mmap(NULL, ProfileFileSize, PROT_READ, MAP_SHARED | MAP_FILE,
224                         fileno(ProfileFile), 0);
225   if (*ProfileBuffer == MAP_FAILED) {
226     PROF_ERR("Unable to merge profile data, mmap failed: %s\n",
227              strerror(errno));
228     return -1;
229   }
230 
231   if (__llvm_profile_check_compatibility(*ProfileBuffer, ProfileFileSize)) {
232     (void)munmap(*ProfileBuffer, ProfileFileSize);
233     PROF_WARN("Unable to merge profile data: %s\n",
234               "source profile file is not compatible.");
235     return -1;
236   }
237   return 0;
238 }
239 
240 /* Read profile data in \c ProfileFile and merge with in-memory
241    profile counters. Returns -1 if there is fatal error, otheriwse
242    0 is returned. Returning 0 does not mean merge is actually
243    performed. If merge is actually done, *MergeDone is set to 1.
244 */
245 static int doProfileMerging(FILE *ProfileFile, int *MergeDone) {
246   uint64_t ProfileFileSize;
247   char *ProfileBuffer;
248 
249   /* Get the size of the profile on disk. */
250   if (getProfileFileSizeForMerging(ProfileFile, &ProfileFileSize) == -1)
251     return -1;
252 
253   /* Nothing to merge.  */
254   if (!ProfileFileSize)
255     return 0;
256 
257   /* mmap() the profile and check that it is compatible with the data in
258    * the current image. */
259   if (mmapProfileForMerging(ProfileFile, ProfileFileSize, &ProfileBuffer) == -1)
260     return -1;
261 
262   /* Now start merging */
263   __llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize);
264 
265   // Truncate the file in case merging of value profile did not happend to
266   // prevent from leaving garbage data at the end of the profile file.
267   COMPILER_RT_FTRUNCATE(ProfileFile, __llvm_profile_get_size_for_buffer());
268 
269   (void)munmap(ProfileBuffer, ProfileFileSize);
270   *MergeDone = 1;
271 
272   return 0;
273 }
274 
275 /* Create the directory holding the file, if needed. */
276 static void createProfileDir(const char *Filename) {
277   size_t Length = strlen(Filename);
278   if (lprofFindFirstDirSeparator(Filename)) {
279     char *Copy = (char *)COMPILER_RT_ALLOCA(Length + 1);
280     strncpy(Copy, Filename, Length + 1);
281     __llvm_profile_recursive_mkdir(Copy);
282   }
283 }
284 
285 /* Open the profile data for merging. It opens the file in r+b mode with
286  * file locking.  If the file has content which is compatible with the
287  * current process, it also reads in the profile data in the file and merge
288  * it with in-memory counters. After the profile data is merged in memory,
289  * the original profile data is truncated and gets ready for the profile
290  * dumper. With profile merging enabled, each executable as well as any of
291  * its instrumented shared libraries dump profile data into their own data file.
292 */
293 static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
294   FILE *ProfileFile = NULL;
295   int rc;
296 
297   ProfileFile = getProfileFile();
298   if (ProfileFile) {
299     lprofLockFileHandle(ProfileFile);
300   } else {
301     createProfileDir(ProfileFileName);
302     ProfileFile = lprofOpenFileEx(ProfileFileName);
303   }
304   if (!ProfileFile)
305     return NULL;
306 
307   rc = doProfileMerging(ProfileFile, MergeDone);
308   if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)) ||
309       fseek(ProfileFile, 0L, SEEK_SET) == -1) {
310     PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName,
311              strerror(errno));
312     fclose(ProfileFile);
313     return NULL;
314   }
315   return ProfileFile;
316 }
317 
318 static FILE *getFileObject(const char *OutputName) {
319   FILE *File;
320   File = getProfileFile();
321   if (File != NULL) {
322     return File;
323   }
324 
325   return fopen(OutputName, "ab");
326 }
327 
328 /* Write profile data to file \c OutputName.  */
329 static int writeFile(const char *OutputName) {
330   int RetVal;
331   FILE *OutputFile;
332 
333   int MergeDone = 0;
334   VPMergeHook = &lprofMergeValueProfData;
335   if (doMerging())
336     OutputFile = openFileForMerging(OutputName, &MergeDone);
337   else
338     OutputFile = getFileObject(OutputName);
339 
340   if (!OutputFile)
341     return -1;
342 
343   FreeHook = &free;
344   setupIOBuffer();
345   ProfDataWriter fileWriter;
346   initFileWriter(&fileWriter, OutputFile);
347   RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
348 
349   if (OutputFile == getProfileFile()) {
350     fflush(OutputFile);
351     if (doMerging()) {
352       lprofUnlockFileHandle(OutputFile);
353     }
354   } else {
355     fclose(OutputFile);
356   }
357 
358   return RetVal;
359 }
360 
361 /* Write order data to file \c OutputName.  */
362 static int writeOrderFile(const char *OutputName) {
363   int RetVal;
364   FILE *OutputFile;
365 
366   OutputFile = fopen(OutputName, "w");
367 
368   if (!OutputFile) {
369     PROF_WARN("can't open file with mode ab: %s\n", OutputName);
370     return -1;
371   }
372 
373   FreeHook = &free;
374   setupIOBuffer();
375   const uint32_t *DataBegin = __llvm_profile_begin_orderfile();
376   RetVal = orderFileWriter(OutputFile, DataBegin);
377 
378   fclose(OutputFile);
379   return RetVal;
380 }
381 
382 #define LPROF_INIT_ONCE_ENV "__LLVM_PROFILE_RT_INIT_ONCE"
383 
384 static void truncateCurrentFile(void) {
385   const char *Filename;
386   char *FilenameBuf;
387   FILE *File;
388   int Length;
389 
390   Length = getCurFilenameLength();
391   FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
392   Filename = getCurFilename(FilenameBuf, 0);
393   if (!Filename)
394     return;
395 
396   /* Only create the profile directory and truncate an existing profile once.
397    * In continuous mode, this is necessary, as the profile is written-to by the
398    * runtime initializer. */
399   int initialized = getenv(LPROF_INIT_ONCE_ENV) != NULL;
400   if (initialized)
401     return;
402 #if defined(_WIN32)
403   _putenv(LPROF_INIT_ONCE_ENV "=" LPROF_INIT_ONCE_ENV);
404 #else
405   setenv(LPROF_INIT_ONCE_ENV, LPROF_INIT_ONCE_ENV, 1);
406 #endif
407 
408   /* Create the profile dir (even if online merging is enabled), so that
409    * the profile file can be set up if continuous mode is enabled. */
410   createProfileDir(Filename);
411 
412   /* By pass file truncation to allow online raw profile merging. */
413   if (lprofCurFilename.MergePoolSize)
414     return;
415 
416   /* Truncate the file.  Later we'll reopen and append. */
417   File = fopen(Filename, "w");
418   if (!File)
419     return;
420   fclose(File);
421 }
422 
423 #ifndef _MSC_VER
424 static void assertIsZero(int *i) {
425   if (*i)
426     PROF_WARN("Expected flag to be 0, but got: %d\n", *i);
427 }
428 #endif
429 
430 #if !defined(__Fuchsia__) && !defined(_WIN32)
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   unlockProfile(&ProfileRequiresUnlock, File);
672 #endif // defined(__Fuchsia__) || defined(_WIN32)
673 }
674 
675 static const char *DefaultProfileName = "default.profraw";
676 static void resetFilenameToDefault(void) {
677   if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
678     free((void *)lprofCurFilename.FilenamePat);
679   }
680   memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
681   lprofCurFilename.FilenamePat = DefaultProfileName;
682   lprofCurFilename.PNS = PNS_default;
683 }
684 
685 static unsigned getMergePoolSize(const char *FilenamePat, int *I) {
686   unsigned J = 0, Num = 0;
687   for (;; ++J) {
688     char C = FilenamePat[*I + J];
689     if (C == 'm') {
690       *I += J;
691       return Num ? Num : 1;
692     }
693     if (C < '0' || C > '9')
694       break;
695     Num = Num * 10 + C - '0';
696 
697     /* If FilenamePat[*I+J] is between '0' and '9', the next byte is guaranteed
698      * to be in-bound as the string is null terminated. */
699   }
700   return 0;
701 }
702 
703 /* Parses the pattern string \p FilenamePat and stores the result to
704  * lprofcurFilename structure. */
705 static int parseFilenamePattern(const char *FilenamePat,
706                                 unsigned CopyFilenamePat) {
707   int NumPids = 0, NumHosts = 0, I;
708   char *PidChars = &lprofCurFilename.PidChars[0];
709   char *Hostname = &lprofCurFilename.Hostname[0];
710   int MergingEnabled = 0;
711 
712   /* Clean up cached prefix and filename.  */
713   if (lprofCurFilename.ProfilePathPrefix)
714     free((void *)lprofCurFilename.ProfilePathPrefix);
715 
716   if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
717     free((void *)lprofCurFilename.FilenamePat);
718   }
719 
720   memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
721 
722   if (!CopyFilenamePat)
723     lprofCurFilename.FilenamePat = FilenamePat;
724   else {
725     lprofCurFilename.FilenamePat = strdup(FilenamePat);
726     lprofCurFilename.OwnsFilenamePat = 1;
727   }
728   /* Check the filename for "%p", which indicates a pid-substitution. */
729   for (I = 0; FilenamePat[I]; ++I)
730     if (FilenamePat[I] == '%') {
731       if (FilenamePat[++I] == 'p') {
732         if (!NumPids++) {
733           if (snprintf(PidChars, MAX_PID_SIZE, "%ld", (long)getpid()) <= 0) {
734             PROF_WARN("Unable to get pid for filename pattern %s. Using the "
735                       "default name.",
736                       FilenamePat);
737             return -1;
738           }
739         }
740       } else if (FilenamePat[I] == 'h') {
741         if (!NumHosts++)
742           if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)) {
743             PROF_WARN("Unable to get hostname for filename pattern %s. Using "
744                       "the default name.",
745                       FilenamePat);
746             return -1;
747           }
748       } else if (FilenamePat[I] == 't') {
749         lprofCurFilename.TmpDir = getenv("TMPDIR");
750         if (!lprofCurFilename.TmpDir) {
751           PROF_WARN("Unable to get the TMPDIR environment variable, referenced "
752                     "in %s. Using the default path.",
753                     FilenamePat);
754           return -1;
755         }
756       } else if (FilenamePat[I] == 'c') {
757         if (__llvm_profile_is_continuous_mode_enabled()) {
758           PROF_WARN("%%c specifier can only be specified once in %s.\n",
759                     FilenamePat);
760           return -1;
761         }
762 
763         __llvm_profile_set_page_size(getpagesize());
764         __llvm_profile_enable_continuous_mode();
765         I++; /* advance to 'c' */
766       } else {
767         unsigned MergePoolSize = getMergePoolSize(FilenamePat, &I);
768         if (!MergePoolSize)
769           continue;
770         if (MergingEnabled) {
771           PROF_WARN("%%m specifier can only be specified once in %s.\n",
772                     FilenamePat);
773           return -1;
774         }
775         MergingEnabled = 1;
776         lprofCurFilename.MergePoolSize = MergePoolSize;
777       }
778     }
779 
780   lprofCurFilename.NumPids = NumPids;
781   lprofCurFilename.NumHosts = NumHosts;
782   return 0;
783 }
784 
785 static void parseAndSetFilename(const char *FilenamePat,
786                                 ProfileNameSpecifier PNS,
787                                 unsigned CopyFilenamePat) {
788 
789   const char *OldFilenamePat = lprofCurFilename.FilenamePat;
790   ProfileNameSpecifier OldPNS = lprofCurFilename.PNS;
791 
792   /* The old profile name specifier takes precedence over the old one. */
793   if (PNS < OldPNS)
794     return;
795 
796   if (!FilenamePat)
797     FilenamePat = DefaultProfileName;
798 
799   if (OldFilenamePat && !strcmp(OldFilenamePat, FilenamePat)) {
800     lprofCurFilename.PNS = PNS;
801     return;
802   }
803 
804   /* When PNS >= OldPNS, the last one wins. */
805   if (!FilenamePat || parseFilenamePattern(FilenamePat, CopyFilenamePat))
806     resetFilenameToDefault();
807   lprofCurFilename.PNS = PNS;
808 
809   if (!OldFilenamePat) {
810     if (getenv("LLVM_PROFILE_VERBOSE"))
811       PROF_NOTE("Set profile file path to \"%s\" via %s.\n",
812                 lprofCurFilename.FilenamePat, getPNSStr(PNS));
813   } else {
814     if (getenv("LLVM_PROFILE_VERBOSE"))
815       PROF_NOTE("Override old profile path \"%s\" via %s to \"%s\" via %s.\n",
816                 OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat,
817                 getPNSStr(PNS));
818   }
819 
820   truncateCurrentFile();
821   if (__llvm_profile_is_continuous_mode_enabled()) {
822     if (lprofRuntimeCounterRelocation())
823       relocateCounters();
824     else
825       initializeProfileForContinuousMode();
826   }
827 }
828 
829 /* Return buffer length that is required to store the current profile
830  * filename with PID and hostname substitutions. */
831 /* The length to hold uint64_t followed by 3 digits pool id including '_' */
832 #define SIGLEN 24
833 static int getCurFilenameLength() {
834   int Len;
835   if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
836     return 0;
837 
838   if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
839         lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize))
840     return strlen(lprofCurFilename.FilenamePat);
841 
842   Len = strlen(lprofCurFilename.FilenamePat) +
843         lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
844         lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2) +
845         (lprofCurFilename.TmpDir ? (strlen(lprofCurFilename.TmpDir) - 1) : 0);
846   if (lprofCurFilename.MergePoolSize)
847     Len += SIGLEN;
848   return Len;
849 }
850 
851 /* Return the pointer to the current profile file name (after substituting
852  * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer
853  * to store the resulting filename. If no substitution is needed, the
854  * current filename pattern string is directly returned, unless ForceUseBuf
855  * is enabled. */
856 static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
857   int I, J, PidLength, HostNameLength, TmpDirLength, FilenamePatLength;
858   const char *FilenamePat = lprofCurFilename.FilenamePat;
859 
860   if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
861     return 0;
862 
863   if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
864         lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize ||
865         __llvm_profile_is_continuous_mode_enabled())) {
866     if (!ForceUseBuf)
867       return lprofCurFilename.FilenamePat;
868 
869     FilenamePatLength = strlen(lprofCurFilename.FilenamePat);
870     memcpy(FilenameBuf, lprofCurFilename.FilenamePat, FilenamePatLength);
871     FilenameBuf[FilenamePatLength] = '\0';
872     return FilenameBuf;
873   }
874 
875   PidLength = strlen(lprofCurFilename.PidChars);
876   HostNameLength = strlen(lprofCurFilename.Hostname);
877   TmpDirLength = lprofCurFilename.TmpDir ? strlen(lprofCurFilename.TmpDir) : 0;
878   /* Construct the new filename. */
879   for (I = 0, J = 0; FilenamePat[I]; ++I)
880     if (FilenamePat[I] == '%') {
881       if (FilenamePat[++I] == 'p') {
882         memcpy(FilenameBuf + J, lprofCurFilename.PidChars, PidLength);
883         J += PidLength;
884       } else if (FilenamePat[I] == 'h') {
885         memcpy(FilenameBuf + J, lprofCurFilename.Hostname, HostNameLength);
886         J += HostNameLength;
887       } else if (FilenamePat[I] == 't') {
888         memcpy(FilenameBuf + J, lprofCurFilename.TmpDir, TmpDirLength);
889         FilenameBuf[J + TmpDirLength] = DIR_SEPARATOR;
890         J += TmpDirLength + 1;
891       } else {
892         if (!getMergePoolSize(FilenamePat, &I))
893           continue;
894         char LoadModuleSignature[SIGLEN + 1];
895         int S;
896         int ProfilePoolId = getpid() % lprofCurFilename.MergePoolSize;
897         S = snprintf(LoadModuleSignature, SIGLEN + 1, "%" PRIu64 "_%d",
898                      lprofGetLoadModuleSignature(), ProfilePoolId);
899         if (S == -1 || S > SIGLEN)
900           S = SIGLEN;
901         memcpy(FilenameBuf + J, LoadModuleSignature, S);
902         J += S;
903       }
904       /* Drop any unknown substitutions. */
905     } else
906       FilenameBuf[J++] = FilenamePat[I];
907   FilenameBuf[J] = 0;
908 
909   return FilenameBuf;
910 }
911 
912 /* Returns the pointer to the environment variable
913  * string. Returns null if the env var is not set. */
914 static const char *getFilenamePatFromEnv(void) {
915   const char *Filename = getenv("LLVM_PROFILE_FILE");
916   if (!Filename || !Filename[0])
917     return 0;
918   return Filename;
919 }
920 
921 COMPILER_RT_VISIBILITY
922 const char *__llvm_profile_get_path_prefix(void) {
923   int Length;
924   char *FilenameBuf, *Prefix;
925   const char *Filename, *PrefixEnd;
926 
927   if (lprofCurFilename.ProfilePathPrefix)
928     return lprofCurFilename.ProfilePathPrefix;
929 
930   Length = getCurFilenameLength();
931   FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
932   Filename = getCurFilename(FilenameBuf, 0);
933   if (!Filename)
934     return "\0";
935 
936   PrefixEnd = lprofFindLastDirSeparator(Filename);
937   if (!PrefixEnd)
938     return "\0";
939 
940   Length = PrefixEnd - Filename + 1;
941   Prefix = (char *)malloc(Length + 1);
942   if (!Prefix) {
943     PROF_ERR("Failed to %s\n", "allocate memory.");
944     return "\0";
945   }
946   memcpy(Prefix, Filename, Length);
947   Prefix[Length] = '\0';
948   lprofCurFilename.ProfilePathPrefix = Prefix;
949   return Prefix;
950 }
951 
952 COMPILER_RT_VISIBILITY
953 const char *__llvm_profile_get_filename(void) {
954   int Length;
955   char *FilenameBuf;
956   const char *Filename;
957 
958   Length = getCurFilenameLength();
959   FilenameBuf = (char *)malloc(Length + 1);
960   if (!FilenameBuf) {
961     PROF_ERR("Failed to %s\n", "allocate memory.");
962     return "\0";
963   }
964   Filename = getCurFilename(FilenameBuf, 1);
965   if (!Filename)
966     return "\0";
967 
968   return FilenameBuf;
969 }
970 
971 /* This API initializes the file handling, both user specified
972  * profile path via -fprofile-instr-generate= and LLVM_PROFILE_FILE
973  * environment variable can override this default value.
974  */
975 COMPILER_RT_VISIBILITY
976 void __llvm_profile_initialize_file(void) {
977   const char *EnvFilenamePat;
978   const char *SelectedPat = NULL;
979   ProfileNameSpecifier PNS = PNS_unknown;
980   int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR[0] != 0);
981 
982   if (__llvm_profile_counter_bias != -1)
983     lprofSetRuntimeCounterRelocation(1);
984 
985   EnvFilenamePat = getFilenamePatFromEnv();
986   if (EnvFilenamePat) {
987     /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
988        at the  moment when __llvm_profile_write_file() gets executed. */
989     parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
990     return;
991   } else if (hasCommandLineOverrider) {
992     SelectedPat = INSTR_PROF_PROFILE_NAME_VAR;
993     PNS = PNS_command_line;
994   } else {
995     SelectedPat = NULL;
996     PNS = PNS_default;
997   }
998 
999   parseAndSetFilename(SelectedPat, PNS, 0);
1000 }
1001 
1002 /* This method is invoked by the runtime initialization hook
1003  * InstrProfilingRuntime.o if it is linked in.
1004  */
1005 COMPILER_RT_VISIBILITY
1006 void __llvm_profile_initialize(void) {
1007   __llvm_profile_initialize_file();
1008   if (!__llvm_profile_is_continuous_mode_enabled())
1009     __llvm_profile_register_write_file_atexit();
1010 }
1011 
1012 /* This API is directly called by the user application code. It has the
1013  * highest precedence compared with LLVM_PROFILE_FILE environment variable
1014  * and command line option -fprofile-instr-generate=<profile_name>.
1015  */
1016 COMPILER_RT_VISIBILITY
1017 void __llvm_profile_set_filename(const char *FilenamePat) {
1018   if (__llvm_profile_is_continuous_mode_enabled())
1019     return;
1020   parseAndSetFilename(FilenamePat, PNS_runtime_api, 1);
1021 }
1022 
1023 /* The public API for writing profile data into the file with name
1024  * set by previous calls to __llvm_profile_set_filename or
1025  * __llvm_profile_override_default_filename or
1026  * __llvm_profile_initialize_file. */
1027 COMPILER_RT_VISIBILITY
1028 int __llvm_profile_write_file(void) {
1029   int rc, Length;
1030   const char *Filename;
1031   char *FilenameBuf;
1032   int PDeathSig = 0;
1033 
1034   if (lprofProfileDumped() || __llvm_profile_is_continuous_mode_enabled()) {
1035     PROF_NOTE("Profile data not written to file: %s.\n", "already written");
1036     return 0;
1037   }
1038 
1039   Length = getCurFilenameLength();
1040   FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
1041   Filename = getCurFilename(FilenameBuf, 0);
1042 
1043   /* Check the filename. */
1044   if (!Filename) {
1045     PROF_ERR("Failed to write file : %s\n", "Filename not set");
1046     return -1;
1047   }
1048 
1049   /* Check if there is llvm/runtime version mismatch.  */
1050   if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
1051     PROF_ERR("Runtime and instrumentation version mismatch : "
1052              "expected %d, but get %d\n",
1053              INSTR_PROF_RAW_VERSION,
1054              (int)GET_VERSION(__llvm_profile_get_version()));
1055     return -1;
1056   }
1057 
1058   // Temporarily suspend getting SIGKILL when the parent exits.
1059   PDeathSig = lprofSuspendSigKill();
1060 
1061   /* Write profile data to the file. */
1062   rc = writeFile(Filename);
1063   if (rc)
1064     PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
1065 
1066   // Restore SIGKILL.
1067   if (PDeathSig == 1)
1068     lprofRestoreSigKill();
1069 
1070   return rc;
1071 }
1072 
1073 COMPILER_RT_VISIBILITY
1074 int __llvm_profile_dump(void) {
1075   if (!doMerging())
1076     PROF_WARN("Later invocation of __llvm_profile_dump can lead to clobbering "
1077               " of previously dumped profile data : %s. Either use %%m "
1078               "in profile name or change profile name before dumping.\n",
1079               "online profile merging is not on");
1080   int rc = __llvm_profile_write_file();
1081   lprofSetProfileDumped(1);
1082   return rc;
1083 }
1084 
1085 /* Order file data will be saved in a file with suffx .order. */
1086 static const char *OrderFileSuffix = ".order";
1087 
1088 COMPILER_RT_VISIBILITY
1089 int __llvm_orderfile_write_file(void) {
1090   int rc, Length, LengthBeforeAppend, SuffixLength;
1091   const char *Filename;
1092   char *FilenameBuf;
1093   int PDeathSig = 0;
1094 
1095   SuffixLength = strlen(OrderFileSuffix);
1096   Length = getCurFilenameLength() + SuffixLength;
1097   FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
1098   Filename = getCurFilename(FilenameBuf, 1);
1099 
1100   /* Check the filename. */
1101   if (!Filename) {
1102     PROF_ERR("Failed to write file : %s\n", "Filename not set");
1103     return -1;
1104   }
1105 
1106   /* Append order file suffix */
1107   LengthBeforeAppend = strlen(Filename);
1108   memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength);
1109   FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0';
1110 
1111   /* Check if there is llvm/runtime version mismatch.  */
1112   if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
1113     PROF_ERR("Runtime and instrumentation version mismatch : "
1114              "expected %d, but get %d\n",
1115              INSTR_PROF_RAW_VERSION,
1116              (int)GET_VERSION(__llvm_profile_get_version()));
1117     return -1;
1118   }
1119 
1120   // Temporarily suspend getting SIGKILL when the parent exits.
1121   PDeathSig = lprofSuspendSigKill();
1122 
1123   /* Write order data to the file. */
1124   rc = writeOrderFile(Filename);
1125   if (rc)
1126     PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
1127 
1128   // Restore SIGKILL.
1129   if (PDeathSig == 1)
1130     lprofRestoreSigKill();
1131 
1132   return rc;
1133 }
1134 
1135 COMPILER_RT_VISIBILITY
1136 int __llvm_orderfile_dump(void) {
1137   int rc = __llvm_orderfile_write_file();
1138   return rc;
1139 }
1140 
1141 static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }
1142 
1143 COMPILER_RT_VISIBILITY
1144 int __llvm_profile_register_write_file_atexit(void) {
1145   static int HasBeenRegistered = 0;
1146 
1147   if (HasBeenRegistered)
1148     return 0;
1149 
1150   lprofSetupValueProfiler();
1151 
1152   HasBeenRegistered = 1;
1153   return atexit(writeFileWithoutReturn);
1154 }
1155 
1156 #endif
1157