blob: e2253de8eda2db9885a72b68b43b95178649e1b8 [file] [log] [blame]
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +00001/*===- InstrProfilingFile.c - Write instrumentation to a file -------------===*\
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +00002|*
Chandler Carruth2946cd72019-01-19 08:50:56 +00003|* 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
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +00006|*
7\*===----------------------------------------------------------------------===*/
8
Petr Hosek47e5fcb2018-07-25 03:01:35 +00009#if !defined(__Fuchsia__)
10
Joerg Sonnenbergeref24b412015-03-09 11:23:29 +000011#include <errno.h>
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +000012#include <stdio.h>
13#include <stdlib.h>
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000014#include <string.h>
Xinliang David Li71eddbf2016-05-20 04:52:27 +000015#ifdef _MSC_VER
Xinliang David Li315e49d2016-05-24 21:29:18 +000016/* For _alloca. */
Xinliang David Li71eddbf2016-05-20 04:52:27 +000017#include <malloc.h>
Xinliang David Lifb320a12016-05-20 05:40:07 +000018#endif
Xinliang David Lie2ce2e02016-06-08 23:43:56 +000019#if defined(_WIN32)
20#include "WindowsMMap.h"
21/* For _chsize_s */
22#include <io.h>
Reid Kleckner963aba32018-04-23 17:05:47 +000023#include <process.h>
Xinliang David Lie2ce2e02016-06-08 23:43:56 +000024#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
Xinliang David Li71eddbf2016-05-20 04:52:27 +000032
Vedant Kumard7c93362017-12-14 19:01:04 +000033#include "InstrProfiling.h"
34#include "InstrProfilingInternal.h"
Vedant Kumard889d1e2019-09-19 11:56:43 -070035#include "InstrProfilingPort.h"
Vedant Kumard7c93362017-12-14 19:01:04 +000036#include "InstrProfilingUtil.h"
37
Xinliang David Li153e8b62016-06-10 20:35:01 +000038/* From where is profile name specified.
39 * The order the enumerators define their
40 * precedence. Re-order them may lead to
Sajjad Mirza6694b2b2019-06-24 21:32:50 +000041 * runtime behavior change. */
Xinliang David Li153e8b62016-06-10 20:35:01 +000042typedef enum ProfileNameSpecifier {
43 PNS_unknown = 0,
44 PNS_default,
45 PNS_command_line,
46 PNS_environment,
47 PNS_runtime_api
48} ProfileNameSpecifier;
49
50static 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
Xinliang David Li315e49d2016-05-24 21:29:18 +000065#define MAX_PID_SIZE 16
Ying Yi2c614cf2016-08-10 10:48:02 +000066/* Data structure holding the result of parsed filename pattern. */
Xinliang David Li315e49d2016-05-24 21:29:18 +000067typedef struct lprofFilename {
68 /* File name string possibly with %p or %h specifiers. */
69 const char *FilenamePat;
Xinliang David Li14c91c42016-08-02 19:34:00 +000070 /* A flag indicating if FilenamePat's memory is allocated
71 * by runtime. */
72 unsigned OwnsFilenamePat;
Xinliang David Lieaf238d2016-07-20 04:26:09 +000073 const char *ProfilePathPrefix;
Xinliang David Li315e49d2016-05-24 21:29:18 +000074 char PidChars[MAX_PID_SIZE];
75 char Hostname[COMPILER_RT_MAX_HOSTLEN];
76 unsigned NumPids;
77 unsigned NumHosts;
Xinliang David Lie2ce2e02016-06-08 23:43:56 +000078 /* When in-process merging is enabled, this parameter specifies
79 * the total number of profile data files shared by all the processes
80 * spawned from the same binary. By default the value is 1. If merging
81 * is not enabled, its value should be 0. This parameter is specified
82 * by the %[0-9]m specifier. For instance %2m enables merging using
83 * 2 profile data files. %1m is equivalent to %m. Also %m specifier
84 * can only appear once at the end of the name pattern. */
85 unsigned MergePoolSize;
Xinliang David Li153e8b62016-06-10 20:35:01 +000086 ProfileNameSpecifier PNS;
Xinliang David Li315e49d2016-05-24 21:29:18 +000087} lprofFilename;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000088
Vedant Kumar937241b2019-10-18 23:33:40 +000089static lprofFilename lprofCurFilename = {0, 0, 0, {0}, {0},
90 0, 0, 0, PNS_unknown};
Xinliang David Li315e49d2016-05-24 21:29:18 +000091
Sajjad Mirza6694b2b2019-06-24 21:32:50 +000092static int ProfileMergeRequested = 0;
93static int isProfileMergeRequested() { return ProfileMergeRequested; }
94static void setProfileMergeRequested(int EnableMerge) {
95 ProfileMergeRequested = EnableMerge;
96}
97
98static FILE *ProfileFile = NULL;
99static FILE *getProfileFile() { return ProfileFile; }
100static void setProfileFile(FILE *File) { ProfileFile = File; }
101
102COMPILER_RT_VISIBILITY void __llvm_profile_set_file_object(FILE *File,
103 int EnableMerge) {
Vedant Kumard889d1e2019-09-19 11:56:43 -0700104 if (__llvm_profile_is_continuous_mode_enabled()) {
105 PROF_WARN("__llvm_profile_set_file_object(fd=%d) not supported, because "
106 "continuous sync mode (%%c) is enabled",
107 fileno(File));
108 return;
109 }
Sajjad Mirza6694b2b2019-06-24 21:32:50 +0000110 setProfileFile(File);
111 setProfileMergeRequested(EnableMerge);
112}
113
Alex Lorenz341317f2017-08-31 15:51:23 +0000114static int getCurFilenameLength();
Teresa Johnson73053b22018-07-19 19:03:50 +0000115static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf);
Sajjad Mirza6694b2b2019-06-24 21:32:50 +0000116static unsigned doMerging() {
117 return lprofCurFilename.MergePoolSize || isProfileMergeRequested();
118}
Joerg Sonnenbergerb1cc6d52014-05-20 16:37:07 +0000119
Xinliang David Li2d5bf072015-11-21 04:16:42 +0000120/* Return 1 if there is an error, otherwise return 0. */
Xinliang David Li967669f2017-06-27 17:28:01 +0000121static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
122 uint32_t NumIOVecs) {
Xinliang David Li2d5bf072015-11-21 04:16:42 +0000123 uint32_t I;
Xinliang David Li967669f2017-06-27 17:28:01 +0000124 FILE *File = (FILE *)This->WriterCtx;
Xinliang David Li2d5bf072015-11-21 04:16:42 +0000125 for (I = 0; I < NumIOVecs; I++) {
Xinliang David Lif50cc3e2017-06-28 16:46:06 +0000126 if (IOVecs[I].Data) {
127 if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
128 IOVecs[I].NumElm)
129 return 1;
130 } else {
131 if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR) == -1)
132 return 1;
133 }
Xinliang David Li2d5bf072015-11-21 04:16:42 +0000134 }
135 return 0;
Xinliang David Li1d8d46a2015-11-18 21:08:03 +0000136}
Duncan P. N. Exon Smithcf4bb962014-03-21 18:29:19 +0000137
Manman Rene73ae9a2019-03-08 15:30:56 +0000138/* TODO: make buffer size controllable by an internal option, and compiler can pass the size
139 to runtime via a variable. */
140static uint32_t orderFileWriter(FILE *File, const uint32_t *DataStart) {
141 if (fwrite(DataStart, sizeof(uint32_t), INSTR_ORDER_FILE_BUFFER_SIZE, File) !=
142 INSTR_ORDER_FILE_BUFFER_SIZE)
143 return 1;
144 return 0;
145}
146
Xinliang David Li967669f2017-06-27 17:28:01 +0000147static void initFileWriter(ProfDataWriter *This, FILE *File) {
148 This->Write = fileWriter;
149 This->WriterCtx = File;
150}
151
Xinliang David Licda3bc22015-12-29 23:54:41 +0000152COMPILER_RT_VISIBILITY ProfBufferIO *
Xinliang David Licf1a8d62016-03-06 04:18:13 +0000153lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
Xinliang David Li609fae32016-05-13 18:26:26 +0000154 FreeHook = &free;
155 DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
156 VPBufferSize = BufferSz;
Xinliang David Li967669f2017-06-27 17:28:01 +0000157 ProfDataWriter *fileWriter =
158 (ProfDataWriter *)calloc(sizeof(ProfDataWriter), 1);
159 initFileWriter(fileWriter, File);
160 ProfBufferIO *IO = lprofCreateBufferIO(fileWriter);
161 IO->OwnFileWriter = 1;
162 return IO;
Xinliang David Li609fae32016-05-13 18:26:26 +0000163}
164
165static void setupIOBuffer() {
166 const char *BufferSzStr = 0;
167 BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
168 if (BufferSzStr && BufferSzStr[0]) {
169 VPBufferSize = atoi(BufferSzStr);
170 DynamicBufferIOBuffer = (uint8_t *)calloc(VPBufferSize, 1);
171 }
Xinliang David Licda3bc22015-12-29 23:54:41 +0000172}
173
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000174/* Read profile data in \c ProfileFile and merge with in-memory
175 profile counters. Returns -1 if there is fatal error, otheriwse
Xinliang David Lif50cc3e2017-06-28 16:46:06 +0000176 0 is returned. Returning 0 does not mean merge is actually
177 performed. If merge is actually done, *MergeDone is set to 1.
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000178*/
Xinliang David Lif50cc3e2017-06-28 16:46:06 +0000179static int doProfileMerging(FILE *ProfileFile, int *MergeDone) {
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000180 uint64_t ProfileFileSize;
181 char *ProfileBuffer;
182
183 if (fseek(ProfileFile, 0L, SEEK_END) == -1) {
184 PROF_ERR("Unable to merge profile data, unable to get size: %s\n",
185 strerror(errno));
186 return -1;
187 }
188 ProfileFileSize = ftell(ProfileFile);
189
190 /* Restore file offset. */
191 if (fseek(ProfileFile, 0L, SEEK_SET) == -1) {
192 PROF_ERR("Unable to merge profile data, unable to rewind: %s\n",
193 strerror(errno));
194 return -1;
195 }
196
197 /* Nothing to merge. */
198 if (ProfileFileSize < sizeof(__llvm_profile_header)) {
199 if (ProfileFileSize)
200 PROF_WARN("Unable to merge profile data: %s\n",
201 "source profile file is too small.");
202 return 0;
203 }
204
205 ProfileBuffer = mmap(NULL, ProfileFileSize, PROT_READ, MAP_SHARED | MAP_FILE,
206 fileno(ProfileFile), 0);
207 if (ProfileBuffer == MAP_FAILED) {
208 PROF_ERR("Unable to merge profile data, mmap failed: %s\n",
209 strerror(errno));
210 return -1;
211 }
212
213 if (__llvm_profile_check_compatibility(ProfileBuffer, ProfileFileSize)) {
214 (void)munmap(ProfileBuffer, ProfileFileSize);
215 PROF_WARN("Unable to merge profile data: %s\n",
216 "source profile file is not compatible.");
217 return 0;
218 }
219
220 /* Now start merging */
221 __llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize);
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000222
Rong Xu95ab7582018-04-02 16:57:00 +0000223 // Truncate the file in case merging of value profile did not happend to
224 // prevent from leaving garbage data at the end of the profile file.
Reid Kleckner963aba32018-04-23 17:05:47 +0000225 COMPILER_RT_FTRUNCATE(ProfileFile, __llvm_profile_get_size_for_buffer());
Rong Xu95ab7582018-04-02 16:57:00 +0000226
227 (void)munmap(ProfileBuffer, ProfileFileSize);
Xinliang David Lif50cc3e2017-06-28 16:46:06 +0000228 *MergeDone = 1;
229
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000230 return 0;
231}
232
Xinliang David Lif2d94812017-02-14 21:39:55 +0000233/* Create the directory holding the file, if needed. */
234static void createProfileDir(const char *Filename) {
235 size_t Length = strlen(Filename);
236 if (lprofFindFirstDirSeparator(Filename)) {
237 char *Copy = (char *)COMPILER_RT_ALLOCA(Length + 1);
238 strncpy(Copy, Filename, Length + 1);
239 __llvm_profile_recursive_mkdir(Copy);
240 }
241}
242
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000243/* Open the profile data for merging. It opens the file in r+b mode with
244 * file locking. If the file has content which is compatible with the
245 * current process, it also reads in the profile data in the file and merge
246 * it with in-memory counters. After the profile data is merged in memory,
247 * the original profile data is truncated and gets ready for the profile
248 * dumper. With profile merging enabled, each executable as well as any of
249 * its instrumented shared libraries dump profile data into their own data file.
250*/
Xinliang David Lif50cc3e2017-06-28 16:46:06 +0000251static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
Sajjad Mirza6694b2b2019-06-24 21:32:50 +0000252 FILE *ProfileFile = NULL;
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000253 int rc;
254
Sajjad Mirza6694b2b2019-06-24 21:32:50 +0000255 ProfileFile = getProfileFile();
256 if (ProfileFile) {
257 lprofLockFileHandle(ProfileFile);
258 } else {
259 createProfileDir(ProfileFileName);
260 ProfileFile = lprofOpenFileEx(ProfileFileName);
261 }
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000262 if (!ProfileFile)
263 return NULL;
264
Xinliang David Lif50cc3e2017-06-28 16:46:06 +0000265 rc = doProfileMerging(ProfileFile, MergeDone);
266 if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)) ||
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000267 fseek(ProfileFile, 0L, SEEK_SET) == -1) {
268 PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName,
269 strerror(errno));
270 fclose(ProfileFile);
271 return NULL;
272 }
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000273 return ProfileFile;
274}
275
Sajjad Mirza6694b2b2019-06-24 21:32:50 +0000276static FILE *getFileObject(const char *OutputName) {
277 FILE *File;
278 File = getProfileFile();
279 if (File != NULL) {
280 return File;
281 }
282
283 return fopen(OutputName, "ab");
284}
285
Xinliang David Li315e49d2016-05-24 21:29:18 +0000286/* Write profile data to file \c OutputName. */
287static int writeFile(const char *OutputName) {
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +0000288 int RetVal;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +0000289 FILE *OutputFile;
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000290
Xinliang David Lif50cc3e2017-06-28 16:46:06 +0000291 int MergeDone = 0;
Rong Xu95ab7582018-04-02 16:57:00 +0000292 VPMergeHook = &lprofMergeValueProfData;
Sajjad Mirza6694b2b2019-06-24 21:32:50 +0000293 if (doMerging())
Hans Wennborg05d44132019-06-12 08:44:32 +0000294 OutputFile = openFileForMerging(OutputName, &MergeDone);
Sajjad Mirza6694b2b2019-06-24 21:32:50 +0000295 else
296 OutputFile = getFileObject(OutputName);
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000297
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +0000298 if (!OutputFile)
299 return -1;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +0000300
Xinliang David Li315e49d2016-05-24 21:29:18 +0000301 FreeHook = &free;
302 setupIOBuffer();
Xinliang David Li967669f2017-06-27 17:28:01 +0000303 ProfDataWriter fileWriter;
304 initFileWriter(&fileWriter, OutputFile);
Xinliang David Lif50cc3e2017-06-28 16:46:06 +0000305 RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +0000306
Sajjad Mirza6694b2b2019-06-24 21:32:50 +0000307 if (OutputFile == getProfileFile()) {
308 fflush(OutputFile);
309 if (doMerging()) {
310 lprofUnlockFileHandle(OutputFile);
311 }
312 } else {
313 fclose(OutputFile);
314 }
315
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +0000316 return RetVal;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +0000317}
318
Manman Rene73ae9a2019-03-08 15:30:56 +0000319/* Write order data to file \c OutputName. */
320static int writeOrderFile(const char *OutputName) {
321 int RetVal;
322 FILE *OutputFile;
323
324 OutputFile = fopen(OutputName, "w");
325
326 if (!OutputFile) {
327 PROF_WARN("can't open file with mode ab: %s\n", OutputName);
328 return -1;
329 }
330
331 FreeHook = &free;
332 setupIOBuffer();
333 const uint32_t *DataBegin = __llvm_profile_begin_orderfile();
334 RetVal = orderFileWriter(OutputFile, DataBegin);
335
336 fclose(OutputFile);
337 return RetVal;
338}
339
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000340static void truncateCurrentFile(void) {
Vasileios Kalintirisc9c7a3e2015-02-25 13:50:18 +0000341 const char *Filename;
Xinliang David Li315e49d2016-05-24 21:29:18 +0000342 char *FilenameBuf;
Vasileios Kalintirisc9c7a3e2015-02-25 13:50:18 +0000343 FILE *File;
Xinliang David Li315e49d2016-05-24 21:29:18 +0000344 int Length;
Vasileios Kalintirisc9c7a3e2015-02-25 13:50:18 +0000345
Xinliang David Li315e49d2016-05-24 21:29:18 +0000346 Length = getCurFilenameLength();
347 FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
Teresa Johnson73053b22018-07-19 19:03:50 +0000348 Filename = getCurFilename(FilenameBuf, 0);
Xinliang David Li315e49d2016-05-24 21:29:18 +0000349 if (!Filename)
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000350 return;
351
Xinliang David Lie3fc4d02016-07-21 03:38:07 +0000352 /* By pass file truncation to allow online raw profile
353 * merging. */
354 if (lprofCurFilename.MergePoolSize)
355 return;
356
Vedant Kumard889d1e2019-09-19 11:56:43 -0700357 /* Only create the profile directory and truncate an existing profile once.
358 * In continuous mode, this is necessary, as the profile is written-to by the
359 * runtime initializer. */
360 const char *lprofInitOnceEnv = "__LLVM_PROFILE_RT_INIT_ONCE";
361 int initialized = getenv(lprofInitOnceEnv) != NULL;
362 if (initialized)
363 return;
364 setenv(lprofInitOnceEnv, lprofInitOnceEnv, 1);
365
Xinliang David Lif2d94812017-02-14 21:39:55 +0000366 createProfileDir(Filename);
367
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000368 /* Truncate the file. Later we'll reopen and append. */
Vasileios Kalintirisc9c7a3e2015-02-25 13:50:18 +0000369 File = fopen(Filename, "w");
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000370 if (!File)
371 return;
372 fclose(File);
373}
374
Vedant Kumard889d1e2019-09-19 11:56:43 -0700375static void initializeProfileForContinuousMode(void) {
376#if defined(__Fuchsia__) || defined(_WIN32)
377 PROF_ERR("%s\n", "Continuous mode not yet supported on Fuchsia or Windows.");
378#else // defined(__Fuchsia__) || defined(_WIN32)
379 if (!__llvm_profile_is_continuous_mode_enabled())
380 return;
381
382 /* Get the sizes of various profile data sections. Taken from
383 * __llvm_profile_get_size_for_buffer(). */
384 const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
385 const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
386 const uint64_t *CountersBegin = __llvm_profile_begin_counters();
387 const uint64_t *CountersEnd = __llvm_profile_end_counters();
388 const char *NamesBegin = __llvm_profile_begin_names();
389 const char *NamesEnd = __llvm_profile_end_names();
390 const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
391 uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
392 uint64_t CountersSize = CountersEnd - CountersBegin;
393
394 /* Check that the counter and data sections in this image are page-aligned. */
395 unsigned PageSize = getpagesize();
396 if ((intptr_t)CountersBegin % PageSize != 0) {
397 PROF_ERR("Counters section not page-aligned (start = %p, pagesz = %u).\n",
398 CountersBegin, PageSize);
399 return;
400 }
401 if ((intptr_t)DataBegin % PageSize != 0) {
402 PROF_ERR("Data section not page-aligned (start = %p, pagesz = %u).\n",
403 DataBegin, PageSize);
404 return;
405 }
406
407 /* Open the raw profile in append mode. */
408 int Length = getCurFilenameLength();
409 char *FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
410 const char *Filename = getCurFilename(FilenameBuf, 0);
411 if (!Filename)
412 return;
413 FILE *File = fopen(Filename, "a+b");
414 if (!File)
415 return;
416
417 int Fileno = fileno(File);
418
419 /* Check that the offset within the file is page-aligned. */
420 off_t CurrentFileOffset = ftello(File);
421 off_t OffsetModPage = CurrentFileOffset % PageSize;
422 if (OffsetModPage != 0) {
423 PROF_ERR("Continuous counter sync mode is enabled, but raw profile is not"
424 "page-aligned. CurrentFileOffset = %lld, pagesz = %u.\n",
425 CurrentFileOffset, PageSize);
426 return;
427 }
428
429 /* Determine how much padding is needed before/after the counters and after
430 * the names. */
431 uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
432 PaddingBytesAfterNames;
433 __llvm_profile_get_padding_sizes_for_counters(
434 DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
435 &PaddingBytesAfterCounters, &PaddingBytesAfterNames);
436
437 uint64_t PageAlignedCountersLength =
438 (CountersSize * sizeof(uint64_t)) + PaddingBytesAfterCounters;
439 uint64_t FileOffsetToCounters =
440 CurrentFileOffset + sizeof(__llvm_profile_header) +
441 (DataSize * sizeof(__llvm_profile_data)) + PaddingBytesBeforeCounters;
442
443 /* Write the partial profile. This grows the file to a point where the mmap()
444 * can succeed. Leak the file handle, as the file should stay open. */
445 setProfileFile(File);
446 int rc = writeFile(Filename);
447 if (rc)
448 PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
449 setProfileFile(NULL);
450
451 uint64_t *CounterMmap = (uint64_t *)mmap(
452 (void *)CountersBegin, PageAlignedCountersLength, PROT_READ | PROT_WRITE,
453 MAP_FIXED | MAP_SHARED, Fileno, FileOffsetToCounters);
454 if (CounterMmap != CountersBegin) {
455 PROF_ERR(
456 "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
457 " - CountersBegin: %p\n"
458 " - PageAlignedCountersLength: %llu\n"
459 " - Fileno: %d\n"
460 " - FileOffsetToCounters: %llu\n",
461 strerror(errno), CountersBegin, PageAlignedCountersLength, Fileno,
462 FileOffsetToCounters);
463 return;
464 }
465#endif // defined(__Fuchsia__) || defined(_WIN32)
466}
467
Xinliang David Li153e8b62016-06-10 20:35:01 +0000468static const char *DefaultProfileName = "default.profraw";
Xinliang David Li315e49d2016-05-24 21:29:18 +0000469static void resetFilenameToDefault(void) {
Xinliang David Li14c91c42016-08-02 19:34:00 +0000470 if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
471 free((void *)lprofCurFilename.FilenamePat);
472 }
Xinliang David Li7f08d122016-05-25 17:30:15 +0000473 memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
Xinliang David Li153e8b62016-06-10 20:35:01 +0000474 lprofCurFilename.FilenamePat = DefaultProfileName;
475 lprofCurFilename.PNS = PNS_default;
Xinliang David Li315e49d2016-05-24 21:29:18 +0000476}
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000477
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000478static int containsMergeSpecifier(const char *FilenamePat, int I) {
479 return (FilenamePat[I] == 'm' ||
480 (FilenamePat[I] >= '1' && FilenamePat[I] <= '9' &&
481 /* If FilenamePat[I] is not '\0', the next byte is guaranteed
482 * to be in-bound as the string is null terminated. */
483 FilenamePat[I + 1] == 'm'));
484}
Xinliang David Li7f08d122016-05-25 17:30:15 +0000485
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000486/* Parses the pattern string \p FilenamePat and stores the result to
487 * lprofcurFilename structure. */
Xinliang David Li14c91c42016-08-02 19:34:00 +0000488static int parseFilenamePattern(const char *FilenamePat,
489 unsigned CopyFilenamePat) {
Xinliang David Li315e49d2016-05-24 21:29:18 +0000490 int NumPids = 0, NumHosts = 0, I;
Xinliang David Li7f08d122016-05-25 17:30:15 +0000491 char *PidChars = &lprofCurFilename.PidChars[0];
492 char *Hostname = &lprofCurFilename.Hostname[0];
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000493 int MergingEnabled = 0;
Vasileios Kalintirisc9c7a3e2015-02-25 13:50:18 +0000494
Teresa Johnson73053b22018-07-19 19:03:50 +0000495 /* Clean up cached prefix and filename. */
Xinliang David Lib061cdb2016-07-20 05:10:56 +0000496 if (lprofCurFilename.ProfilePathPrefix)
497 free((void *)lprofCurFilename.ProfilePathPrefix);
Teresa Johnson73053b22018-07-19 19:03:50 +0000498
Xinliang David Li14c91c42016-08-02 19:34:00 +0000499 if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
500 free((void *)lprofCurFilename.FilenamePat);
501 }
502
Igor Kudrin63600c72018-07-24 12:28:53 +0000503 memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
504
Xinliang David Li14c91c42016-08-02 19:34:00 +0000505 if (!CopyFilenamePat)
506 lprofCurFilename.FilenamePat = FilenamePat;
507 else {
508 lprofCurFilename.FilenamePat = strdup(FilenamePat);
509 lprofCurFilename.OwnsFilenamePat = 1;
510 }
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000511 /* Check the filename for "%p", which indicates a pid-substitution. */
Xinliang David Li315e49d2016-05-24 21:29:18 +0000512 for (I = 0; FilenamePat[I]; ++I)
513 if (FilenamePat[I] == '%') {
514 if (FilenamePat[++I] == 'p') {
Vedant Kumara06e8ca2016-01-29 23:52:11 +0000515 if (!NumPids++) {
Vedant Kumard7c93362017-12-14 19:01:04 +0000516 if (snprintf(PidChars, MAX_PID_SIZE, "%ld", (long)getpid()) <= 0) {
Bob Haarman9ee65ac2016-11-29 15:24:00 +0000517 PROF_WARN("Unable to get pid for filename pattern %s. Using the "
518 "default name.",
519 FilenamePat);
Vedant Kumara06e8ca2016-01-29 23:52:11 +0000520 return -1;
Xinliang David Li315e49d2016-05-24 21:29:18 +0000521 }
Vedant Kumara06e8ca2016-01-29 23:52:11 +0000522 }
Xinliang David Li315e49d2016-05-24 21:29:18 +0000523 } else if (FilenamePat[I] == 'h') {
Vedant Kumara06e8ca2016-01-29 23:52:11 +0000524 if (!NumHosts++)
Xinliang David Li315e49d2016-05-24 21:29:18 +0000525 if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)) {
Bob Haarman9ee65ac2016-11-29 15:24:00 +0000526 PROF_WARN("Unable to get hostname for filename pattern %s. Using "
527 "the default name.",
528 FilenamePat);
Vedant Kumara06e8ca2016-01-29 23:52:11 +0000529 return -1;
Xinliang David Li315e49d2016-05-24 21:29:18 +0000530 }
Vedant Kumard889d1e2019-09-19 11:56:43 -0700531 } else if (FilenamePat[I] == 'c') {
532 if (__llvm_profile_is_continuous_mode_enabled()) {
533 PROF_WARN("%%c specifier can only be specified once in %s.\n",
534 FilenamePat);
535 return -1;
536 }
537 if (MergingEnabled) {
538 PROF_WARN("%%c specifier can not be used with profile merging (%%m) "
539 "in %s.\n",
540 FilenamePat);
541 return -1;
542 }
543
544 __llvm_profile_enable_continuous_mode();
545 I++; /* advance to 'c' */
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000546 } else if (containsMergeSpecifier(FilenamePat, I)) {
547 if (MergingEnabled) {
Vedant Kumar8e2dd512016-06-14 17:23:13 +0000548 PROF_WARN("%%m specifier can only be specified once in %s.\n",
549 FilenamePat);
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000550 return -1;
551 }
Vedant Kumard889d1e2019-09-19 11:56:43 -0700552 if (__llvm_profile_is_continuous_mode_enabled()) {
553 PROF_WARN("%%c specifier can not be used with profile merging (%%m) "
554 "in %s.\n",
555 FilenamePat);
556 return -1;
557 }
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000558 MergingEnabled = 1;
559 if (FilenamePat[I] == 'm')
560 lprofCurFilename.MergePoolSize = 1;
561 else {
562 lprofCurFilename.MergePoolSize = FilenamePat[I] - '0';
563 I++; /* advance to 'm' */
564 }
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +0000565 }
Vedant Kumara06e8ca2016-01-29 23:52:11 +0000566 }
567
Xinliang David Li7f08d122016-05-25 17:30:15 +0000568 lprofCurFilename.NumPids = NumPids;
569 lprofCurFilename.NumHosts = NumHosts;
Xinliang David Li315e49d2016-05-24 21:29:18 +0000570 return 0;
571}
572
Xinliang David Li153e8b62016-06-10 20:35:01 +0000573static void parseAndSetFilename(const char *FilenamePat,
Xinliang David Li14c91c42016-08-02 19:34:00 +0000574 ProfileNameSpecifier PNS,
575 unsigned CopyFilenamePat) {
Xinliang David Li7f08d122016-05-25 17:30:15 +0000576
Xinliang David Li153e8b62016-06-10 20:35:01 +0000577 const char *OldFilenamePat = lprofCurFilename.FilenamePat;
578 ProfileNameSpecifier OldPNS = lprofCurFilename.PNS;
579
Vedant Kumard889d1e2019-09-19 11:56:43 -0700580 /* The old profile name specifier takes precedence over the old one. */
Xinliang David Li153e8b62016-06-10 20:35:01 +0000581 if (PNS < OldPNS)
582 return;
583
584 if (!FilenamePat)
585 FilenamePat = DefaultProfileName;
586
Xinliang David Li153e8b62016-06-10 20:35:01 +0000587 if (OldFilenamePat && !strcmp(OldFilenamePat, FilenamePat)) {
588 lprofCurFilename.PNS = PNS;
589 return;
590 }
591
592 /* When PNS >= OldPNS, the last one wins. */
Xinliang David Li14c91c42016-08-02 19:34:00 +0000593 if (!FilenamePat || parseFilenamePattern(FilenamePat, CopyFilenamePat))
Xinliang David Li7f08d122016-05-25 17:30:15 +0000594 resetFilenameToDefault();
Xinliang David Li153e8b62016-06-10 20:35:01 +0000595 lprofCurFilename.PNS = PNS;
Xinliang David Li7f08d122016-05-25 17:30:15 +0000596
Xinliang David Li153e8b62016-06-10 20:35:01 +0000597 if (!OldFilenamePat) {
Xinliang David Lie68df592016-09-22 21:00:29 +0000598 if (getenv("LLVM_PROFILE_VERBOSE"))
599 PROF_NOTE("Set profile file path to \"%s\" via %s.\n",
600 lprofCurFilename.FilenamePat, getPNSStr(PNS));
Xinliang David Li153e8b62016-06-10 20:35:01 +0000601 } else {
Xinliang David Lie68df592016-09-22 21:00:29 +0000602 if (getenv("LLVM_PROFILE_VERBOSE"))
603 PROF_NOTE("Override old profile path \"%s\" via %s to \"%s\" via %s.\n",
604 OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat,
605 getPNSStr(PNS));
Xinliang David Li153e8b62016-06-10 20:35:01 +0000606 }
Xinliang David Li7f08d122016-05-25 17:30:15 +0000607
Xinliang David Lie3fc4d02016-07-21 03:38:07 +0000608 truncateCurrentFile();
Vedant Kumard889d1e2019-09-19 11:56:43 -0700609 initializeProfileForContinuousMode();
Xinliang David Li7f08d122016-05-25 17:30:15 +0000610}
611
Xinliang David Li315e49d2016-05-24 21:29:18 +0000612/* Return buffer length that is required to store the current profile
613 * filename with PID and hostname substitutions. */
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000614/* The length to hold uint64_t followed by 2 digit pool id including '_' */
615#define SIGLEN 24
Xinliang David Li315e49d2016-05-24 21:29:18 +0000616static int getCurFilenameLength() {
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000617 int Len;
Xinliang David Li315e49d2016-05-24 21:29:18 +0000618 if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000619 return 0;
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +0000620
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000621 if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
622 lprofCurFilename.MergePoolSize))
Xinliang David Li315e49d2016-05-24 21:29:18 +0000623 return strlen(lprofCurFilename.FilenamePat);
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000624
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000625 Len = strlen(lprofCurFilename.FilenamePat) +
626 lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
627 lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2);
628 if (lprofCurFilename.MergePoolSize)
629 Len += SIGLEN;
630 return Len;
Xinliang David Li315e49d2016-05-24 21:29:18 +0000631}
632
633/* Return the pointer to the current profile file name (after substituting
634 * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer
635 * to store the resulting filename. If no substitution is needed, the
Teresa Johnson73053b22018-07-19 19:03:50 +0000636 * current filename pattern string is directly returned, unless ForceUseBuf
637 * is enabled. */
638static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
639 int I, J, PidLength, HostNameLength, FilenamePatLength;
Xinliang David Li315e49d2016-05-24 21:29:18 +0000640 const char *FilenamePat = lprofCurFilename.FilenamePat;
641
642 if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
643 return 0;
644
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000645 if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
Vedant Kumard889d1e2019-09-19 11:56:43 -0700646 lprofCurFilename.MergePoolSize ||
647 __llvm_profile_is_continuous_mode_enabled())) {
Teresa Johnson73053b22018-07-19 19:03:50 +0000648 if (!ForceUseBuf)
649 return lprofCurFilename.FilenamePat;
650
651 FilenamePatLength = strlen(lprofCurFilename.FilenamePat);
652 memcpy(FilenameBuf, lprofCurFilename.FilenamePat, FilenamePatLength);
653 FilenameBuf[FilenamePatLength] = '\0';
654 return FilenameBuf;
655 }
Xinliang David Li315e49d2016-05-24 21:29:18 +0000656
657 PidLength = strlen(lprofCurFilename.PidChars);
658 HostNameLength = strlen(lprofCurFilename.Hostname);
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000659 /* Construct the new filename. */
Xinliang David Li315e49d2016-05-24 21:29:18 +0000660 for (I = 0, J = 0; FilenamePat[I]; ++I)
661 if (FilenamePat[I] == '%') {
662 if (FilenamePat[++I] == 'p') {
663 memcpy(FilenameBuf + J, lprofCurFilename.PidChars, PidLength);
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000664 J += PidLength;
Xinliang David Li315e49d2016-05-24 21:29:18 +0000665 } else if (FilenamePat[I] == 'h') {
666 memcpy(FilenameBuf + J, lprofCurFilename.Hostname, HostNameLength);
Vedant Kumara06e8ca2016-01-29 23:52:11 +0000667 J += HostNameLength;
Xinliang David Lie2ce2e02016-06-08 23:43:56 +0000668 } else if (containsMergeSpecifier(FilenamePat, I)) {
669 char LoadModuleSignature[SIGLEN];
670 int S;
671 int ProfilePoolId = getpid() % lprofCurFilename.MergePoolSize;
672 S = snprintf(LoadModuleSignature, SIGLEN, "%" PRIu64 "_%d",
673 lprofGetLoadModuleSignature(), ProfilePoolId);
674 if (S == -1 || S > SIGLEN)
675 S = SIGLEN;
676 memcpy(FilenameBuf + J, LoadModuleSignature, S);
677 J += S;
678 if (FilenamePat[I] != 'm')
679 I++;
Vedant Kumara06e8ca2016-01-29 23:52:11 +0000680 }
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000681 /* Drop any unknown substitutions. */
682 } else
Xinliang David Li315e49d2016-05-24 21:29:18 +0000683 FilenameBuf[J++] = FilenamePat[I];
684 FilenameBuf[J] = 0;
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000685
Xinliang David Li315e49d2016-05-24 21:29:18 +0000686 return FilenameBuf;
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000687}
688
Xinliang David Li315e49d2016-05-24 21:29:18 +0000689/* Returns the pointer to the environment variable
690 * string. Returns null if the env var is not set. */
691static const char *getFilenamePatFromEnv(void) {
Eric Christopherd641b532015-04-28 22:54:51 +0000692 const char *Filename = getenv("LLVM_PROFILE_FILE");
Eric Christopherd641b532015-04-28 22:54:51 +0000693 if (!Filename || !Filename[0])
Xinliang David Li51fe0022016-05-24 01:23:09 +0000694 return 0;
695 return Filename;
Eric Christopherd641b532015-04-28 22:54:51 +0000696}
697
Xinliang David Lieaf238d2016-07-20 04:26:09 +0000698COMPILER_RT_VISIBILITY
699const char *__llvm_profile_get_path_prefix(void) {
700 int Length;
701 char *FilenameBuf, *Prefix;
702 const char *Filename, *PrefixEnd;
703
704 if (lprofCurFilename.ProfilePathPrefix)
705 return lprofCurFilename.ProfilePathPrefix;
706
707 Length = getCurFilenameLength();
708 FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
Teresa Johnson73053b22018-07-19 19:03:50 +0000709 Filename = getCurFilename(FilenameBuf, 0);
Xinliang David Lieaf238d2016-07-20 04:26:09 +0000710 if (!Filename)
711 return "\0";
712
713 PrefixEnd = lprofFindLastDirSeparator(Filename);
714 if (!PrefixEnd)
715 return "\0";
716
717 Length = PrefixEnd - Filename + 1;
718 Prefix = (char *)malloc(Length + 1);
719 if (!Prefix) {
720 PROF_ERR("Failed to %s\n", "allocate memory.");
721 return "\0";
722 }
723 memcpy(Prefix, Filename, Length);
724 Prefix[Length] = '\0';
725 lprofCurFilename.ProfilePathPrefix = Prefix;
726 return Prefix;
727}
728
Teresa Johnson73053b22018-07-19 19:03:50 +0000729COMPILER_RT_VISIBILITY
730const char *__llvm_profile_get_filename(void) {
731 int Length;
732 char *FilenameBuf;
733 const char *Filename;
734
Teresa Johnson73053b22018-07-19 19:03:50 +0000735 Length = getCurFilenameLength();
736 FilenameBuf = (char *)malloc(Length + 1);
737 if (!FilenameBuf) {
738 PROF_ERR("Failed to %s\n", "allocate memory.");
739 return "\0";
740 }
741 Filename = getCurFilename(FilenameBuf, 1);
742 if (!Filename)
743 return "\0";
744
Teresa Johnson73053b22018-07-19 19:03:50 +0000745 return FilenameBuf;
746}
747
Xinliang David Li51fe0022016-05-24 01:23:09 +0000748/* This method is invoked by the runtime initialization hook
749 * InstrProfilingRuntime.o if it is linked in. Both user specified
750 * profile path via -fprofile-instr-generate= and LLVM_PROFILE_FILE
751 * environment variable can override this default value. */
Xinliang David Liabfd5532015-12-16 03:29:15 +0000752COMPILER_RT_VISIBILITY
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000753void __llvm_profile_initialize_file(void) {
Xinliang David Lie9539332016-07-21 23:19:18 +0000754 const char *EnvFilenamePat;
Xinliang David Li1c9320c2017-08-15 03:13:01 +0000755 const char *SelectedPat = NULL;
756 ProfileNameSpecifier PNS = PNS_unknown;
Xinliang David Lie9539332016-07-21 23:19:18 +0000757 int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR[0] != 0);
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000758
Xinliang David Lie9539332016-07-21 23:19:18 +0000759 EnvFilenamePat = getFilenamePatFromEnv();
Xinliang David Li1c9320c2017-08-15 03:13:01 +0000760 if (EnvFilenamePat) {
Sajjad Mirza6694b2b2019-06-24 21:32:50 +0000761 /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
Xinliang David Lic7c53032017-08-23 21:39:33 +0000762 at the moment when __llvm_profile_write_file() gets executed. */
763 parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
764 return;
Xinliang David Li1c9320c2017-08-15 03:13:01 +0000765 } else if (hasCommandLineOverrider) {
766 SelectedPat = INSTR_PROF_PROFILE_NAME_VAR;
767 PNS = PNS_command_line;
Xinliang David Lie9539332016-07-21 23:19:18 +0000768 } else {
Xinliang David Li1c9320c2017-08-15 03:13:01 +0000769 SelectedPat = NULL;
770 PNS = PNS_default;
Xinliang David Lie9539332016-07-21 23:19:18 +0000771 }
772
Xinliang David Li1c9320c2017-08-15 03:13:01 +0000773 parseAndSetFilename(SelectedPat, PNS, 0);
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000774}
775
Xinliang David Li51fe0022016-05-24 01:23:09 +0000776/* This API is directly called by the user application code. It has the
777 * highest precedence compared with LLVM_PROFILE_FILE environment variable
Xinliang David Li41518942016-05-24 02:37:07 +0000778 * and command line option -fprofile-instr-generate=<profile_name>.
Xinliang David Li51fe0022016-05-24 01:23:09 +0000779 */
Xinliang David Liabfd5532015-12-16 03:29:15 +0000780COMPILER_RT_VISIBILITY
Xinliang David Li315e49d2016-05-24 21:29:18 +0000781void __llvm_profile_set_filename(const char *FilenamePat) {
Vedant Kumard889d1e2019-09-19 11:56:43 -0700782 if (__llvm_profile_is_continuous_mode_enabled())
783 return;
Xinliang David Li14c91c42016-08-02 19:34:00 +0000784 parseAndSetFilename(FilenamePat, PNS_runtime_api, 1);
Eric Christopherd641b532015-04-28 22:54:51 +0000785}
786
Xinliang David Li315e49d2016-05-24 21:29:18 +0000787/* The public API for writing profile data into the file with name
788 * set by previous calls to __llvm_profile_set_filename or
789 * __llvm_profile_override_default_filename or
790 * __llvm_profile_initialize_file. */
Xinliang David Liabfd5532015-12-16 03:29:15 +0000791COMPILER_RT_VISIBILITY
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000792int __llvm_profile_write_file(void) {
Xinliang David Li315e49d2016-05-24 21:29:18 +0000793 int rc, Length;
794 const char *Filename;
795 char *FilenameBuf;
Rong Xucf1f6fb2017-03-17 18:41:33 +0000796 int PDeathSig = 0;
Vasileios Kalintirisc9c7a3e2015-02-25 13:50:18 +0000797
Vedant Kumard889d1e2019-09-19 11:56:43 -0700798 if (lprofProfileDumped() || __llvm_profile_is_continuous_mode_enabled()) {
Sajjad Mirza6694b2b2019-06-24 21:32:50 +0000799 PROF_NOTE("Profile data not written to file: %s.\n", "already written");
Xinliang David Li3b2c0022016-08-09 04:21:14 +0000800 return 0;
801 }
802
Xinliang David Li315e49d2016-05-24 21:29:18 +0000803 Length = getCurFilenameLength();
804 FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
Teresa Johnson73053b22018-07-19 19:03:50 +0000805 Filename = getCurFilename(FilenameBuf, 0);
Xinliang David Li315e49d2016-05-24 21:29:18 +0000806
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000807 /* Check the filename. */
Xinliang David Li315e49d2016-05-24 21:29:18 +0000808 if (!Filename) {
Xinliang David Li690c31f2016-05-20 05:15:42 +0000809 PROF_ERR("Failed to write file : %s\n", "Filename not set");
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000810 return -1;
Xinliang David Li9ea30642015-12-03 18:31:59 +0000811 }
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000812
Xinliang David Lid85c32c2016-01-08 23:42:28 +0000813 /* Check if there is llvm/runtime version mismatch. */
Xinliang David Lia6924212016-01-08 23:31:57 +0000814 if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
Xinliang David Li690c31f2016-05-20 05:15:42 +0000815 PROF_ERR("Runtime and instrumentation version mismatch : "
Xinliang David Lia6924212016-01-08 23:31:57 +0000816 "expected %d, but get %d\n",
817 INSTR_PROF_RAW_VERSION,
818 (int)GET_VERSION(__llvm_profile_get_version()));
819 return -1;
820 }
821
Rong Xucf1f6fb2017-03-17 18:41:33 +0000822 // Temporarily suspend getting SIGKILL when the parent exits.
823 PDeathSig = lprofSuspendSigKill();
824
Xinliang David Li315e49d2016-05-24 21:29:18 +0000825 /* Write profile data to the file. */
826 rc = writeFile(Filename);
Xinliang David Li9ea30642015-12-03 18:31:59 +0000827 if (rc)
Xinliang David Li315e49d2016-05-24 21:29:18 +0000828 PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
Rong Xucf1f6fb2017-03-17 18:41:33 +0000829
830 // Restore SIGKILL.
831 if (PDeathSig == 1)
832 lprofRestoreSigKill();
833
Justin Bogner66fd5c92015-01-16 20:10:56 +0000834 return rc;
Duncan P. N. Exon Smith54cc0e22014-03-20 19:23:55 +0000835}
836
Xinliang David Li3b2c0022016-08-09 04:21:14 +0000837COMPILER_RT_VISIBILITY
838int __llvm_profile_dump(void) {
839 if (!doMerging())
840 PROF_WARN("Later invocation of __llvm_profile_dump can lead to clobbering "
Nico Weber81291a02016-09-08 01:46:52 +0000841 " of previously dumped profile data : %s. Either use %%m "
Xinliang David Li3b2c0022016-08-09 04:21:14 +0000842 "in profile name or change profile name before dumping.\n",
843 "online profile merging is not on");
844 int rc = __llvm_profile_write_file();
845 lprofSetProfileDumped();
846 return rc;
847}
848
Manman Rene73ae9a2019-03-08 15:30:56 +0000849/* Order file data will be saved in a file with suffx .order. */
850static const char *OrderFileSuffix = ".order";
851
852COMPILER_RT_VISIBILITY
853int __llvm_orderfile_write_file(void) {
854 int rc, Length, LengthBeforeAppend, SuffixLength;
855 const char *Filename;
856 char *FilenameBuf;
857 int PDeathSig = 0;
858
859 SuffixLength = strlen(OrderFileSuffix);
860 Length = getCurFilenameLength() + SuffixLength;
861 FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
862 Filename = getCurFilename(FilenameBuf, 1);
863
864 /* Check the filename. */
865 if (!Filename) {
866 PROF_ERR("Failed to write file : %s\n", "Filename not set");
867 return -1;
868 }
869
870 /* Append order file suffix */
871 LengthBeforeAppend = strlen(Filename);
872 memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength);
873 FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0';
874
875 /* Check if there is llvm/runtime version mismatch. */
876 if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
877 PROF_ERR("Runtime and instrumentation version mismatch : "
878 "expected %d, but get %d\n",
879 INSTR_PROF_RAW_VERSION,
880 (int)GET_VERSION(__llvm_profile_get_version()));
881 return -1;
882 }
883
884 // Temporarily suspend getting SIGKILL when the parent exits.
885 PDeathSig = lprofSuspendSigKill();
886
887 /* Write order data to the file. */
888 rc = writeOrderFile(Filename);
889 if (rc)
890 PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
891
892 // Restore SIGKILL.
893 if (PDeathSig == 1)
894 lprofRestoreSigKill();
895
896 return rc;
897}
898
899COMPILER_RT_VISIBILITY
900int __llvm_orderfile_dump(void) {
901 int rc = __llvm_orderfile_write_file();
902 return rc;
903}
904
Xinliang David Li6fe18f42015-11-23 04:38:17 +0000905static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000906
Xinliang David Liabfd5532015-12-16 03:29:15 +0000907COMPILER_RT_VISIBILITY
Duncan P. N. Exon Smith55e4d662014-05-17 01:27:30 +0000908int __llvm_profile_register_write_file_atexit(void) {
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +0000909 static int HasBeenRegistered = 0;
910
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000911 if (HasBeenRegistered)
912 return 0;
913
Xinliang David Li4617aa72016-05-18 22:34:05 +0000914 lprofSetupValueProfiler();
915
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000916 HasBeenRegistered = 1;
917 return atexit(writeFileWithoutReturn);
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +0000918}
Petr Hosek47e5fcb2018-07-25 03:01:35 +0000919
920#endif