[Profile] Disable continuous mode when reset to default.profraw due to malformed LLVM_PROFILE_FILE. (#74879)

When LLVM_PROFILE_FILE is set incorrectly (e.g. multiple %c) and it
falls back to use `default.profraw` name, but continuous mode is still
set. This might cause signal bus in the following scenario.

LLVM_PROFILE_FILE is set incorrectly (with "%c%c") for process A and B.
Suppose A starts first and falls back to use `default.profraw` and
mmaped its file content to memory. Later B starts and also falls back to
use `default.profraw`, but it will truncate the file because online
merging is disable when reseting to `default.profraw`. When A tries to
update counter via mmaped memory, signal bus will occur.

This fixes it by disabling continuous mode when reset to
default.profraw.
This commit is contained in:
Zequan Wu 2023-12-11 10:13:08 -05:00 committed by GitHub
parent b40c534656
commit ace26b380f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 0 deletions

View File

@ -54,6 +54,12 @@ int __llvm_profile_is_continuous_mode_enabled(void);
*/
void __llvm_profile_enable_continuous_mode(void);
/*!
* \brief Disable continuous mode.
*
*/
void __llvm_profile_disable_continuous_mode(void);
/*!
* \brief Set the page size.
*

View File

@ -33,6 +33,10 @@ COMPILER_RT_VISIBILITY void __llvm_profile_enable_continuous_mode(void) {
ContinuouslySyncProfile = 1;
}
void __llvm_profile_disable_continuous_mode(void) {
ContinuouslySyncProfile = 0;
}
COMPILER_RT_VISIBILITY void __llvm_profile_set_page_size(unsigned PS) {
PageSize = PS;
}

View File

@ -806,6 +806,7 @@ static int parseFilenamePattern(const char *FilenamePat,
if (__llvm_profile_is_continuous_mode_enabled()) {
PROF_WARN("%%c specifier can only be specified once in %s.\n",
FilenamePat);
__llvm_profile_disable_continuous_mode();
return -1;
}
#if defined(__APPLE__) || defined(__ELF__) || defined(_WIN32)

View File

@ -0,0 +1,21 @@
// REQUIRES: darwin || linux
// Test when LLVM_PROFILE_FILE is set incorrectly, it should fall backs to use default.profraw without runtime error.
// Create & cd into a temporary directory.
// RUN: rm -rf %t.dir && mkdir -p %t.dir && cd %t.dir
// RUN: %clang -fprofile-instr-generate -fcoverage-mapping -mllvm -runtime-counter-relocation=true -o %t.exe %s
// RUN: env LLVM_PROFILE_FILE="incorrect-profile-name%m%c%c.profraw" %run %t.exe
// RUN: ls -l | FileCheck %s
// CHECK: default.profraw
// CHECK-NOT: incorrect-profile-name.profraw
#include <stdio.h>
int f() { return 0; }
int main(int argc, char **argv) {
FILE *File = fopen("default.profraw", "w");
f();
return 0;
}