Bug Summary

File:compiler-rt/lib/profile/InstrProfilingFile.c
Warning:line 712, column 7
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name InstrProfilingFile.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=none -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/build-llvm/projects/compiler-rt/lib/profile -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/compiler-rt/lib/profile -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/build-llvm/include -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/compiler-rt/lib/profile/.. -I /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/compiler-rt/lib/profile/../../include -U NDEBUG -D COMPILER_RT_HAS_ATOMICS=1 -D COMPILER_RT_HAS_FCNTL_LCK=1 -D COMPILER_RT_HAS_UNAME=1 -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -Wno-unused-parameter -Wno-pedantic -fconst-strings -fdebug-compilation-dir /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/build-llvm/projects/compiler-rt/lib/profile -fdebug-prefix-map=/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd=. -ferror-limit 19 -fmessage-length 0 -stack-protector 2 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -o /tmp/scan-build-2020-01-13-084841-49055-1 -x c /build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/compiler-rt/lib/profile/InstrProfilingFile.c
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(*__errno_location ()).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__1)
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. */
42typedef 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
65#define MAX_PID_SIZE16 16
66/* Data structure holding the result of parsed filename pattern. */
67typedef 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_SIZE16];
75 char Hostname[COMPILER_RT_MAX_HOSTLEN128];
76 unsigned NumPids;
77 unsigned NumHosts;
78 /* 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;
86 ProfileNameSpecifier PNS;
87} lprofFilename;
88
89static lprofFilename lprofCurFilename = {0, 0, 0, {0}, {0},
90 0, 0, 0, PNS_unknown};
91
92static int ProfileMergeRequested = 0;
93static int isProfileMergeRequested() { return ProfileMergeRequested; }
94static void setProfileMergeRequested(int EnableMerge) {
95 ProfileMergeRequested = EnableMerge;
96}
97
98static FILE *ProfileFile = NULL((void*)0);
99static FILE *getProfileFile() { return ProfileFile; }
100static void setProfileFile(FILE *File) { ProfileFile = File; }
101
102COMPILER_RT_VISIBILITY__attribute__((visibility("hidden"))) void __llvm_profile_set_file_object(FILE *File,
103 int EnableMerge) {
104 if (__llvm_profile_is_continuous_mode_enabled()) {
105 PROF_WARN("__llvm_profile_set_file_object(fd=%d) not supported, because "fprintf(stderr, "LLVM Profile Warning: " "__llvm_profile_set_file_object(fd=%d) not supported, because "
"continuous sync mode (%%c) is enabled", fileno(File));
106 "continuous sync mode (%%c) is enabled",fprintf(stderr, "LLVM Profile Warning: " "__llvm_profile_set_file_object(fd=%d) not supported, because "
"continuous sync mode (%%c) is enabled", fileno(File));
107 fileno(File))fprintf(stderr, "LLVM Profile Warning: " "__llvm_profile_set_file_object(fd=%d) not supported, because "
"continuous sync mode (%%c) is enabled", fileno(File));
;
108 return;
109 }
110 setProfileFile(File);
111 setProfileMergeRequested(EnableMerge);
112}
113
114static int getCurFilenameLength();
115static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf);
116static unsigned doMerging() {
117 return lprofCurFilename.MergePoolSize || isProfileMergeRequested();
118}
119
120/* Return 1 if there is an error, otherwise return 0. */
121static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
122 uint32_t NumIOVecs) {
123 uint32_t I;
124 FILE *File = (FILE *)This->WriterCtx;
125 char Zeroes[sizeof(uint64_t)] = {0};
126 for (I = 0; I < NumIOVecs; I++) {
127 if (IOVecs[I].Data) {
128 if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
129 IOVecs[I].NumElm)
130 return 1;
131 } else if (IOVecs[I].UseZeroPadding) {
132 size_t BytesToWrite = IOVecs[I].ElmSize * IOVecs[I].NumElm;
133 while (BytesToWrite > 0) {
134 size_t PartialWriteLen =
135 (sizeof(uint64_t) > BytesToWrite) ? BytesToWrite : sizeof(uint64_t);
136 if (fwrite(Zeroes, sizeof(uint8_t), PartialWriteLen, File) !=
137 PartialWriteLen) {
138 return 1;
139 }
140 BytesToWrite -= PartialWriteLen;
141 }
142 } else {
143 if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR1) == -1)
144 return 1;
145 }
146 }
147 return 0;
148}
149
150/* TODO: make buffer size controllable by an internal option, and compiler can pass the size
151 to runtime via a variable. */
152static uint32_t orderFileWriter(FILE *File, const uint32_t *DataStart) {
153 if (fwrite(DataStart, sizeof(uint32_t), INSTR_ORDER_FILE_BUFFER_SIZE131072, File) !=
154 INSTR_ORDER_FILE_BUFFER_SIZE131072)
155 return 1;
156 return 0;
157}
158
159static void initFileWriter(ProfDataWriter *This, FILE *File) {
160 This->Write = fileWriter;
161 This->WriterCtx = File;
162}
163
164COMPILER_RT_VISIBILITY__attribute__((visibility("hidden"))) ProfBufferIO *
165lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
166 FreeHook = &free;
167 DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
168 VPBufferSize = BufferSz;
169 ProfDataWriter *fileWriter =
170 (ProfDataWriter *)calloc(sizeof(ProfDataWriter), 1);
171 initFileWriter(fileWriter, File);
172 ProfBufferIO *IO = lprofCreateBufferIO(fileWriter);
173 IO->OwnFileWriter = 1;
174 return IO;
175}
176
177static void setupIOBuffer() {
178 const char *BufferSzStr = 0;
179 BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
180 if (BufferSzStr && BufferSzStr[0]) {
181 VPBufferSize = atoi(BufferSzStr);
182 DynamicBufferIOBuffer = (uint8_t *)calloc(VPBufferSize, 1);
183 }
184}
185
186/* Get the size of the profile file. If there are any errors, print the
187 * message under the assumption that the profile is being read for merging
188 * purposes, and return -1. Otherwise return the file size in the inout param
189 * \p ProfileFileSize. */
190static int getProfileFileSizeForMerging(FILE *ProfileFile,
191 uint64_t *ProfileFileSize) {
192 if (fseek(ProfileFile, 0L, SEEK_END2) == -1) {
193 PROF_ERR("Unable to merge profile data, unable to get size: %s\n",fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, unable to get size: %s\n"
, strerror((*__errno_location ())));
194 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, unable to get size: %s\n"
, strerror((*__errno_location ())));
;
195 return -1;
196 }
197 *ProfileFileSize = ftell(ProfileFile);
198
199 /* Restore file offset. */
200 if (fseek(ProfileFile, 0L, SEEK_SET0) == -1) {
201 PROF_ERR("Unable to merge profile data, unable to rewind: %s\n",fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, unable to rewind: %s\n"
, strerror((*__errno_location ())));
202 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, unable to rewind: %s\n"
, strerror((*__errno_location ())));
;
203 return -1;
204 }
205
206 if (*ProfileFileSize > 0 &&
207 *ProfileFileSize < sizeof(__llvm_profile_header)) {
208 PROF_WARN("Unable to merge profile data: %s\n",fprintf(stderr, "LLVM Profile Warning: " "Unable to merge profile data: %s\n"
, "source profile file is too small.");
209 "source profile file is too small.")fprintf(stderr, "LLVM Profile Warning: " "Unable to merge profile data: %s\n"
, "source profile file is too small.");
;
210 return -1;
211 }
212 return 0;
213}
214
215/* mmap() \p ProfileFile for profile merging purposes, assuming that an
216 * exclusive lock is held on the file and that \p ProfileFileSize is the
217 * length of the file. Return the mmap'd buffer in the inout variable
218 * \p ProfileBuffer. Returns -1 on failure. On success, the caller is
219 * responsible for unmapping the mmap'd buffer in \p ProfileBuffer. */
220static int mmapProfileForMerging(FILE *ProfileFile, uint64_t ProfileFileSize,
221 char **ProfileBuffer) {
222 *ProfileBuffer = mmap(NULL((void*)0), ProfileFileSize, PROT_READ0x1, MAP_SHARED0x01 | MAP_FILE0,
223 fileno(ProfileFile), 0);
224 if (*ProfileBuffer == MAP_FAILED((void *) -1)) {
225 PROF_ERR("Unable to merge profile data, mmap failed: %s\n",fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, mmap failed: %s\n"
, strerror((*__errno_location ())));
226 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, mmap failed: %s\n"
, strerror((*__errno_location ())));
;
227 return -1;
228 }
229
230 if (__llvm_profile_check_compatibility(*ProfileBuffer, ProfileFileSize)) {
231 (void)munmap(*ProfileBuffer, ProfileFileSize);
232 PROF_WARN("Unable to merge profile data: %s\n",fprintf(stderr, "LLVM Profile Warning: " "Unable to merge profile data: %s\n"
, "source profile file is not compatible.");
233 "source profile file is not compatible.")fprintf(stderr, "LLVM Profile Warning: " "Unable to merge profile data: %s\n"
, "source profile file is not compatible.");
;
234 return -1;
235 }
236 return 0;
237}
238
239/* Read profile data in \c ProfileFile and merge with in-memory
240 profile counters. Returns -1 if there is fatal error, otheriwse
241 0 is returned. Returning 0 does not mean merge is actually
242 performed. If merge is actually done, *MergeDone is set to 1.
243*/
244static int doProfileMerging(FILE *ProfileFile, int *MergeDone) {
245 uint64_t ProfileFileSize;
246 char *ProfileBuffer;
247
248 /* Get the size of the profile on disk. */
249 if (getProfileFileSizeForMerging(ProfileFile, &ProfileFileSize) == -1)
250 return -1;
251
252 /* Nothing to merge. */
253 if (!ProfileFileSize)
254 return 0;
255
256 /* mmap() the profile and check that it is compatible with the data in
257 * the current image. */
258 if (mmapProfileForMerging(ProfileFile, ProfileFileSize, &ProfileBuffer) == -1)
259 return -1;
260
261 /* Now start merging */
262 __llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize);
263
264 // Truncate the file in case merging of value profile did not happend to
265 // prevent from leaving garbage data at the end of the profile file.
266 COMPILER_RT_FTRUNCATE(ProfileFile, __llvm_profile_get_size_for_buffer())ftruncate(fileno(ProfileFile),__llvm_profile_get_size_for_buffer
())
;
267
268 (void)munmap(ProfileBuffer, ProfileFileSize);
269 *MergeDone = 1;
270
271 return 0;
272}
273
274/* Create the directory holding the file, if needed. */
275static void createProfileDir(const char *Filename) {
276 size_t Length = strlen(Filename);
277 if (lprofFindFirstDirSeparator(Filename)) {
278 char *Copy = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
279 strncpy(Copy, Filename, Length + 1)__builtin_strncpy (Copy, Filename, Length + 1);
280 __llvm_profile_recursive_mkdir(Copy);
281 }
282}
283
284/* Open the profile data for merging. It opens the file in r+b mode with
285 * file locking. If the file has content which is compatible with the
286 * current process, it also reads in the profile data in the file and merge
287 * it with in-memory counters. After the profile data is merged in memory,
288 * the original profile data is truncated and gets ready for the profile
289 * dumper. With profile merging enabled, each executable as well as any of
290 * its instrumented shared libraries dump profile data into their own data file.
291*/
292static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
293 FILE *ProfileFile = NULL((void*)0);
294 int rc;
295
296 ProfileFile = getProfileFile();
297 if (ProfileFile) {
298 lprofLockFileHandle(ProfileFile);
299 } else {
300 createProfileDir(ProfileFileName);
301 ProfileFile = lprofOpenFileEx(ProfileFileName);
302 }
303 if (!ProfileFile)
304 return NULL((void*)0);
305
306 rc = doProfileMerging(ProfileFile, MergeDone);
307 if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)ftruncate(fileno(ProfileFile),0L)) ||
308 fseek(ProfileFile, 0L, SEEK_SET0) == -1) {
309 PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName,fprintf(stderr, "LLVM Profile Error: " "Profile Merging of file %s failed: %s\n"
, ProfileFileName, strerror((*__errno_location ())));
310 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Profile Merging of file %s failed: %s\n"
, ProfileFileName, strerror((*__errno_location ())));
;
311 fclose(ProfileFile);
312 return NULL((void*)0);
313 }
314 return ProfileFile;
315}
316
317static FILE *getFileObject(const char *OutputName) {
318 FILE *File;
319 File = getProfileFile();
320 if (File != NULL((void*)0)) {
321 return File;
322 }
323
324 return fopen(OutputName, "ab");
325}
326
327/* Write profile data to file \c OutputName. */
328static int writeFile(const char *OutputName) {
329 int RetVal;
330 FILE *OutputFile;
331
332 int MergeDone = 0;
333 VPMergeHook = &lprofMergeValueProfData;
334 if (doMerging())
335 OutputFile = openFileForMerging(OutputName, &MergeDone);
336 else
337 OutputFile = getFileObject(OutputName);
338
339 if (!OutputFile)
340 return -1;
341
342 FreeHook = &free;
343 setupIOBuffer();
344 ProfDataWriter fileWriter;
345 initFileWriter(&fileWriter, OutputFile);
346 RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
347
348 if (OutputFile == getProfileFile()) {
349 fflush(OutputFile);
350 if (doMerging()) {
351 lprofUnlockFileHandle(OutputFile);
352 }
353 } else {
354 fclose(OutputFile);
355 }
356
357 return RetVal;
358}
359
360/* Write order data to file \c OutputName. */
361static int writeOrderFile(const char *OutputName) {
362 int RetVal;
363 FILE *OutputFile;
364
365 OutputFile = fopen(OutputName, "w");
366
367 if (!OutputFile) {
368 PROF_WARN("can't open file with mode ab: %s\n", OutputName)fprintf(stderr, "LLVM Profile Warning: " "can't open file with mode ab: %s\n"
, OutputName);
;
369 return -1;
370 }
371
372 FreeHook = &free;
373 setupIOBuffer();
374 const uint32_t *DataBegin = __llvm_profile_begin_orderfile();
375 RetVal = orderFileWriter(OutputFile, DataBegin);
376
377 fclose(OutputFile);
378 return RetVal;
379}
380
381#define LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE" "__LLVM_PROFILE_RT_INIT_ONCE"
382
383static void truncateCurrentFile(void) {
384 const char *Filename;
385 char *FilenameBuf;
386 FILE *File;
387 int Length;
388
389 Length = getCurFilenameLength();
390 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
391 Filename = getCurFilename(FilenameBuf, 0);
392 if (!Filename)
393 return;
394
395 /* Only create the profile directory and truncate an existing profile once.
396 * In continuous mode, this is necessary, as the profile is written-to by the
397 * runtime initializer. */
398 int initialized = getenv(LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE") != NULL((void*)0);
399 if (initialized)
400 return;
401#if defined(_WIN32)
402 _putenv(LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE" "=" LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE");
403#else
404 setenv(LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE", LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE", 1);
405#endif
406
407 /* Create the profile dir (even if online merging is enabled), so that
408 * the profile file can be set up if continuous mode is enabled. */
409 createProfileDir(Filename);
410
411 /* By pass file truncation to allow online raw profile merging. */
412 if (lprofCurFilename.MergePoolSize)
413 return;
414
415 /* Truncate the file. Later we'll reopen and append. */
416 File = fopen(Filename, "w");
417 if (!File)
418 return;
419 fclose(File);
420}
421
422#ifndef _MSC_VER
423static void assertIsZero(int *i) {
424 if (*i)
425 PROF_WARN("Expected flag to be 0, but got: %d\n", *i)fprintf(stderr, "LLVM Profile Warning: " "Expected flag to be 0, but got: %d\n"
, *i);
;
426}
427#endif
428
429#if !defined(__Fuchsia__) && !defined(_WIN32)
430/* Write a partial profile to \p Filename, which is required to be backed by
431 * the open file object \p File. */
432static int writeProfileWithFileObject(const char *Filename, FILE *File) {
433 setProfileFile(File);
434 int rc = writeFile(Filename);
435 if (rc)
436 PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Failed to write file \"%s\": %s\n"
, Filename, strerror((*__errno_location ())));
;
437 setProfileFile(NULL((void*)0));
438 return rc;
439}
440
441/* Unlock the profile \p File and clear the unlock flag. */
442static void unlockProfile(int *ProfileRequiresUnlock, FILE *File) {
443 if (!*ProfileRequiresUnlock) {
444 PROF_WARN("%s", "Expected to require profile unlock\n")fprintf(stderr, "LLVM Profile Warning: " "%s", "Expected to require profile unlock\n"
);
;
445 }
446 lprofUnlockFileHandle(File);
447 *ProfileRequiresUnlock = 0;
448}
449#endif // !defined(__Fuchsia__) && !defined(_WIN32)
450
451static void initializeProfileForContinuousMode(void) {
452 if (!__llvm_profile_is_continuous_mode_enabled())
453 return;
454
455#if defined(__Fuchsia__) || defined(_WIN32)
456 PROF_ERR("%s\n", "Continuous mode not yet supported on Fuchsia or Windows.")fprintf(stderr, "LLVM Profile Error: " "%s\n", "Continuous mode not yet supported on Fuchsia or Windows."
);
;
457#else // defined(__Fuchsia__) || defined(_WIN32)
458 /* Get the sizes of various profile data sections. Taken from
459 * __llvm_profile_get_size_for_buffer(). */
460 const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
461 const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
462 const uint64_t *CountersBegin = __llvm_profile_begin_counters();
463 const uint64_t *CountersEnd = __llvm_profile_end_counters();
464 const char *NamesBegin = __llvm_profile_begin_names();
465 const char *NamesEnd = __llvm_profile_end_names();
466 const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
467 uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
468 uint64_t CountersSize = CountersEnd - CountersBegin;
469
470 /* Check that the counter and data sections in this image are page-aligned. */
471 unsigned PageSize = getpagesize();
472 if ((intptr_t)CountersBegin % PageSize != 0) {
473 PROF_ERR("Counters section not page-aligned (start = %p, pagesz = %u).\n",fprintf(stderr, "LLVM Profile Error: " "Counters section not page-aligned (start = %p, pagesz = %u).\n"
, CountersBegin, PageSize);
474 CountersBegin, PageSize)fprintf(stderr, "LLVM Profile Error: " "Counters section not page-aligned (start = %p, pagesz = %u).\n"
, CountersBegin, PageSize);
;
475 return;
476 }
477 if ((intptr_t)DataBegin % PageSize != 0) {
478 PROF_ERR("Data section not page-aligned (start = %p, pagesz = %u).\n",fprintf(stderr, "LLVM Profile Error: " "Data section not page-aligned (start = %p, pagesz = %u).\n"
, DataBegin, PageSize);
479 DataBegin, PageSize)fprintf(stderr, "LLVM Profile Error: " "Data section not page-aligned (start = %p, pagesz = %u).\n"
, DataBegin, PageSize);
;
480 return;
481 }
482
483 int Length = getCurFilenameLength();
484 char *FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
485 const char *Filename = getCurFilename(FilenameBuf, 0);
486 if (!Filename)
487 return;
488
489 FILE *File = NULL((void*)0);
490 off_t CurrentFileOffset = 0;
491 off_t OffsetModPage = 0;
492
493 /* Whether an exclusive lock on the profile must be dropped after init.
494 * Use a cleanup to warn if the unlock does not occur. */
495 COMPILER_RT_CLEANUP(assertIsZero)__attribute__((cleanup(assertIsZero))) int ProfileRequiresUnlock = 0;
496
497 if (!doMerging()) {
498 /* We are not merging profiles, so open the raw profile in append mode. */
499 File = fopen(Filename, "a+b");
500 if (!File)
501 return;
502
503 /* Check that the offset within the file is page-aligned. */
504 CurrentFileOffset = ftello(File);
505 OffsetModPage = CurrentFileOffset % PageSize;
506 if (OffsetModPage != 0) {
507 PROF_ERR("Continuous counter sync mode is enabled, but raw profile is not"fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but raw profile is not"
"page-aligned. CurrentFileOffset = %" "l" "u" ", pagesz = %u.\n"
, (uint64_t)CurrentFileOffset, PageSize);
508 "page-aligned. CurrentFileOffset = %" PRIu64 ", pagesz = %u.\n",fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but raw profile is not"
"page-aligned. CurrentFileOffset = %" "l" "u" ", pagesz = %u.\n"
, (uint64_t)CurrentFileOffset, PageSize);
509 (uint64_t)CurrentFileOffset, PageSize)fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but raw profile is not"
"page-aligned. CurrentFileOffset = %" "l" "u" ", pagesz = %u.\n"
, (uint64_t)CurrentFileOffset, PageSize);
;
510 return;
511 }
512
513 /* Grow the profile so that mmap() can succeed. Leak the file handle, as
514 * the file should stay open. */
515 if (writeProfileWithFileObject(Filename, File) != 0)
516 return;
517 } else {
518 /* We are merging profiles. Map the counter section as shared memory into
519 * the profile, i.e. into each participating process. An increment in one
520 * process should be visible to every other process with the same counter
521 * section mapped. */
522 File = lprofOpenFileEx(Filename);
523 if (!File)
524 return;
525
526 ProfileRequiresUnlock = 1;
527
528 uint64_t ProfileFileSize;
529 if (getProfileFileSizeForMerging(File, &ProfileFileSize) == -1)
530 return unlockProfile(&ProfileRequiresUnlock, File);
531
532 if (ProfileFileSize == 0) {
533 /* Grow the profile so that mmap() can succeed. Leak the file handle, as
534 * the file should stay open. */
535 if (writeProfileWithFileObject(Filename, File) != 0)
536 return unlockProfile(&ProfileRequiresUnlock, File);
537 } else {
538 /* The merged profile has a non-zero length. Check that it is compatible
539 * with the data in this process. */
540 char *ProfileBuffer;
541 if (mmapProfileForMerging(File, ProfileFileSize, &ProfileBuffer) == -1 ||
542 munmap(ProfileBuffer, ProfileFileSize) == -1)
543 return unlockProfile(&ProfileRequiresUnlock, File);
544 }
545 }
546
547 int Fileno = fileno(File);
548
549 /* Determine how much padding is needed before/after the counters and after
550 * the names. */
551 uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
552 PaddingBytesAfterNames;
553 __llvm_profile_get_padding_sizes_for_counters(
554 DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
555 &PaddingBytesAfterCounters, &PaddingBytesAfterNames);
556
557 uint64_t PageAlignedCountersLength =
558 (CountersSize * sizeof(uint64_t)) + PaddingBytesAfterCounters;
559 uint64_t FileOffsetToCounters =
560 CurrentFileOffset + sizeof(__llvm_profile_header) +
561 (DataSize * sizeof(__llvm_profile_data)) + PaddingBytesBeforeCounters;
562
563 uint64_t *CounterMmap = (uint64_t *)mmap(
564 (void *)CountersBegin, PageAlignedCountersLength, PROT_READ0x1 | PROT_WRITE0x2,
565 MAP_FIXED0x10 | MAP_SHARED0x01, Fileno, FileOffsetToCounters);
566 if (CounterMmap != CountersBegin) {
567 PROF_ERR(fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"l" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"l" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
568 "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"l" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"l" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
569 " - CountersBegin: %p\n"fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"l" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"l" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
570 " - PageAlignedCountersLength: %" PRIu64 "\n"fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"l" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"l" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
571 " - Fileno: %d\n"fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"l" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"l" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
572 " - FileOffsetToCounters: %" PRIu64 "\n",fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"l" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"l" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
573 strerror(errno), CountersBegin, PageAlignedCountersLength, Fileno,fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"l" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"l" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
574 FileOffsetToCounters)fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"l" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"l" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
;
575 }
576
577 unlockProfile(&ProfileRequiresUnlock, File);
578#endif // defined(__Fuchsia__) || defined(_WIN32)
579}
580
581static const char *DefaultProfileName = "default.profraw";
582static void resetFilenameToDefault(void) {
583 if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
584 free((void *)lprofCurFilename.FilenamePat);
585 }
586 memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
587 lprofCurFilename.FilenamePat = DefaultProfileName;
588 lprofCurFilename.PNS = PNS_default;
589}
590
591static unsigned getMergePoolSize(const char *FilenamePat, int *I) {
592 unsigned J = 0, Num = 0;
593 for (;; ++J) {
594 char C = FilenamePat[*I + J];
595 if (C == 'm') {
596 *I += J;
597 return Num ? Num : 1;
598 }
599 if (C < '0' || C > '9')
600 break;
601 Num = Num * 10 + C - '0';
602
603 /* If FilenamePat[*I+J] is between '0' and '9', the next byte is guaranteed
604 * to be in-bound as the string is null terminated. */
605 }
606 return 0;
607}
608
609/* Parses the pattern string \p FilenamePat and stores the result to
610 * lprofcurFilename structure. */
611static int parseFilenamePattern(const char *FilenamePat,
612 unsigned CopyFilenamePat) {
613 int NumPids = 0, NumHosts = 0, I;
614 char *PidChars = &lprofCurFilename.PidChars[0];
615 char *Hostname = &lprofCurFilename.Hostname[0];
616 int MergingEnabled = 0;
617
618 /* Clean up cached prefix and filename. */
619 if (lprofCurFilename.ProfilePathPrefix)
12
Assuming field 'ProfilePathPrefix' is null
13
Taking false branch
620 free((void *)lprofCurFilename.ProfilePathPrefix);
621
622 if (lprofCurFilename.FilenamePat
13.1
Field 'FilenamePat' is non-null
&& lprofCurFilename.OwnsFilenamePat) {
14
Assuming field 'OwnsFilenamePat' is not equal to 0
15
Taking true branch
623 free((void *)lprofCurFilename.FilenamePat);
16
Memory is released
624 }
625
626 memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
627
628 if (!CopyFilenamePat
16.1
'CopyFilenamePat' is 1
)
17
Taking false branch
629 lprofCurFilename.FilenamePat = FilenamePat;
630 else {
631 lprofCurFilename.FilenamePat = strdup(FilenamePat)(__extension__ (__builtin_constant_p (FilenamePat) &&
((size_t)(const void *)((FilenamePat) + 1) - (size_t)(const void
*)(FilenamePat) == 1) ? (((const char *) (FilenamePat))[0] ==
'\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len
= strlen (FilenamePat) + 1; char *__retval = (char *) malloc
(__len); if (__retval != ((void*)0)) __retval = (char *) memcpy
(__retval, FilenamePat, __len); __retval; })) : __strdup (FilenamePat
)))
;
632 lprofCurFilename.OwnsFilenamePat = 1;
633 }
634 /* Check the filename for "%p", which indicates a pid-substitution. */
635 for (I = 0; FilenamePat[I]; ++I)
18
Loop condition is false. Execution continues on line 677
636 if (FilenamePat[I] == '%') {
637 if (FilenamePat[++I] == 'p') {
638 if (!NumPids++) {
639 if (snprintf(PidChars, MAX_PID_SIZE16, "%ld", (long)getpid()) <= 0) {
640 PROF_WARN("Unable to get pid for filename pattern %s. Using the "fprintf(stderr, "LLVM Profile Warning: " "Unable to get pid for filename pattern %s. Using the "
"default name.", FilenamePat);
641 "default name.",fprintf(stderr, "LLVM Profile Warning: " "Unable to get pid for filename pattern %s. Using the "
"default name.", FilenamePat);
642 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "Unable to get pid for filename pattern %s. Using the "
"default name.", FilenamePat);
;
643 return -1;
644 }
645 }
646 } else if (FilenamePat[I] == 'h') {
647 if (!NumHosts++)
648 if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)lprofGetHostName(Hostname, 128)) {
649 PROF_WARN("Unable to get hostname for filename pattern %s. Using "fprintf(stderr, "LLVM Profile Warning: " "Unable to get hostname for filename pattern %s. Using "
"the default name.", FilenamePat);
650 "the default name.",fprintf(stderr, "LLVM Profile Warning: " "Unable to get hostname for filename pattern %s. Using "
"the default name.", FilenamePat);
651 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "Unable to get hostname for filename pattern %s. Using "
"the default name.", FilenamePat);
;
652 return -1;
653 }
654 } else if (FilenamePat[I] == 'c') {
655 if (__llvm_profile_is_continuous_mode_enabled()) {
656 PROF_WARN("%%c specifier can only be specified once in %s.\n",fprintf(stderr, "LLVM Profile Warning: " "%%c specifier can only be specified once in %s.\n"
, FilenamePat);
657 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "%%c specifier can only be specified once in %s.\n"
, FilenamePat);
;
658 return -1;
659 }
660
661 __llvm_profile_enable_continuous_mode();
662 I++; /* advance to 'c' */
663 } else {
664 unsigned MergePoolSize = getMergePoolSize(FilenamePat, &I);
665 if (!MergePoolSize)
666 continue;
667 if (MergingEnabled) {
668 PROF_WARN("%%m specifier can only be specified once in %s.\n",fprintf(stderr, "LLVM Profile Warning: " "%%m specifier can only be specified once in %s.\n"
, FilenamePat);
669 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "%%m specifier can only be specified once in %s.\n"
, FilenamePat);
;
670 return -1;
671 }
672 MergingEnabled = 1;
673 lprofCurFilename.MergePoolSize = MergePoolSize;
674 }
675 }
676
677 lprofCurFilename.NumPids = NumPids;
678 lprofCurFilename.NumHosts = NumHosts;
679 return 0;
680}
681
682static void parseAndSetFilename(const char *FilenamePat,
683 ProfileNameSpecifier PNS,
684 unsigned CopyFilenamePat) {
685
686 const char *OldFilenamePat = lprofCurFilename.FilenamePat;
687 ProfileNameSpecifier OldPNS = lprofCurFilename.PNS;
688
689 /* The old profile name specifier takes precedence over the old one. */
690 if (PNS < OldPNS)
4
Assuming 'PNS' is >= 'OldPNS'
5
Taking false branch
691 return;
692
693 if (!FilenamePat)
6
Assuming 'FilenamePat' is non-null
7
Taking false branch
694 FilenamePat = DefaultProfileName;
695
696 if (OldFilenamePat && !strcmp(OldFilenamePat, FilenamePat)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(OldFilenamePat) && __builtin_constant_p (FilenamePat
) && (__s1_len = __builtin_strlen (OldFilenamePat), __s2_len
= __builtin_strlen (FilenamePat), (!((size_t)(const void *)(
(OldFilenamePat) + 1) - (size_t)(const void *)(OldFilenamePat
) == 1) || __s1_len >= 4) && (!((size_t)(const void
*)((FilenamePat) + 1) - (size_t)(const void *)(FilenamePat) ==
1) || __s2_len >= 4)) ? __builtin_strcmp (OldFilenamePat,
FilenamePat) : (__builtin_constant_p (OldFilenamePat) &&
((size_t)(const void *)((OldFilenamePat) + 1) - (size_t)(const
void *)(OldFilenamePat) == 1) && (__s1_len = __builtin_strlen
(OldFilenamePat), __s1_len < 4) ? (__builtin_constant_p (
FilenamePat) && ((size_t)(const void *)((FilenamePat)
+ 1) - (size_t)(const void *)(FilenamePat) == 1) ? __builtin_strcmp
(OldFilenamePat, FilenamePat) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (FilenamePat
); int __result = (((const unsigned char *) (const char *) (OldFilenamePat
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (OldFilenamePat
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (OldFilenamePat
))[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (OldFilenamePat
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
FilenamePat) && ((size_t)(const void *)((FilenamePat)
+ 1) - (size_t)(const void *)(FilenamePat) == 1) && (
__s2_len = __builtin_strlen (FilenamePat), __s2_len < 4) ?
(__builtin_constant_p (OldFilenamePat) && ((size_t)(
const void *)((OldFilenamePat) + 1) - (size_t)(const void *)(
OldFilenamePat) == 1) ? __builtin_strcmp (OldFilenamePat, FilenamePat
) : -(__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (OldFilenamePat); int __result = (((const
unsigned char *) (const char *) (FilenamePat))[0] - __s2[0])
; if (__s2_len > 0 && __result == 0) { __result = (
((const unsigned char *) (const char *) (FilenamePat))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (FilenamePat))[2]
- __s2[2]); if (__s2_len > 2 && __result == 0) __result
= (((const unsigned char *) (const char *) (FilenamePat))[3]
- __s2[3]); } } __result; }))) : __builtin_strcmp (OldFilenamePat
, FilenamePat)))); })
) {
8
Assuming 'OldFilenamePat' is non-null
9
Assuming the condition is false
10
Taking false branch
697 lprofCurFilename.PNS = PNS;
698 return;
699 }
700
701 /* When PNS >= OldPNS, the last one wins. */
702 if (!FilenamePat
10.1
'FilenamePat' is non-null
|| parseFilenamePattern(FilenamePat, CopyFilenamePat))
11
Calling 'parseFilenamePattern'
19
Returning; memory was released
20
Taking false branch
703 resetFilenameToDefault();
704 lprofCurFilename.PNS = PNS;
705
706 if (!OldFilenamePat
20.1
'OldFilenamePat' is non-null
) {
21
Taking false branch
707 if (getenv("LLVM_PROFILE_VERBOSE"))
708 PROF_NOTE("Set profile file path to \"%s\" via %s.\n",fprintf(stderr, "LLVM Profile Note: " "Set profile file path to \"%s\" via %s.\n"
, lprofCurFilename.FilenamePat, getPNSStr(PNS));
709 lprofCurFilename.FilenamePat, getPNSStr(PNS))fprintf(stderr, "LLVM Profile Note: " "Set profile file path to \"%s\" via %s.\n"
, lprofCurFilename.FilenamePat, getPNSStr(PNS));
;
710 } else {
711 if (getenv("LLVM_PROFILE_VERBOSE"))
22
Assuming the condition is true
23
Taking true branch
712 PROF_NOTE("Override old profile path \"%s\" via %s to \"%s\" via %s.\n",fprintf(stderr, "LLVM Profile Note: " "Override old profile path \"%s\" via %s to \"%s\" via %s.\n"
, OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat
, getPNSStr(PNS));
24
Use of memory after it is freed
713 OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat,fprintf(stderr, "LLVM Profile Note: " "Override old profile path \"%s\" via %s to \"%s\" via %s.\n"
, OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat
, getPNSStr(PNS));
714 getPNSStr(PNS))fprintf(stderr, "LLVM Profile Note: " "Override old profile path \"%s\" via %s to \"%s\" via %s.\n"
, OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat
, getPNSStr(PNS));
;
715 }
716
717 truncateCurrentFile();
718 initializeProfileForContinuousMode();
719}
720
721/* Return buffer length that is required to store the current profile
722 * filename with PID and hostname substitutions. */
723/* The length to hold uint64_t followed by 3 digits pool id including '_' */
724#define SIGLEN24 24
725static int getCurFilenameLength() {
726 int Len;
727 if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
728 return 0;
729
730 if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
731 lprofCurFilename.MergePoolSize))
732 return strlen(lprofCurFilename.FilenamePat);
733
734 Len = strlen(lprofCurFilename.FilenamePat) +
735 lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
736 lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2);
737 if (lprofCurFilename.MergePoolSize)
738 Len += SIGLEN24;
739 return Len;
740}
741
742/* Return the pointer to the current profile file name (after substituting
743 * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer
744 * to store the resulting filename. If no substitution is needed, the
745 * current filename pattern string is directly returned, unless ForceUseBuf
746 * is enabled. */
747static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
748 int I, J, PidLength, HostNameLength, FilenamePatLength;
749 const char *FilenamePat = lprofCurFilename.FilenamePat;
750
751 if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
752 return 0;
753
754 if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
755 lprofCurFilename.MergePoolSize ||
756 __llvm_profile_is_continuous_mode_enabled())) {
757 if (!ForceUseBuf)
758 return lprofCurFilename.FilenamePat;
759
760 FilenamePatLength = strlen(lprofCurFilename.FilenamePat);
761 memcpy(FilenameBuf, lprofCurFilename.FilenamePat, FilenamePatLength);
762 FilenameBuf[FilenamePatLength] = '\0';
763 return FilenameBuf;
764 }
765
766 PidLength = strlen(lprofCurFilename.PidChars);
767 HostNameLength = strlen(lprofCurFilename.Hostname);
768 /* Construct the new filename. */
769 for (I = 0, J = 0; FilenamePat[I]; ++I)
770 if (FilenamePat[I] == '%') {
771 if (FilenamePat[++I] == 'p') {
772 memcpy(FilenameBuf + J, lprofCurFilename.PidChars, PidLength);
773 J += PidLength;
774 } else if (FilenamePat[I] == 'h') {
775 memcpy(FilenameBuf + J, lprofCurFilename.Hostname, HostNameLength);
776 J += HostNameLength;
777 } else {
778 if (!getMergePoolSize(FilenamePat, &I))
779 continue;
780 char LoadModuleSignature[SIGLEN24 + 1];
781 int S;
782 int ProfilePoolId = getpid() % lprofCurFilename.MergePoolSize;
783 S = snprintf(LoadModuleSignature, SIGLEN24 + 1, "%" PRIu64"l" "u" "_%d",
784 lprofGetLoadModuleSignature(), ProfilePoolId);
785 if (S == -1 || S > SIGLEN24)
786 S = SIGLEN24;
787 memcpy(FilenameBuf + J, LoadModuleSignature, S);
788 J += S;
789 }
790 /* Drop any unknown substitutions. */
791 } else
792 FilenameBuf[J++] = FilenamePat[I];
793 FilenameBuf[J] = 0;
794
795 return FilenameBuf;
796}
797
798/* Returns the pointer to the environment variable
799 * string. Returns null if the env var is not set. */
800static const char *getFilenamePatFromEnv(void) {
801 const char *Filename = getenv("LLVM_PROFILE_FILE");
802 if (!Filename || !Filename[0])
803 return 0;
804 return Filename;
805}
806
807COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
808const char *__llvm_profile_get_path_prefix(void) {
809 int Length;
810 char *FilenameBuf, *Prefix;
811 const char *Filename, *PrefixEnd;
812
813 if (lprofCurFilename.ProfilePathPrefix)
814 return lprofCurFilename.ProfilePathPrefix;
815
816 Length = getCurFilenameLength();
817 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
818 Filename = getCurFilename(FilenameBuf, 0);
819 if (!Filename)
820 return "\0";
821
822 PrefixEnd = lprofFindLastDirSeparator(Filename);
823 if (!PrefixEnd)
824 return "\0";
825
826 Length = PrefixEnd - Filename + 1;
827 Prefix = (char *)malloc(Length + 1);
828 if (!Prefix) {
829 PROF_ERR("Failed to %s\n", "allocate memory.")fprintf(stderr, "LLVM Profile Error: " "Failed to %s\n", "allocate memory."
);
;
830 return "\0";
831 }
832 memcpy(Prefix, Filename, Length);
833 Prefix[Length] = '\0';
834 lprofCurFilename.ProfilePathPrefix = Prefix;
835 return Prefix;
836}
837
838COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
839const char *__llvm_profile_get_filename(void) {
840 int Length;
841 char *FilenameBuf;
842 const char *Filename;
843
844 Length = getCurFilenameLength();
845 FilenameBuf = (char *)malloc(Length + 1);
846 if (!FilenameBuf) {
847 PROF_ERR("Failed to %s\n", "allocate memory.")fprintf(stderr, "LLVM Profile Error: " "Failed to %s\n", "allocate memory."
);
;
848 return "\0";
849 }
850 Filename = getCurFilename(FilenameBuf, 1);
851 if (!Filename)
852 return "\0";
853
854 return FilenameBuf;
855}
856
857/* This method is invoked by the runtime initialization hook
858 * InstrProfilingRuntime.o if it is linked in. Both user specified
859 * profile path via -fprofile-instr-generate= and LLVM_PROFILE_FILE
860 * environment variable can override this default value. */
861COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
862void __llvm_profile_initialize_file(void) {
863 const char *EnvFilenamePat;
864 const char *SelectedPat = NULL((void*)0);
865 ProfileNameSpecifier PNS = PNS_unknown;
866 int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR__llvm_profile_filename[0] != 0);
867
868 EnvFilenamePat = getFilenamePatFromEnv();
869 if (EnvFilenamePat) {
870 /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
871 at the moment when __llvm_profile_write_file() gets executed. */
872 parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
873 return;
874 } else if (hasCommandLineOverrider) {
875 SelectedPat = INSTR_PROF_PROFILE_NAME_VAR__llvm_profile_filename;
876 PNS = PNS_command_line;
877 } else {
878 SelectedPat = NULL((void*)0);
879 PNS = PNS_default;
880 }
881
882 parseAndSetFilename(SelectedPat, PNS, 0);
883}
884
885/* This API is directly called by the user application code. It has the
886 * highest precedence compared with LLVM_PROFILE_FILE environment variable
887 * and command line option -fprofile-instr-generate=<profile_name>.
888 */
889COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
890void __llvm_profile_set_filename(const char *FilenamePat) {
891 if (__llvm_profile_is_continuous_mode_enabled())
1
Assuming the condition is false
2
Taking false branch
892 return;
893 parseAndSetFilename(FilenamePat, PNS_runtime_api, 1);
3
Calling 'parseAndSetFilename'
894}
895
896/* The public API for writing profile data into the file with name
897 * set by previous calls to __llvm_profile_set_filename or
898 * __llvm_profile_override_default_filename or
899 * __llvm_profile_initialize_file. */
900COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
901int __llvm_profile_write_file(void) {
902 int rc, Length;
903 const char *Filename;
904 char *FilenameBuf;
905 int PDeathSig = 0;
906
907 if (lprofProfileDumped() || __llvm_profile_is_continuous_mode_enabled()) {
908 PROF_NOTE("Profile data not written to file: %s.\n", "already written")fprintf(stderr, "LLVM Profile Note: " "Profile data not written to file: %s.\n"
, "already written");
;
909 return 0;
910 }
911
912 Length = getCurFilenameLength();
913 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
914 Filename = getCurFilename(FilenameBuf, 0);
915
916 /* Check the filename. */
917 if (!Filename) {
918 PROF_ERR("Failed to write file : %s\n", "Filename not set")fprintf(stderr, "LLVM Profile Error: " "Failed to write file : %s\n"
, "Filename not set");
;
919 return -1;
920 }
921
922 /* Check if there is llvm/runtime version mismatch. */
923 if (GET_VERSION(__llvm_profile_get_version())((__llvm_profile_get_version()) & ~0xff00000000000000ULL) != INSTR_PROF_RAW_VERSION5) {
924 PROF_ERR("Runtime and instrumentation version mismatch : "fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 5, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
925 "expected %d, but get %d\n",fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 5, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
926 INSTR_PROF_RAW_VERSION,fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 5, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
927 (int)GET_VERSION(__llvm_profile_get_version()))fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 5, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
;
928 return -1;
929 }
930
931 // Temporarily suspend getting SIGKILL when the parent exits.
932 PDeathSig = lprofSuspendSigKill();
933
934 /* Write profile data to the file. */
935 rc = writeFile(Filename);
936 if (rc)
937 PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Failed to write file \"%s\": %s\n"
, Filename, strerror((*__errno_location ())));
;
938
939 // Restore SIGKILL.
940 if (PDeathSig == 1)
941 lprofRestoreSigKill();
942
943 return rc;
944}
945
946COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
947int __llvm_profile_dump(void) {
948 if (!doMerging())
949 PROF_WARN("Later invocation of __llvm_profile_dump can lead to clobbering "fprintf(stderr, "LLVM Profile Warning: " "Later invocation of __llvm_profile_dump can lead to clobbering "
" of previously dumped profile data : %s. Either use %%m " "in profile name or change profile name before dumping.\n"
, "online profile merging is not on");
950 " of previously dumped profile data : %s. Either use %%m "fprintf(stderr, "LLVM Profile Warning: " "Later invocation of __llvm_profile_dump can lead to clobbering "
" of previously dumped profile data : %s. Either use %%m " "in profile name or change profile name before dumping.\n"
, "online profile merging is not on");
951 "in profile name or change profile name before dumping.\n",fprintf(stderr, "LLVM Profile Warning: " "Later invocation of __llvm_profile_dump can lead to clobbering "
" of previously dumped profile data : %s. Either use %%m " "in profile name or change profile name before dumping.\n"
, "online profile merging is not on");
952 "online profile merging is not on")fprintf(stderr, "LLVM Profile Warning: " "Later invocation of __llvm_profile_dump can lead to clobbering "
" of previously dumped profile data : %s. Either use %%m " "in profile name or change profile name before dumping.\n"
, "online profile merging is not on");
;
953 int rc = __llvm_profile_write_file();
954 lprofSetProfileDumped();
955 return rc;
956}
957
958/* Order file data will be saved in a file with suffx .order. */
959static const char *OrderFileSuffix = ".order";
960
961COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
962int __llvm_orderfile_write_file(void) {
963 int rc, Length, LengthBeforeAppend, SuffixLength;
964 const char *Filename;
965 char *FilenameBuf;
966 int PDeathSig = 0;
967
968 SuffixLength = strlen(OrderFileSuffix);
969 Length = getCurFilenameLength() + SuffixLength;
970 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
971 Filename = getCurFilename(FilenameBuf, 1);
972
973 /* Check the filename. */
974 if (!Filename) {
975 PROF_ERR("Failed to write file : %s\n", "Filename not set")fprintf(stderr, "LLVM Profile Error: " "Failed to write file : %s\n"
, "Filename not set");
;
976 return -1;
977 }
978
979 /* Append order file suffix */
980 LengthBeforeAppend = strlen(Filename);
981 memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength);
982 FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0';
983
984 /* Check if there is llvm/runtime version mismatch. */
985 if (GET_VERSION(__llvm_profile_get_version())((__llvm_profile_get_version()) & ~0xff00000000000000ULL) != INSTR_PROF_RAW_VERSION5) {
986 PROF_ERR("Runtime and instrumentation version mismatch : "fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 5, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
987 "expected %d, but get %d\n",fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 5, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
988 INSTR_PROF_RAW_VERSION,fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 5, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
989 (int)GET_VERSION(__llvm_profile_get_version()))fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 5, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
;
990 return -1;
991 }
992
993 // Temporarily suspend getting SIGKILL when the parent exits.
994 PDeathSig = lprofSuspendSigKill();
995
996 /* Write order data to the file. */
997 rc = writeOrderFile(Filename);
998 if (rc)
999 PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Failed to write file \"%s\": %s\n"
, Filename, strerror((*__errno_location ())));
;
1000
1001 // Restore SIGKILL.
1002 if (PDeathSig == 1)
1003 lprofRestoreSigKill();
1004
1005 return rc;
1006}
1007
1008COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
1009int __llvm_orderfile_dump(void) {
1010 int rc = __llvm_orderfile_write_file();
1011 return rc;
1012}
1013
1014static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }
1015
1016COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
1017int __llvm_profile_register_write_file_atexit(void) {
1018 static int HasBeenRegistered = 0;
1019
1020 if (HasBeenRegistered)
1021 return 0;
1022
1023 lprofSetupValueProfiler();
1024
1025 HasBeenRegistered = 1;
1026 return atexit(writeFileWithoutReturn);
1027}
1028
1029#endif