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