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.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__) 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. */ 41 typedef enum ProfileNameSpecifier { 42 PNS_unknown = 0, 43 PNS_default, 44 PNS_command_line, 45 PNS_environment, 46 PNS_runtime_api 47 } ProfileNameSpecifier; 48 49 static 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_SIZE 16 65 /* Data structure holding the result of parsed filename pattern. */ 66 typedef 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_SIZE]; 75 char Hostname[COMPILER_RT_MAX_HOSTLEN]; 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 89 COMPILER_RT_WEAK lprofFilename lprofCurFilename = {0, 0, 0, 0, {0}, 90 {0}, 0, 0, 0, PNS_unknown}; 91 92 static int ProfileMergeRequested = 0; 93 static int isProfileMergeRequested() { return ProfileMergeRequested; } 94 static void setProfileMergeRequested(int EnableMerge) { 95 ProfileMergeRequested = EnableMerge; 96 } 97 98 static FILE *ProfileFile = NULL; 99 static FILE *getProfileFile() { return ProfileFile; } 100 static void setProfileFile(FILE *File) { ProfileFile = File; } 101 102 COMPILER_RT_VISIBILITY void __llvm_profile_set_file_object(FILE *File, 103 int EnableMerge) { 104 setProfileFile(File); 105 setProfileMergeRequested(EnableMerge); 106 } 107 108 static int getCurFilenameLength(); 109 static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf); 110 static unsigned doMerging() { 111 return lprofCurFilename.MergePoolSize || isProfileMergeRequested(); 112 } 113 114 /* Return 1 if there is an error, otherwise return 0. */ 115 static 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_CUR) == -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. */ 134 static uint32_t orderFileWriter(FILE *File, const uint32_t *DataStart) { 135 if (fwrite(DataStart, sizeof(uint32_t), INSTR_ORDER_FILE_BUFFER_SIZE, File) != 136 INSTR_ORDER_FILE_BUFFER_SIZE) 137 return 1; 138 return 0; 139 } 140 141 static void initFileWriter(ProfDataWriter *This, FILE *File) { 142 This->Write = fileWriter; 143 This->WriterCtx = File; 144 } 145 146 COMPILER_RT_VISIBILITY ProfBufferIO * 147 lprofCreateBufferIOInternal(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 159 static 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 */ 173 static int doProfileMerging(FILE *ProfileFile, int *MergeDone) { 174 uint64_t ProfileFileSize; 175 char *ProfileBuffer; 176 177 if (fseek(ProfileFile, 0L, SEEK_END) == -1) { 178 PROF_ERR("Unable to merge profile data, unable to get size: %s\n", 179 strerror(errno)); 180 return -1; 181 } 182 ProfileFileSize = ftell(ProfileFile); 183 184 /* Restore file offset. */ 185 if (fseek(ProfileFile, 0L, SEEK_SET) == -1) { 186 PROF_ERR("Unable to merge profile data, unable to rewind: %s\n", 187 strerror(errno)); 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", 195 "source profile file is too small."); 196 return 0; 197 } 198 199 ProfileBuffer = mmap(NULL, ProfileFileSize, PROT_READ, MAP_SHARED | MAP_FILE, 200 fileno(ProfileFile), 0); 201 if (ProfileBuffer == MAP_FAILED) { 202 PROF_ERR("Unable to merge profile data, mmap failed: %s\n", 203 strerror(errno)); 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", 210 "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()); 220 221 (void)munmap(ProfileBuffer, ProfileFileSize); 222 *MergeDone = 1; 223 224 return 0; 225 } 226 227 /* Create the directory holding the file, if needed. */ 228 static void createProfileDir(const char *Filename) { 229 size_t Length = strlen(Filename); 230 if (lprofFindFirstDirSeparator(Filename)) { 231 char *Copy = (char *)COMPILER_RT_ALLOCA(Length + 1); 232 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 */ 245 static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) { 246 FILE *ProfileFile = NULL; 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; 258 259 rc = doProfileMerging(ProfileFile, MergeDone); 260 if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)) || 261 fseek(ProfileFile, 0L, SEEK_SET) == -1) { 262 PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName, 263 strerror(errno)); 264 fclose(ProfileFile); 265 return NULL; 266 } 267 return ProfileFile; 268 } 269 270 static FILE *getFileObject(const char *OutputName) { 271 FILE *File; 272 File = getProfileFile(); 273 if (File != NULL) { 274 return File; 275 } 276 277 return fopen(OutputName, "ab"); 278 } 279 280 /* Write profile data to file \c OutputName. */ 281 static 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. */ 314 static 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); 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 334 static 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(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 360 static const char *DefaultProfileName = "default.profraw"; 361 static 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 370 static 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. */ 380 static 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) 389 free((void *)lprofCurFilename.ProfilePathPrefix); 390 if (lprofCurFilename.Filename) 391 free((void *)lprofCurFilename.Filename); 392 393 if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) { 394 free((void *)lprofCurFilename.FilenamePat); 395 } 396 397 memset(&lprofCurFilename, 0, sizeof(lprofCurFilename)); 398 399 if (!CopyFilenamePat) 400 lprofCurFilename.FilenamePat = FilenamePat; 401 else { 402 lprofCurFilename.FilenamePat = 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) 407 if (FilenamePat[I] == '%') { 408 if (FilenamePat[++I] == 'p') { 409 if (!NumPids++) { 410 if (snprintf(PidChars, MAX_PID_SIZE, "%ld", (long)getpid()) <= 0) { 411 PROF_WARN("Unable to get pid for filename pattern %s. Using the " 412 "default name.", 413 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)) { 420 PROF_WARN("Unable to get hostname for filename pattern %s. Using " 421 "the default name.", 422 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", 428 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 446 static 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) 454 return; 455 456 if (!FilenamePat) 457 FilenamePat = DefaultProfileName; 458 459 if (OldFilenamePat && !strcmp(OldFilenamePat, FilenamePat)) { 460 lprofCurFilename.PNS = PNS; 461 return; 462 } 463 464 /* When PNS >= OldPNS, the last one wins. */ 465 if (!FilenamePat || parseFilenamePattern(FilenamePat, CopyFilenamePat)) 466 resetFilenameToDefault(); 467 lprofCurFilename.PNS = PNS; 468 469 if (!OldFilenamePat) { 470 if (getenv("LLVM_PROFILE_VERBOSE")) 471 PROF_NOTE("Set profile file path to \"%s\" via %s.\n", 472 lprofCurFilename.FilenamePat, getPNSStr(PNS)); 473 } else { 474 if (getenv("LLVM_PROFILE_VERBOSE")) 475 PROF_NOTE("Override old profile path \"%s\" via %s to \"%s\" via %s.\n", 476 OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat, 477 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 SIGLEN 24 487 static 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 += SIGLEN; 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. */ 509 static 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[SIGLEN]; 540 int S; 541 int ProfilePoolId = getpid() % lprofCurFilename.MergePoolSize; 542 S = snprintf(LoadModuleSignature, SIGLEN, "%" PRIu64 "_%d", 543 lprofGetLoadModuleSignature(), ProfilePoolId); 544 if (S == -1 || S > SIGLEN) 545 S = SIGLEN; 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. */ 561 static 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 568 COMPILER_RT_VISIBILITY 569 const 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(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."); 591 return "\0"; 592 } 593 memcpy(Prefix, Filename, Length); 594 Prefix[Length] = '\0'; 595 lprofCurFilename.ProfilePathPrefix = Prefix; 596 return Prefix; 597 } 598 599 COMPILER_RT_VISIBILITY 600 const 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."); 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. */ 626 COMPILER_RT_VISIBILITY 627 void __llvm_profile_initialize_file(void) { 628 const char *EnvFilenamePat; 629 const char *SelectedPat = NULL; 630 ProfileNameSpecifier PNS = PNS_unknown; 631 int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR[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; 641 PNS = PNS_command_line; 642 } else { 643 SelectedPat = NULL; 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 */ 654 COMPILER_RT_VISIBILITY 655 void __llvm_profile_set_filename(const char *FilenamePat) { 656 parseAndSetFilename(FilenamePat, PNS_runtime_api, 1); 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. */ 663 COMPILER_RT_VISIBILITY 664 int __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"); 672 return 0; 673 } 674 675 Length = getCurFilenameLength(); 676 FilenameBuf = (char *)COMPILER_RT_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"); 682 return -1; 683 } 684 685 /* Check if there is llvm/runtime version mismatch. */ 686 if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) { 687 PROF_ERR("Runtime and instrumentation version mismatch : " 688 "expected %d, but get %d\n", 689 INSTR_PROF_RAW_VERSION, 690 (int)GET_VERSION(__llvm_profile_get_version())); 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)); 701 702 // Restore SIGKILL. 703 if (PDeathSig == 1) 704 lprofRestoreSigKill(); 705 706 return rc; 707 } 708 709 COMPILER_RT_VISIBILITY 710 int __llvm_profile_dump(void) { 711 if (!doMerging()) 712 PROF_WARN("Later invocation of __llvm_profile_dump can lead to clobbering " 713 " of previously dumped profile data : %s. Either use %%m " 714 "in profile name or change profile name before dumping.\n", 715 "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. */ 722 static const char *OrderFileSuffix = ".order"; 723 724 COMPILER_RT_VISIBILITY 725 int __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(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"); 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()) != INSTR_PROF_RAW_VERSION) { 749 PROF_ERR("Runtime and instrumentation version mismatch : " 750 "expected %d, but get %d\n", 751 INSTR_PROF_RAW_VERSION, 752 (int)GET_VERSION(__llvm_profile_get_version())); 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)); 763 764 // Restore SIGKILL. 765 if (PDeathSig == 1) 766 lprofRestoreSigKill(); 767 768 return rc; 769 } 770 771 COMPILER_RT_VISIBILITY 772 int __llvm_orderfile_dump(void) { 773 int rc = __llvm_orderfile_write_file(); 774 return rc; 775 } 776 777 static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); } 778 779 COMPILER_RT_VISIBILITY 780 int __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 793