Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple i386-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 -fuse-init-array -target-cpu i686 -dwarf-column-info -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~+201911111502510600c19528f1809/build-llvm/projects/compiler-rt/lib/profile -I /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/compiler-rt/lib/profile -I /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/build-llvm/include -I /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/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 /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~+201911111502510600c19528f1809/build-llvm/projects/compiler-rt/lib/profile -fdebug-prefix-map=/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809=. -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-2019-12-11-181444-25759-1 -x c /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/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 for (I = 0; I < NumIOVecs; I++) {
126 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_CUR1) == -1)
132 return 1;
133 }
134 }
135 return 0;
136}
137
138/* 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_SIZE131072, File) !=
142 INSTR_ORDER_FILE_BUFFER_SIZE131072)
143 return 1;
144 return 0;
145}
146
147static void initFileWriter(ProfDataWriter *This, FILE *File) {
148 This->Write = fileWriter;
149 This->WriterCtx = File;
150}
151
152COMPILER_RT_VISIBILITY__attribute__((visibility("hidden"))) ProfBufferIO *
153lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
154 FreeHook = &free;
155 DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
156 VPBufferSize = BufferSz;
157 ProfDataWriter *fileWriter =
158 (ProfDataWriter *)calloc(sizeof(ProfDataWriter), 1);
159 initFileWriter(fileWriter, File);
160 ProfBufferIO *IO = lprofCreateBufferIO(fileWriter);
161 IO->OwnFileWriter = 1;
162 return IO;
163}
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 }
172}
173
174/* Read profile data in \c ProfileFile and merge with in-memory
175 profile counters. Returns -1 if there is fatal error, otheriwse
176 0 is returned. Returning 0 does not mean merge is actually
177 performed. If merge is actually done, *MergeDone is set to 1.
178*/
179static int doProfileMerging(FILE *ProfileFile, int *MergeDone) {
180 uint64_t ProfileFileSize;
181 char *ProfileBuffer;
182
183 if (fseek(ProfileFile, 0L, SEEK_END2) == -1) {
184 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 ())));
185 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, unable to get size: %s\n"
, strerror((*__errno_location ())));
;
186 return -1;
187 }
188 ProfileFileSize = ftell(ProfileFile);
189
190 /* Restore file offset. */
191 if (fseek(ProfileFile, 0L, SEEK_SET0) == -1) {
192 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 ())));
193 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, unable to rewind: %s\n"
, strerror((*__errno_location ())));
;
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",fprintf(stderr, "LLVM Profile Warning: " "Unable to merge profile data: %s\n"
, "source profile file is too small.");
201 "source profile file is too small.")fprintf(stderr, "LLVM Profile Warning: " "Unable to merge profile data: %s\n"
, "source profile file is too small.");
;
202 return 0;
203 }
204
205 ProfileBuffer = mmap(NULL((void*)0), ProfileFileSize, PROT_READ0x1, MAP_SHARED0x01 | MAP_FILE0,
206 fileno(ProfileFile), 0);
207 if (ProfileBuffer == MAP_FAILED((void *) -1)) {
208 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 ())));
209 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, mmap failed: %s\n"
, strerror((*__errno_location ())));
;
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",fprintf(stderr, "LLVM Profile Warning: " "Unable to merge profile data: %s\n"
, "source profile file is not compatible.");
216 "source profile file is not compatible.")fprintf(stderr, "LLVM Profile Warning: " "Unable to merge profile data: %s\n"
, "source profile file is not compatible.");
;
217 return 0;
218 }
219
220 /* Now start merging */
221 __llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize);
222
223 // 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.
225 COMPILER_RT_FTRUNCATE(ProfileFile, __llvm_profile_get_size_for_buffer())ftruncate(fileno(ProfileFile),__llvm_profile_get_size_for_buffer
())
;
226
227 (void)munmap(ProfileBuffer, ProfileFileSize);
228 *MergeDone = 1;
229
230 return 0;
231}
232
233/* 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__builtin_alloca(Length + 1);
238 strncpy(Copy, Filename, Length + 1)__builtin_strncpy (Copy, Filename, Length + 1);
239 __llvm_profile_recursive_mkdir(Copy);
240 }
241}
242
243/* 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*/
251static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
252 FILE *ProfileFile = NULL((void*)0);
253 int rc;
254
255 ProfileFile = getProfileFile();
256 if (ProfileFile) {
257 lprofLockFileHandle(ProfileFile);
258 } else {
259 createProfileDir(ProfileFileName);
260 ProfileFile = lprofOpenFileEx(ProfileFileName);
261 }
262 if (!ProfileFile)
263 return NULL((void*)0);
264
265 rc = doProfileMerging(ProfileFile, MergeDone);
266 if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)ftruncate(fileno(ProfileFile),0L)) ||
267 fseek(ProfileFile, 0L, SEEK_SET0) == -1) {
268 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 ())));
269 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Profile Merging of file %s failed: %s\n"
, ProfileFileName, strerror((*__errno_location ())));
;
270 fclose(ProfileFile);
271 return NULL((void*)0);
272 }
273 return ProfileFile;
274}
275
276static FILE *getFileObject(const char *OutputName) {
277 FILE *File;
278 File = getProfileFile();
279 if (File != NULL((void*)0)) {
280 return File;
281 }
282
283 return fopen(OutputName, "ab");
284}
285
286/* Write profile data to file \c OutputName. */
287static int writeFile(const char *OutputName) {
288 int RetVal;
289 FILE *OutputFile;
290
291 int MergeDone = 0;
292 VPMergeHook = &lprofMergeValueProfData;
293 if (doMerging())
294 OutputFile = openFileForMerging(OutputName, &MergeDone);
295 else
296 OutputFile = getFileObject(OutputName);
297
298 if (!OutputFile)
299 return -1;
300
301 FreeHook = &free;
302 setupIOBuffer();
303 ProfDataWriter fileWriter;
304 initFileWriter(&fileWriter, OutputFile);
305 RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
306
307 if (OutputFile == getProfileFile()) {
308 fflush(OutputFile);
309 if (doMerging()) {
310 lprofUnlockFileHandle(OutputFile);
311 }
312 } else {
313 fclose(OutputFile);
314 }
315
316 return RetVal;
317}
318
319/* 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)fprintf(stderr, "LLVM Profile Warning: " "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
340#define LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE" "__LLVM_PROFILE_RT_INIT_ONCE"
341
342static void truncateCurrentFile(void) {
343 const char *Filename;
344 char *FilenameBuf;
345 FILE *File;
346 int Length;
347
348 Length = getCurFilenameLength();
349 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
350 Filename = getCurFilename(FilenameBuf, 0);
351 if (!Filename)
352 return;
353
354 /* By pass file truncation to allow online raw profile
355 * merging. */
356 if (lprofCurFilename.MergePoolSize)
357 return;
358
359 /* Only create the profile directory and truncate an existing profile once.
360 * In continuous mode, this is necessary, as the profile is written-to by the
361 * runtime initializer. */
362 int initialized = getenv(LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE") != NULL((void*)0);
363 if (initialized)
364 return;
365#if defined(_WIN32)
366 _putenv(LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE" "=" LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE");
367#else
368 setenv(LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE", LPROF_INIT_ONCE_ENV"__LLVM_PROFILE_RT_INIT_ONCE", 1);
369#endif
370
371 createProfileDir(Filename);
372
373 /* Truncate the file. Later we'll reopen and append. */
374 File = fopen(Filename, "w");
375 if (!File)
376 return;
377 fclose(File);
378}
379
380static void initializeProfileForContinuousMode(void) {
381#if defined(__Fuchsia__) || defined(_WIN32)
382 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."
);
;
383#else // defined(__Fuchsia__) || defined(_WIN32)
384 if (!__llvm_profile_is_continuous_mode_enabled())
385 return;
386
387 /* Get the sizes of various profile data sections. Taken from
388 * __llvm_profile_get_size_for_buffer(). */
389 const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
390 const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
391 const uint64_t *CountersBegin = __llvm_profile_begin_counters();
392 const uint64_t *CountersEnd = __llvm_profile_end_counters();
393 const char *NamesBegin = __llvm_profile_begin_names();
394 const char *NamesEnd = __llvm_profile_end_names();
395 const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
396 uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
397 uint64_t CountersSize = CountersEnd - CountersBegin;
398
399 /* Check that the counter and data sections in this image are page-aligned. */
400 unsigned PageSize = getpagesize();
401 if ((intptr_t)CountersBegin % PageSize != 0) {
402 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);
403 CountersBegin, PageSize)fprintf(stderr, "LLVM Profile Error: " "Counters section not page-aligned (start = %p, pagesz = %u).\n"
, CountersBegin, PageSize);
;
404 return;
405 }
406 if ((intptr_t)DataBegin % PageSize != 0) {
407 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);
408 DataBegin, PageSize)fprintf(stderr, "LLVM Profile Error: " "Data section not page-aligned (start = %p, pagesz = %u).\n"
, DataBegin, PageSize);
;
409 return;
410 }
411
412 /* Open the raw profile in append mode. */
413 int Length = getCurFilenameLength();
414 char *FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
415 const char *Filename = getCurFilename(FilenameBuf, 0);
416 if (!Filename)
417 return;
418 FILE *File = fopen(Filename, "a+b");
419 if (!File)
420 return;
421
422 int Fileno = fileno(File);
423
424 /* Check that the offset within the file is page-aligned. */
425 off_t CurrentFileOffset = ftello(File);
426 off_t OffsetModPage = CurrentFileOffset % PageSize;
427 if (OffsetModPage != 0) {
428 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 = %" "ll" "u" ", pagesz = %u.\n"
, (uint64_t) CurrentFileOffset, PageSize);
429 "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 = %" "ll" "u" ", pagesz = %u.\n"
, (uint64_t) CurrentFileOffset, PageSize);
430 (uint64_t) CurrentFileOffset, PageSize)fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but raw profile is not"
"page-aligned. CurrentFileOffset = %" "ll" "u" ", pagesz = %u.\n"
, (uint64_t) CurrentFileOffset, PageSize);
;
431 return;
432 }
433
434 /* Determine how much padding is needed before/after the counters and after
435 * the names. */
436 uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
437 PaddingBytesAfterNames;
438 __llvm_profile_get_padding_sizes_for_counters(
439 DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
440 &PaddingBytesAfterCounters, &PaddingBytesAfterNames);
441
442 uint64_t PageAlignedCountersLength =
443 (CountersSize * sizeof(uint64_t)) + PaddingBytesAfterCounters;
444 uint64_t FileOffsetToCounters =
445 CurrentFileOffset + sizeof(__llvm_profile_header) +
446 (DataSize * sizeof(__llvm_profile_data)) + PaddingBytesBeforeCounters;
447
448 /* Write the partial profile. This grows the file to a point where the mmap()
449 * can succeed. Leak the file handle, as the file should stay open. */
450 setProfileFile(File);
451 int rc = writeFile(Filename);
452 if (rc)
453 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 ())));
;
454 setProfileFile(NULL((void*)0));
455
456 uint64_t *CounterMmap = (uint64_t *)mmap(
457 (void *)CountersBegin, PageAlignedCountersLength, PROT_READ0x1 | PROT_WRITE0x2,
458 MAP_FIXED0x10 | MAP_SHARED0x01, Fileno, FileOffsetToCounters);
459 if (CounterMmap != CountersBegin) {
460 PROF_ERR(fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"ll" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"ll" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
461 "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: %"
"ll" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"ll" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
462 " - CountersBegin: %p\n"fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"ll" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"ll" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
463 " - PageAlignedCountersLength: %" PRIu64 "\n"fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"ll" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"ll" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
464 " - Fileno: %d\n"fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"ll" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"ll" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
465 " - FileOffsetToCounters: %" PRIu64 "\n",fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"ll" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"ll" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
466 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: %"
"ll" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"ll" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
467 FileOffsetToCounters)fprintf(stderr, "LLVM Profile Error: " "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
" - CountersBegin: %p\n" " - PageAlignedCountersLength: %"
"ll" "u" "\n" " - Fileno: %d\n" " - FileOffsetToCounters: %"
"ll" "u" "\n", strerror((*__errno_location ())), CountersBegin
, PageAlignedCountersLength, Fileno, FileOffsetToCounters);
;
468 return;
469 }
470#endif // defined(__Fuchsia__) || defined(_WIN32)
471}
472
473static const char *DefaultProfileName = "default.profraw";
474static void resetFilenameToDefault(void) {
475 if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
476 free((void *)lprofCurFilename.FilenamePat);
477 }
478 memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
479 lprofCurFilename.FilenamePat = DefaultProfileName;
480 lprofCurFilename.PNS = PNS_default;
481}
482
483static int containsMergeSpecifier(const char *FilenamePat, int I) {
484 return (FilenamePat[I] == 'm' ||
485 (FilenamePat[I] >= '1' && FilenamePat[I] <= '9' &&
486 /* If FilenamePat[I] is not '\0', the next byte is guaranteed
487 * to be in-bound as the string is null terminated. */
488 FilenamePat[I + 1] == 'm'));
489}
490
491/* Parses the pattern string \p FilenamePat and stores the result to
492 * lprofcurFilename structure. */
493static int parseFilenamePattern(const char *FilenamePat,
494 unsigned CopyFilenamePat) {
495 int NumPids = 0, NumHosts = 0, I;
496 char *PidChars = &lprofCurFilename.PidChars[0];
497 char *Hostname = &lprofCurFilename.Hostname[0];
498 int MergingEnabled = 0;
499
500 /* Clean up cached prefix and filename. */
501 if (lprofCurFilename.ProfilePathPrefix)
12
Assuming field 'ProfilePathPrefix' is null
13
Taking false branch
502 free((void *)lprofCurFilename.ProfilePathPrefix);
503
504 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
505 free((void *)lprofCurFilename.FilenamePat);
16
Memory is released
506 }
507
508 memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
509
510 if (!CopyFilenamePat
16.1
'CopyFilenamePat' is 1
)
17
Taking false branch
511 lprofCurFilename.FilenamePat = FilenamePat;
512 else {
513 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
)))
;
514 lprofCurFilename.OwnsFilenamePat = 1;
515 }
516 /* Check the filename for "%p", which indicates a pid-substitution. */
517 for (I = 0; FilenamePat[I]; ++I)
18
Loop condition is false. Execution continues on line 573
518 if (FilenamePat[I] == '%') {
519 if (FilenamePat[++I] == 'p') {
520 if (!NumPids++) {
521 if (snprintf(PidChars, MAX_PID_SIZE16, "%ld", (long)getpid()) <= 0) {
522 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);
523 "default name.",fprintf(stderr, "LLVM Profile Warning: " "Unable to get pid for filename pattern %s. Using the "
"default name.", FilenamePat);
524 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "Unable to get pid for filename pattern %s. Using the "
"default name.", FilenamePat);
;
525 return -1;
526 }
527 }
528 } else if (FilenamePat[I] == 'h') {
529 if (!NumHosts++)
530 if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)lprofGetHostName(Hostname, 128)) {
531 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);
532 "the default name.",fprintf(stderr, "LLVM Profile Warning: " "Unable to get hostname for filename pattern %s. Using "
"the default name.", FilenamePat);
533 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "Unable to get hostname for filename pattern %s. Using "
"the default name.", FilenamePat);
;
534 return -1;
535 }
536 } else if (FilenamePat[I] == 'c') {
537 if (__llvm_profile_is_continuous_mode_enabled()) {
538 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);
539 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "%%c specifier can only be specified once in %s.\n"
, FilenamePat);
;
540 return -1;
541 }
542 if (MergingEnabled) {
543 PROF_WARN("%%c specifier can not be used with profile merging (%%m) "fprintf(stderr, "LLVM Profile Warning: " "%%c specifier can not be used with profile merging (%%m) "
"in %s.\n", FilenamePat);
544 "in %s.\n",fprintf(stderr, "LLVM Profile Warning: " "%%c specifier can not be used with profile merging (%%m) "
"in %s.\n", FilenamePat);
545 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "%%c specifier can not be used with profile merging (%%m) "
"in %s.\n", FilenamePat);
;
546 return -1;
547 }
548
549 __llvm_profile_enable_continuous_mode();
550 I++; /* advance to 'c' */
551 } else if (containsMergeSpecifier(FilenamePat, I)) {
552 if (MergingEnabled) {
553 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);
554 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "%%m specifier can only be specified once in %s.\n"
, FilenamePat);
;
555 return -1;
556 }
557 if (__llvm_profile_is_continuous_mode_enabled()) {
558 PROF_WARN("%%c specifier can not be used with profile merging (%%m) "fprintf(stderr, "LLVM Profile Warning: " "%%c specifier can not be used with profile merging (%%m) "
"in %s.\n", FilenamePat);
559 "in %s.\n",fprintf(stderr, "LLVM Profile Warning: " "%%c specifier can not be used with profile merging (%%m) "
"in %s.\n", FilenamePat);
560 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "%%c specifier can not be used with profile merging (%%m) "
"in %s.\n", FilenamePat);
;
561 return -1;
562 }
563 MergingEnabled = 1;
564 if (FilenamePat[I] == 'm')
565 lprofCurFilename.MergePoolSize = 1;
566 else {
567 lprofCurFilename.MergePoolSize = FilenamePat[I] - '0';
568 I++; /* advance to 'm' */
569 }
570 }
571 }
572
573 lprofCurFilename.NumPids = NumPids;
574 lprofCurFilename.NumHosts = NumHosts;
575 return 0;
576}
577
578static void parseAndSetFilename(const char *FilenamePat,
579 ProfileNameSpecifier PNS,
580 unsigned CopyFilenamePat) {
581
582 const char *OldFilenamePat = lprofCurFilename.FilenamePat;
583 ProfileNameSpecifier OldPNS = lprofCurFilename.PNS;
584
585 /* The old profile name specifier takes precedence over the old one. */
586 if (PNS < OldPNS)
4
Assuming 'PNS' is >= 'OldPNS'
5
Taking false branch
587 return;
588
589 if (!FilenamePat)
6
Assuming 'FilenamePat' is non-null
7
Taking false branch
590 FilenamePat = DefaultProfileName;
591
592 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
593 lprofCurFilename.PNS = PNS;
594 return;
595 }
596
597 /* When PNS >= OldPNS, the last one wins. */
598 if (!FilenamePat
10.1
'FilenamePat' is non-null
|| parseFilenamePattern(FilenamePat, CopyFilenamePat))
11
Calling 'parseFilenamePattern'
19
Returning; memory was released
20
Taking false branch
599 resetFilenameToDefault();
600 lprofCurFilename.PNS = PNS;
601
602 if (!OldFilenamePat
20.1
'OldFilenamePat' is non-null
) {
21
Taking false branch
603 if (getenv("LLVM_PROFILE_VERBOSE"))
604 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));
605 lprofCurFilename.FilenamePat, getPNSStr(PNS))fprintf(stderr, "LLVM Profile Note: " "Set profile file path to \"%s\" via %s.\n"
, lprofCurFilename.FilenamePat, getPNSStr(PNS));
;
606 } else {
607 if (getenv("LLVM_PROFILE_VERBOSE"))
22
Assuming the condition is true
23
Taking true branch
608 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
609 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));
610 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));
;
611 }
612
613 truncateCurrentFile();
614 initializeProfileForContinuousMode();
615}
616
617/* Return buffer length that is required to store the current profile
618 * filename with PID and hostname substitutions. */
619/* The length to hold uint64_t followed by 2 digit pool id including '_' */
620#define SIGLEN24 24
621static int getCurFilenameLength() {
622 int Len;
623 if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
624 return 0;
625
626 if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
627 lprofCurFilename.MergePoolSize))
628 return strlen(lprofCurFilename.FilenamePat);
629
630 Len = strlen(lprofCurFilename.FilenamePat) +
631 lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
632 lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2);
633 if (lprofCurFilename.MergePoolSize)
634 Len += SIGLEN24;
635 return Len;
636}
637
638/* Return the pointer to the current profile file name (after substituting
639 * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer
640 * to store the resulting filename. If no substitution is needed, the
641 * current filename pattern string is directly returned, unless ForceUseBuf
642 * is enabled. */
643static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
644 int I, J, PidLength, HostNameLength, FilenamePatLength;
645 const char *FilenamePat = lprofCurFilename.FilenamePat;
646
647 if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
648 return 0;
649
650 if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
651 lprofCurFilename.MergePoolSize ||
652 __llvm_profile_is_continuous_mode_enabled())) {
653 if (!ForceUseBuf)
654 return lprofCurFilename.FilenamePat;
655
656 FilenamePatLength = strlen(lprofCurFilename.FilenamePat);
657 memcpy(FilenameBuf, lprofCurFilename.FilenamePat, FilenamePatLength);
658 FilenameBuf[FilenamePatLength] = '\0';
659 return FilenameBuf;
660 }
661
662 PidLength = strlen(lprofCurFilename.PidChars);
663 HostNameLength = strlen(lprofCurFilename.Hostname);
664 /* Construct the new filename. */
665 for (I = 0, J = 0; FilenamePat[I]; ++I)
666 if (FilenamePat[I] == '%') {
667 if (FilenamePat[++I] == 'p') {
668 memcpy(FilenameBuf + J, lprofCurFilename.PidChars, PidLength);
669 J += PidLength;
670 } else if (FilenamePat[I] == 'h') {
671 memcpy(FilenameBuf + J, lprofCurFilename.Hostname, HostNameLength);
672 J += HostNameLength;
673 } else if (containsMergeSpecifier(FilenamePat, I)) {
674 char LoadModuleSignature[SIGLEN24];
675 int S;
676 int ProfilePoolId = getpid() % lprofCurFilename.MergePoolSize;
677 S = snprintf(LoadModuleSignature, SIGLEN24, "%" PRIu64"ll" "u" "_%d",
678 lprofGetLoadModuleSignature(), ProfilePoolId);
679 if (S == -1 || S > SIGLEN24)
680 S = SIGLEN24;
681 memcpy(FilenameBuf + J, LoadModuleSignature, S);
682 J += S;
683 if (FilenamePat[I] != 'm')
684 I++;
685 }
686 /* Drop any unknown substitutions. */
687 } else
688 FilenameBuf[J++] = FilenamePat[I];
689 FilenameBuf[J] = 0;
690
691 return FilenameBuf;
692}
693
694/* Returns the pointer to the environment variable
695 * string. Returns null if the env var is not set. */
696static const char *getFilenamePatFromEnv(void) {
697 const char *Filename = getenv("LLVM_PROFILE_FILE");
698 if (!Filename || !Filename[0])
699 return 0;
700 return Filename;
701}
702
703COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
704const char *__llvm_profile_get_path_prefix(void) {
705 int Length;
706 char *FilenameBuf, *Prefix;
707 const char *Filename, *PrefixEnd;
708
709 if (lprofCurFilename.ProfilePathPrefix)
710 return lprofCurFilename.ProfilePathPrefix;
711
712 Length = getCurFilenameLength();
713 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
714 Filename = getCurFilename(FilenameBuf, 0);
715 if (!Filename)
716 return "\0";
717
718 PrefixEnd = lprofFindLastDirSeparator(Filename);
719 if (!PrefixEnd)
720 return "\0";
721
722 Length = PrefixEnd - Filename + 1;
723 Prefix = (char *)malloc(Length + 1);
724 if (!Prefix) {
725 PROF_ERR("Failed to %s\n", "allocate memory.")fprintf(stderr, "LLVM Profile Error: " "Failed to %s\n", "allocate memory."
);
;
726 return "\0";
727 }
728 memcpy(Prefix, Filename, Length);
729 Prefix[Length] = '\0';
730 lprofCurFilename.ProfilePathPrefix = Prefix;
731 return Prefix;
732}
733
734COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
735const char *__llvm_profile_get_filename(void) {
736 int Length;
737 char *FilenameBuf;
738 const char *Filename;
739
740 Length = getCurFilenameLength();
741 FilenameBuf = (char *)malloc(Length + 1);
742 if (!FilenameBuf) {
743 PROF_ERR("Failed to %s\n", "allocate memory.")fprintf(stderr, "LLVM Profile Error: " "Failed to %s\n", "allocate memory."
);
;
744 return "\0";
745 }
746 Filename = getCurFilename(FilenameBuf, 1);
747 if (!Filename)
748 return "\0";
749
750 return FilenameBuf;
751}
752
753/* This method is invoked by the runtime initialization hook
754 * InstrProfilingRuntime.o if it is linked in. Both user specified
755 * profile path via -fprofile-instr-generate= and LLVM_PROFILE_FILE
756 * environment variable can override this default value. */
757COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
758void __llvm_profile_initialize_file(void) {
759 const char *EnvFilenamePat;
760 const char *SelectedPat = NULL((void*)0);
761 ProfileNameSpecifier PNS = PNS_unknown;
762 int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR__llvm_profile_filename[0] != 0);
763
764 EnvFilenamePat = getFilenamePatFromEnv();
765 if (EnvFilenamePat) {
766 /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
767 at the moment when __llvm_profile_write_file() gets executed. */
768 parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
769 return;
770 } else if (hasCommandLineOverrider) {
771 SelectedPat = INSTR_PROF_PROFILE_NAME_VAR__llvm_profile_filename;
772 PNS = PNS_command_line;
773 } else {
774 SelectedPat = NULL((void*)0);
775 PNS = PNS_default;
776 }
777
778 parseAndSetFilename(SelectedPat, PNS, 0);
779}
780
781/* This API is directly called by the user application code. It has the
782 * highest precedence compared with LLVM_PROFILE_FILE environment variable
783 * and command line option -fprofile-instr-generate=<profile_name>.
784 */
785COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
786void __llvm_profile_set_filename(const char *FilenamePat) {
787 if (__llvm_profile_is_continuous_mode_enabled())
1
Assuming the condition is false
2
Taking false branch
788 return;
789 parseAndSetFilename(FilenamePat, PNS_runtime_api, 1);
3
Calling 'parseAndSetFilename'
790}
791
792/* The public API for writing profile data into the file with name
793 * set by previous calls to __llvm_profile_set_filename or
794 * __llvm_profile_override_default_filename or
795 * __llvm_profile_initialize_file. */
796COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
797int __llvm_profile_write_file(void) {
798 int rc, Length;
799 const char *Filename;
800 char *FilenameBuf;
801 int PDeathSig = 0;
802
803 if (lprofProfileDumped() || __llvm_profile_is_continuous_mode_enabled()) {
804 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");
;
805 return 0;
806 }
807
808 Length = getCurFilenameLength();
809 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
810 Filename = getCurFilename(FilenameBuf, 0);
811
812 /* Check the filename. */
813 if (!Filename) {
814 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");
;
815 return -1;
816 }
817
818 /* Check if there is llvm/runtime version mismatch. */
819 if (GET_VERSION(__llvm_profile_get_version())((__llvm_profile_get_version()) & ~0xff00000000000000ULL) != INSTR_PROF_RAW_VERSION5) {
820 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));
821 "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));
822 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));
823 (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));
;
824 return -1;
825 }
826
827 // Temporarily suspend getting SIGKILL when the parent exits.
828 PDeathSig = lprofSuspendSigKill();
829
830 /* Write profile data to the file. */
831 rc = writeFile(Filename);
832 if (rc)
833 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 ())));
;
834
835 // Restore SIGKILL.
836 if (PDeathSig == 1)
837 lprofRestoreSigKill();
838
839 return rc;
840}
841
842COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
843int __llvm_profile_dump(void) {
844 if (!doMerging())
845 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");
846 " 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");
847 "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");
848 "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");
;
849 int rc = __llvm_profile_write_file();
850 lprofSetProfileDumped();
851 return rc;
852}
853
854/* Order file data will be saved in a file with suffx .order. */
855static const char *OrderFileSuffix = ".order";
856
857COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
858int __llvm_orderfile_write_file(void) {
859 int rc, Length, LengthBeforeAppend, SuffixLength;
860 const char *Filename;
861 char *FilenameBuf;
862 int PDeathSig = 0;
863
864 SuffixLength = strlen(OrderFileSuffix);
865 Length = getCurFilenameLength() + SuffixLength;
866 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
867 Filename = getCurFilename(FilenameBuf, 1);
868
869 /* Check the filename. */
870 if (!Filename) {
871 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");
;
872 return -1;
873 }
874
875 /* Append order file suffix */
876 LengthBeforeAppend = strlen(Filename);
877 memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength);
878 FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0';
879
880 /* Check if there is llvm/runtime version mismatch. */
881 if (GET_VERSION(__llvm_profile_get_version())((__llvm_profile_get_version()) & ~0xff00000000000000ULL) != INSTR_PROF_RAW_VERSION5) {
882 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));
883 "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));
884 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));
885 (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));
;
886 return -1;
887 }
888
889 // Temporarily suspend getting SIGKILL when the parent exits.
890 PDeathSig = lprofSuspendSigKill();
891
892 /* Write order data to the file. */
893 rc = writeOrderFile(Filename);
894 if (rc)
895 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 ())));
;
896
897 // Restore SIGKILL.
898 if (PDeathSig == 1)
899 lprofRestoreSigKill();
900
901 return rc;
902}
903
904COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
905int __llvm_orderfile_dump(void) {
906 int rc = __llvm_orderfile_write_file();
907 return rc;
908}
909
910static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }
911
912COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
913int __llvm_profile_register_write_file_atexit(void) {
914 static int HasBeenRegistered = 0;
915
916 if (HasBeenRegistered)
917 return 0;
918
919 lprofSetupValueProfiler();
920
921 HasBeenRegistered = 1;
922 return atexit(writeFileWithoutReturn);
923}
924
925#endif