Bug Summary

File:projects/compiler-rt/lib/profile/InstrProfilingFile.c
Warning:line 475, 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 -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=none -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -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~svn374877/build-llvm/projects/compiler-rt/lib/profile -I /build/llvm-toolchain-snapshot-10~svn374877/projects/compiler-rt/lib/profile -I /build/llvm-toolchain-snapshot-10~svn374877/build-llvm/include -I /build/llvm-toolchain-snapshot-10~svn374877/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~svn374877/build-llvm/projects/compiler-rt/lib/profile -fdebug-prefix-map=/build/llvm-toolchain-snapshot-10~svn374877=. -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-10-15-233810-7101-1 -x c /build/llvm-toolchain-snapshot-10~svn374877/projects/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 "InstrProfilingUtil.h"
36
37/* From where is profile name specified.
38 * The order the enumerators define their
39 * precedence. Re-order them may lead to
40 * runtime behavior change. */
41typedef enum ProfileNameSpecifier {
42 PNS_unknown = 0,
43 PNS_default,
44 PNS_command_line,
45 PNS_environment,
46 PNS_runtime_api
47} ProfileNameSpecifier;
48
49static const char *getPNSStr(ProfileNameSpecifier PNS) {
50 switch (PNS) {
51 case PNS_default:
52 return "default setting";
53 case PNS_command_line:
54 return "command line";
55 case PNS_environment:
56 return "environment variable";
57 case PNS_runtime_api:
58 return "runtime API";
59 default:
60 return "Unknown";
61 }
62}
63
64#define MAX_PID_SIZE16 16
65/* Data structure holding the result of parsed filename pattern. */
66typedef struct lprofFilename {
67 /* File name string possibly with %p or %h specifiers. */
68 const char *FilenamePat;
69 /* A flag indicating if FilenamePat's memory is allocated
70 * by runtime. */
71 unsigned OwnsFilenamePat;
72 const char *ProfilePathPrefix;
73 const char *Filename;
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
89COMPILER_RT_WEAK__attribute__((weak)) lprofFilename lprofCurFilename = {0, 0, 0, 0, {0},
90 {0}, 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 setProfileFile(File);
105 setProfileMergeRequested(EnableMerge);
106}
107
108static int getCurFilenameLength();
109static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf);
110static unsigned doMerging() {
111 return lprofCurFilename.MergePoolSize || isProfileMergeRequested();
112}
113
114/* Return 1 if there is an error, otherwise return 0. */
115static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
116 uint32_t NumIOVecs) {
117 uint32_t I;
118 FILE *File = (FILE *)This->WriterCtx;
119 for (I = 0; I < NumIOVecs; I++) {
120 if (IOVecs[I].Data) {
121 if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
122 IOVecs[I].NumElm)
123 return 1;
124 } else {
125 if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR1) == -1)
126 return 1;
127 }
128 }
129 return 0;
130}
131
132/* TODO: make buffer size controllable by an internal option, and compiler can pass the size
133 to runtime via a variable. */
134static uint32_t orderFileWriter(FILE *File, const uint32_t *DataStart) {
135 if (fwrite(DataStart, sizeof(uint32_t), INSTR_ORDER_FILE_BUFFER_SIZE131072, File) !=
136 INSTR_ORDER_FILE_BUFFER_SIZE131072)
137 return 1;
138 return 0;
139}
140
141static void initFileWriter(ProfDataWriter *This, FILE *File) {
142 This->Write = fileWriter;
143 This->WriterCtx = File;
144}
145
146COMPILER_RT_VISIBILITY__attribute__((visibility("hidden"))) ProfBufferIO *
147lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
148 FreeHook = &free;
149 DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
150 VPBufferSize = BufferSz;
151 ProfDataWriter *fileWriter =
152 (ProfDataWriter *)calloc(sizeof(ProfDataWriter), 1);
153 initFileWriter(fileWriter, File);
154 ProfBufferIO *IO = lprofCreateBufferIO(fileWriter);
155 IO->OwnFileWriter = 1;
156 return IO;
157}
158
159static void setupIOBuffer() {
160 const char *BufferSzStr = 0;
161 BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
162 if (BufferSzStr && BufferSzStr[0]) {
163 VPBufferSize = atoi(BufferSzStr);
164 DynamicBufferIOBuffer = (uint8_t *)calloc(VPBufferSize, 1);
165 }
166}
167
168/* Read profile data in \c ProfileFile and merge with in-memory
169 profile counters. Returns -1 if there is fatal error, otheriwse
170 0 is returned. Returning 0 does not mean merge is actually
171 performed. If merge is actually done, *MergeDone is set to 1.
172*/
173static int doProfileMerging(FILE *ProfileFile, int *MergeDone) {
174 uint64_t ProfileFileSize;
175 char *ProfileBuffer;
176
177 if (fseek(ProfileFile, 0L, SEEK_END2) == -1) {
178 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 ())));
179 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, unable to get size: %s\n"
, strerror((*__errno_location ())));
;
180 return -1;
181 }
182 ProfileFileSize = ftell(ProfileFile);
183
184 /* Restore file offset. */
185 if (fseek(ProfileFile, 0L, SEEK_SET0) == -1) {
186 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 ())));
187 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, unable to rewind: %s\n"
, strerror((*__errno_location ())));
;
188 return -1;
189 }
190
191 /* Nothing to merge. */
192 if (ProfileFileSize < sizeof(__llvm_profile_header)) {
193 if (ProfileFileSize)
194 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.");
195 "source profile file is too small.")fprintf(stderr, "LLVM Profile Warning: " "Unable to merge profile data: %s\n"
, "source profile file is too small.");
;
196 return 0;
197 }
198
199 ProfileBuffer = mmap(NULL((void*)0), ProfileFileSize, PROT_READ0x1, MAP_SHARED0x01 | MAP_FILE0,
200 fileno(ProfileFile), 0);
201 if (ProfileBuffer == MAP_FAILED((void *) -1)) {
202 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 ())));
203 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Unable to merge profile data, mmap failed: %s\n"
, strerror((*__errno_location ())));
;
204 return -1;
205 }
206
207 if (__llvm_profile_check_compatibility(ProfileBuffer, ProfileFileSize)) {
208 (void)munmap(ProfileBuffer, ProfileFileSize);
209 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.");
210 "source profile file is not compatible.")fprintf(stderr, "LLVM Profile Warning: " "Unable to merge profile data: %s\n"
, "source profile file is not compatible.");
;
211 return 0;
212 }
213
214 /* Now start merging */
215 __llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize);
216
217 // Truncate the file in case merging of value profile did not happend to
218 // prevent from leaving garbage data at the end of the profile file.
219 COMPILER_RT_FTRUNCATE(ProfileFile, __llvm_profile_get_size_for_buffer())ftruncate(fileno(ProfileFile),__llvm_profile_get_size_for_buffer
())
;
220
221 (void)munmap(ProfileBuffer, ProfileFileSize);
222 *MergeDone = 1;
223
224 return 0;
225}
226
227/* Create the directory holding the file, if needed. */
228static void createProfileDir(const char *Filename) {
229 size_t Length = strlen(Filename);
230 if (lprofFindFirstDirSeparator(Filename)) {
231 char *Copy = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
232 strncpy(Copy, Filename, Length + 1)__builtin_strncpy (Copy, Filename, Length + 1);
233 __llvm_profile_recursive_mkdir(Copy);
234 }
235}
236
237/* Open the profile data for merging. It opens the file in r+b mode with
238 * file locking. If the file has content which is compatible with the
239 * current process, it also reads in the profile data in the file and merge
240 * it with in-memory counters. After the profile data is merged in memory,
241 * the original profile data is truncated and gets ready for the profile
242 * dumper. With profile merging enabled, each executable as well as any of
243 * its instrumented shared libraries dump profile data into their own data file.
244*/
245static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
246 FILE *ProfileFile = NULL((void*)0);
247 int rc;
248
249 ProfileFile = getProfileFile();
250 if (ProfileFile) {
251 lprofLockFileHandle(ProfileFile);
252 } else {
253 createProfileDir(ProfileFileName);
254 ProfileFile = lprofOpenFileEx(ProfileFileName);
255 }
256 if (!ProfileFile)
257 return NULL((void*)0);
258
259 rc = doProfileMerging(ProfileFile, MergeDone);
260 if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)ftruncate(fileno(ProfileFile),0L)) ||
261 fseek(ProfileFile, 0L, SEEK_SET0) == -1) {
262 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 ())));
263 strerror(errno))fprintf(stderr, "LLVM Profile Error: " "Profile Merging of file %s failed: %s\n"
, ProfileFileName, strerror((*__errno_location ())));
;
264 fclose(ProfileFile);
265 return NULL((void*)0);
266 }
267 return ProfileFile;
268}
269
270static FILE *getFileObject(const char *OutputName) {
271 FILE *File;
272 File = getProfileFile();
273 if (File != NULL((void*)0)) {
274 return File;
275 }
276
277 return fopen(OutputName, "ab");
278}
279
280/* Write profile data to file \c OutputName. */
281static int writeFile(const char *OutputName) {
282 int RetVal;
283 FILE *OutputFile;
284
285 int MergeDone = 0;
286 VPMergeHook = &lprofMergeValueProfData;
287 if (doMerging())
288 OutputFile = openFileForMerging(OutputName, &MergeDone);
289 else
290 OutputFile = getFileObject(OutputName);
291
292 if (!OutputFile)
293 return -1;
294
295 FreeHook = &free;
296 setupIOBuffer();
297 ProfDataWriter fileWriter;
298 initFileWriter(&fileWriter, OutputFile);
299 RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
300
301 if (OutputFile == getProfileFile()) {
302 fflush(OutputFile);
303 if (doMerging()) {
304 lprofUnlockFileHandle(OutputFile);
305 }
306 } else {
307 fclose(OutputFile);
308 }
309
310 return RetVal;
311}
312
313/* Write order data to file \c OutputName. */
314static int writeOrderFile(const char *OutputName) {
315 int RetVal;
316 FILE *OutputFile;
317
318 OutputFile = fopen(OutputName, "w");
319
320 if (!OutputFile) {
321 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);
;
322 return -1;
323 }
324
325 FreeHook = &free;
326 setupIOBuffer();
327 const uint32_t *DataBegin = __llvm_profile_begin_orderfile();
328 RetVal = orderFileWriter(OutputFile, DataBegin);
329
330 fclose(OutputFile);
331 return RetVal;
332}
333
334static void truncateCurrentFile(void) {
335 const char *Filename;
336 char *FilenameBuf;
337 FILE *File;
338 int Length;
339
340 Length = getCurFilenameLength();
341 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
342 Filename = getCurFilename(FilenameBuf, 0);
343 if (!Filename)
344 return;
345
346 /* By pass file truncation to allow online raw profile
347 * merging. */
348 if (lprofCurFilename.MergePoolSize)
349 return;
350
351 createProfileDir(Filename);
352
353 /* Truncate the file. Later we'll reopen and append. */
354 File = fopen(Filename, "w");
355 if (!File)
356 return;
357 fclose(File);
358}
359
360static const char *DefaultProfileName = "default.profraw";
361static void resetFilenameToDefault(void) {
362 if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
363 free((void *)lprofCurFilename.FilenamePat);
364 }
365 memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
366 lprofCurFilename.FilenamePat = DefaultProfileName;
367 lprofCurFilename.PNS = PNS_default;
368}
369
370static int containsMergeSpecifier(const char *FilenamePat, int I) {
371 return (FilenamePat[I] == 'm' ||
372 (FilenamePat[I] >= '1' && FilenamePat[I] <= '9' &&
373 /* If FilenamePat[I] is not '\0', the next byte is guaranteed
374 * to be in-bound as the string is null terminated. */
375 FilenamePat[I + 1] == 'm'));
376}
377
378/* Parses the pattern string \p FilenamePat and stores the result to
379 * lprofcurFilename structure. */
380static int parseFilenamePattern(const char *FilenamePat,
381 unsigned CopyFilenamePat) {
382 int NumPids = 0, NumHosts = 0, I;
383 char *PidChars = &lprofCurFilename.PidChars[0];
384 char *Hostname = &lprofCurFilename.Hostname[0];
385 int MergingEnabled = 0;
386
387 /* Clean up cached prefix and filename. */
388 if (lprofCurFilename.ProfilePathPrefix)
10
Assuming field 'ProfilePathPrefix' is null
11
Taking false branch
389 free((void *)lprofCurFilename.ProfilePathPrefix);
390 if (lprofCurFilename.Filename)
12
Assuming field 'Filename' is null
13
Taking false branch
391 free((void *)lprofCurFilename.Filename);
392
393 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
394 free((void *)lprofCurFilename.FilenamePat);
16
Memory is released
395 }
396
397 memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
398
399 if (!CopyFilenamePat
16.1
'CopyFilenamePat' is 1
)
17
Taking false branch
400 lprofCurFilename.FilenamePat = FilenamePat;
401 else {
402 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
)))
;
403 lprofCurFilename.OwnsFilenamePat = 1;
404 }
405 /* Check the filename for "%p", which indicates a pid-substitution. */
406 for (I = 0; FilenamePat[I]; ++I)
18
Loop condition is false. Execution continues on line 441
407 if (FilenamePat[I] == '%') {
408 if (FilenamePat[++I] == 'p') {
409 if (!NumPids++) {
410 if (snprintf(PidChars, MAX_PID_SIZE16, "%ld", (long)getpid()) <= 0) {
411 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);
412 "default name.",fprintf(stderr, "LLVM Profile Warning: " "Unable to get pid for filename pattern %s. Using the "
"default name.", FilenamePat);
413 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "Unable to get pid for filename pattern %s. Using the "
"default name.", FilenamePat);
;
414 return -1;
415 }
416 }
417 } else if (FilenamePat[I] == 'h') {
418 if (!NumHosts++)
419 if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)lprofGetHostName(Hostname, 128)) {
420 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);
421 "the default name.",fprintf(stderr, "LLVM Profile Warning: " "Unable to get hostname for filename pattern %s. Using "
"the default name.", FilenamePat);
422 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "Unable to get hostname for filename pattern %s. Using "
"the default name.", FilenamePat);
;
423 return -1;
424 }
425 } else if (containsMergeSpecifier(FilenamePat, I)) {
426 if (MergingEnabled) {
427 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);
428 FilenamePat)fprintf(stderr, "LLVM Profile Warning: " "%%m specifier can only be specified once in %s.\n"
, FilenamePat);
;
429 return -1;
430 }
431 MergingEnabled = 1;
432 if (FilenamePat[I] == 'm')
433 lprofCurFilename.MergePoolSize = 1;
434 else {
435 lprofCurFilename.MergePoolSize = FilenamePat[I] - '0';
436 I++; /* advance to 'm' */
437 }
438 }
439 }
440
441 lprofCurFilename.NumPids = NumPids;
442 lprofCurFilename.NumHosts = NumHosts;
443 return 0;
444}
445
446static void parseAndSetFilename(const char *FilenamePat,
447 ProfileNameSpecifier PNS,
448 unsigned CopyFilenamePat) {
449
450 const char *OldFilenamePat = lprofCurFilename.FilenamePat;
451 ProfileNameSpecifier OldPNS = lprofCurFilename.PNS;
452
453 if (PNS < OldPNS)
2
Assuming 'PNS' is >= 'OldPNS'
3
Taking false branch
454 return;
455
456 if (!FilenamePat)
4
Assuming 'FilenamePat' is non-null
5
Taking false branch
457 FilenamePat = DefaultProfileName;
458
459 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)))); })
) {
6
Assuming 'OldFilenamePat' is non-null
7
Assuming the condition is false
8
Taking false branch
460 lprofCurFilename.PNS = PNS;
461 return;
462 }
463
464 /* When PNS >= OldPNS, the last one wins. */
465 if (!FilenamePat
8.1
'FilenamePat' is non-null
|| parseFilenamePattern(FilenamePat, CopyFilenamePat))
9
Calling 'parseFilenamePattern'
19
Returning; memory was released
20
Taking false branch
466 resetFilenameToDefault();
467 lprofCurFilename.PNS = PNS;
468
469 if (!OldFilenamePat
20.1
'OldFilenamePat' is non-null
) {
21
Taking false branch
470 if (getenv("LLVM_PROFILE_VERBOSE"))
471 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));
472 lprofCurFilename.FilenamePat, getPNSStr(PNS))fprintf(stderr, "LLVM Profile Note: " "Set profile file path to \"%s\" via %s.\n"
, lprofCurFilename.FilenamePat, getPNSStr(PNS));
;
473 } else {
474 if (getenv("LLVM_PROFILE_VERBOSE"))
22
Assuming the condition is true
23
Taking true branch
475 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
476 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));
477 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));
;
478 }
479
480 truncateCurrentFile();
481}
482
483/* Return buffer length that is required to store the current profile
484 * filename with PID and hostname substitutions. */
485/* The length to hold uint64_t followed by 2 digit pool id including '_' */
486#define SIGLEN24 24
487static int getCurFilenameLength() {
488 int Len;
489 if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
490 return 0;
491
492 if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
493 lprofCurFilename.MergePoolSize))
494 return strlen(lprofCurFilename.FilenamePat);
495
496 Len = strlen(lprofCurFilename.FilenamePat) +
497 lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
498 lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2);
499 if (lprofCurFilename.MergePoolSize)
500 Len += SIGLEN24;
501 return Len;
502}
503
504/* Return the pointer to the current profile file name (after substituting
505 * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer
506 * to store the resulting filename. If no substitution is needed, the
507 * current filename pattern string is directly returned, unless ForceUseBuf
508 * is enabled. */
509static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
510 int I, J, PidLength, HostNameLength, FilenamePatLength;
511 const char *FilenamePat = lprofCurFilename.FilenamePat;
512
513 if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
514 return 0;
515
516 if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
517 lprofCurFilename.MergePoolSize)) {
518 if (!ForceUseBuf)
519 return lprofCurFilename.FilenamePat;
520
521 FilenamePatLength = strlen(lprofCurFilename.FilenamePat);
522 memcpy(FilenameBuf, lprofCurFilename.FilenamePat, FilenamePatLength);
523 FilenameBuf[FilenamePatLength] = '\0';
524 return FilenameBuf;
525 }
526
527 PidLength = strlen(lprofCurFilename.PidChars);
528 HostNameLength = strlen(lprofCurFilename.Hostname);
529 /* Construct the new filename. */
530 for (I = 0, J = 0; FilenamePat[I]; ++I)
531 if (FilenamePat[I] == '%') {
532 if (FilenamePat[++I] == 'p') {
533 memcpy(FilenameBuf + J, lprofCurFilename.PidChars, PidLength);
534 J += PidLength;
535 } else if (FilenamePat[I] == 'h') {
536 memcpy(FilenameBuf + J, lprofCurFilename.Hostname, HostNameLength);
537 J += HostNameLength;
538 } else if (containsMergeSpecifier(FilenamePat, I)) {
539 char LoadModuleSignature[SIGLEN24];
540 int S;
541 int ProfilePoolId = getpid() % lprofCurFilename.MergePoolSize;
542 S = snprintf(LoadModuleSignature, SIGLEN24, "%" PRIu64"l" "u" "_%d",
543 lprofGetLoadModuleSignature(), ProfilePoolId);
544 if (S == -1 || S > SIGLEN24)
545 S = SIGLEN24;
546 memcpy(FilenameBuf + J, LoadModuleSignature, S);
547 J += S;
548 if (FilenamePat[I] != 'm')
549 I++;
550 }
551 /* Drop any unknown substitutions. */
552 } else
553 FilenameBuf[J++] = FilenamePat[I];
554 FilenameBuf[J] = 0;
555
556 return FilenameBuf;
557}
558
559/* Returns the pointer to the environment variable
560 * string. Returns null if the env var is not set. */
561static const char *getFilenamePatFromEnv(void) {
562 const char *Filename = getenv("LLVM_PROFILE_FILE");
563 if (!Filename || !Filename[0])
564 return 0;
565 return Filename;
566}
567
568COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
569const char *__llvm_profile_get_path_prefix(void) {
570 int Length;
571 char *FilenameBuf, *Prefix;
572 const char *Filename, *PrefixEnd;
573
574 if (lprofCurFilename.ProfilePathPrefix)
575 return lprofCurFilename.ProfilePathPrefix;
576
577 Length = getCurFilenameLength();
578 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
579 Filename = getCurFilename(FilenameBuf, 0);
580 if (!Filename)
581 return "\0";
582
583 PrefixEnd = lprofFindLastDirSeparator(Filename);
584 if (!PrefixEnd)
585 return "\0";
586
587 Length = PrefixEnd - Filename + 1;
588 Prefix = (char *)malloc(Length + 1);
589 if (!Prefix) {
590 PROF_ERR("Failed to %s\n", "allocate memory.")fprintf(stderr, "LLVM Profile Error: " "Failed to %s\n", "allocate memory."
);
;
591 return "\0";
592 }
593 memcpy(Prefix, Filename, Length);
594 Prefix[Length] = '\0';
595 lprofCurFilename.ProfilePathPrefix = Prefix;
596 return Prefix;
597}
598
599COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
600const char *__llvm_profile_get_filename(void) {
601 int Length;
602 char *FilenameBuf;
603 const char *Filename;
604
605 if (lprofCurFilename.Filename)
606 return lprofCurFilename.Filename;
607
608 Length = getCurFilenameLength();
609 FilenameBuf = (char *)malloc(Length + 1);
610 if (!FilenameBuf) {
611 PROF_ERR("Failed to %s\n", "allocate memory.")fprintf(stderr, "LLVM Profile Error: " "Failed to %s\n", "allocate memory."
);
;
612 return "\0";
613 }
614 Filename = getCurFilename(FilenameBuf, 1);
615 if (!Filename)
616 return "\0";
617
618 lprofCurFilename.Filename = FilenameBuf;
619 return FilenameBuf;
620}
621
622/* This method is invoked by the runtime initialization hook
623 * InstrProfilingRuntime.o if it is linked in. Both user specified
624 * profile path via -fprofile-instr-generate= and LLVM_PROFILE_FILE
625 * environment variable can override this default value. */
626COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
627void __llvm_profile_initialize_file(void) {
628 const char *EnvFilenamePat;
629 const char *SelectedPat = NULL((void*)0);
630 ProfileNameSpecifier PNS = PNS_unknown;
631 int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR__llvm_profile_filename[0] != 0);
632
633 EnvFilenamePat = getFilenamePatFromEnv();
634 if (EnvFilenamePat) {
635 /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
636 at the moment when __llvm_profile_write_file() gets executed. */
637 parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
638 return;
639 } else if (hasCommandLineOverrider) {
640 SelectedPat = INSTR_PROF_PROFILE_NAME_VAR__llvm_profile_filename;
641 PNS = PNS_command_line;
642 } else {
643 SelectedPat = NULL((void*)0);
644 PNS = PNS_default;
645 }
646
647 parseAndSetFilename(SelectedPat, PNS, 0);
648}
649
650/* This API is directly called by the user application code. It has the
651 * highest precedence compared with LLVM_PROFILE_FILE environment variable
652 * and command line option -fprofile-instr-generate=<profile_name>.
653 */
654COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
655void __llvm_profile_set_filename(const char *FilenamePat) {
656 parseAndSetFilename(FilenamePat, PNS_runtime_api, 1);
1
Calling 'parseAndSetFilename'
657}
658
659/* The public API for writing profile data into the file with name
660 * set by previous calls to __llvm_profile_set_filename or
661 * __llvm_profile_override_default_filename or
662 * __llvm_profile_initialize_file. */
663COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
664int __llvm_profile_write_file(void) {
665 int rc, Length;
666 const char *Filename;
667 char *FilenameBuf;
668 int PDeathSig = 0;
669
670 if (lprofProfileDumped()) {
671 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");
;
672 return 0;
673 }
674
675 Length = getCurFilenameLength();
676 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
677 Filename = getCurFilename(FilenameBuf, 0);
678
679 /* Check the filename. */
680 if (!Filename) {
681 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");
;
682 return -1;
683 }
684
685 /* Check if there is llvm/runtime version mismatch. */
686 if (GET_VERSION(__llvm_profile_get_version())((__llvm_profile_get_version()) & ~0xff00000000000000ULL) != INSTR_PROF_RAW_VERSION4) {
687 PROF_ERR("Runtime and instrumentation version mismatch : "fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 4, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
688 "expected %d, but get %d\n",fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 4, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
689 INSTR_PROF_RAW_VERSION,fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 4, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
690 (int)GET_VERSION(__llvm_profile_get_version()))fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 4, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
;
691 return -1;
692 }
693
694 // Temporarily suspend getting SIGKILL when the parent exits.
695 PDeathSig = lprofSuspendSigKill();
696
697 /* Write profile data to the file. */
698 rc = writeFile(Filename);
699 if (rc)
700 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 ())));
;
701
702 // Restore SIGKILL.
703 if (PDeathSig == 1)
704 lprofRestoreSigKill();
705
706 return rc;
707}
708
709COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
710int __llvm_profile_dump(void) {
711 if (!doMerging())
712 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");
713 " 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");
714 "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");
715 "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");
;
716 int rc = __llvm_profile_write_file();
717 lprofSetProfileDumped();
718 return rc;
719}
720
721/* Order file data will be saved in a file with suffx .order. */
722static const char *OrderFileSuffix = ".order";
723
724COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
725int __llvm_orderfile_write_file(void) {
726 int rc, Length, LengthBeforeAppend, SuffixLength;
727 const char *Filename;
728 char *FilenameBuf;
729 int PDeathSig = 0;
730
731 SuffixLength = strlen(OrderFileSuffix);
732 Length = getCurFilenameLength() + SuffixLength;
733 FilenameBuf = (char *)COMPILER_RT_ALLOCA__builtin_alloca(Length + 1);
734 Filename = getCurFilename(FilenameBuf, 1);
735
736 /* Check the filename. */
737 if (!Filename) {
738 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");
;
739 return -1;
740 }
741
742 /* Append order file suffix */
743 LengthBeforeAppend = strlen(Filename);
744 memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength);
745 FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0';
746
747 /* Check if there is llvm/runtime version mismatch. */
748 if (GET_VERSION(__llvm_profile_get_version())((__llvm_profile_get_version()) & ~0xff00000000000000ULL) != INSTR_PROF_RAW_VERSION4) {
749 PROF_ERR("Runtime and instrumentation version mismatch : "fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 4, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
750 "expected %d, but get %d\n",fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 4, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
751 INSTR_PROF_RAW_VERSION,fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 4, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
752 (int)GET_VERSION(__llvm_profile_get_version()))fprintf(stderr, "LLVM Profile Error: " "Runtime and instrumentation version mismatch : "
"expected %d, but get %d\n", 4, (int)((__llvm_profile_get_version
()) & ~0xff00000000000000ULL));
;
753 return -1;
754 }
755
756 // Temporarily suspend getting SIGKILL when the parent exits.
757 PDeathSig = lprofSuspendSigKill();
758
759 /* Write order data to the file. */
760 rc = writeOrderFile(Filename);
761 if (rc)
762 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 ())));
;
763
764 // Restore SIGKILL.
765 if (PDeathSig == 1)
766 lprofRestoreSigKill();
767
768 return rc;
769}
770
771COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
772int __llvm_orderfile_dump(void) {
773 int rc = __llvm_orderfile_write_file();
774 return rc;
775}
776
777static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }
778
779COMPILER_RT_VISIBILITY__attribute__((visibility("hidden")))
780int __llvm_profile_register_write_file_atexit(void) {
781 static int HasBeenRegistered = 0;
782
783 if (HasBeenRegistered)
784 return 0;
785
786 lprofSetupValueProfiler();
787
788 HasBeenRegistered = 1;
789 return atexit(writeFileWithoutReturn);
790}
791
792#endif