/* Read profile data in \c ProfileFile and merge with in-memory profile counters. Returns -1 if there is fatal error, otheriwse 0 is returned. */ static int doProfileMerging(FILE *ProfileFile) { uint64_t ProfileFileSize; char *ProfileBuffer; if (fseek(ProfileFile, 0L, SEEK_END) == -1) { PROF_ERR("Unable to merge profile data, unable to get size: %s\n", strerror(errno)); return -1; } ProfileFileSize = ftell(ProfileFile); /* Restore file offset. */ if (fseek(ProfileFile, 0L, SEEK_SET) == -1) { PROF_ERR("Unable to merge profile data, unable to rewind: %s\n", strerror(errno)); return -1; } /* Nothing to merge. */ if (ProfileFileSize < sizeof(__llvm_profile_header)) { if (ProfileFileSize) PROF_WARN("Unable to merge profile data: %s\n", "source profile file is too small."); return 0; } ProfileBuffer = mmap(NULL, ProfileFileSize, PROT_READ, MAP_SHARED | MAP_FILE, fileno(ProfileFile), 0); if (ProfileBuffer == MAP_FAILED) { PROF_ERR("Unable to merge profile data, mmap failed: %s\n", strerror(errno)); return -1; } if (__llvm_profile_check_compatibility(ProfileBuffer, ProfileFileSize)) { (void)munmap(ProfileBuffer, ProfileFileSize); PROF_WARN("Unable to merge profile data: %s\n", "source profile file is not compatible."); return 0; } /* Now start merging */ __llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize); (void)munmap(ProfileBuffer, ProfileFileSize); return 0; }
/* Returns 0 (size) when an error occurs. */ uint64_t libEntry(char *Buffer, uint64_t MaxSize) { uint64_t Size = __llvm_profile_get_size_for_buffer(); if (Size > MaxSize) return 0; __llvm_profile_reset_counters(); bar('1'); if (__llvm_profile_write_buffer(Buffer)) return 0; /* Now check compatibility. Should return 0. */ if (__llvm_profile_check_compatibility(Buffer, Size)) return 0; return Size; }