[InstrProfiling] Use weak alias for bias variable
We need the compiler generated variable to override the weak symbol of the same name inside the profile runtime, but using LinkOnceODRLinkage results in weak symbol being emitted in which case the symbol selected by the linker is going to depend on the order of inputs which can be fragile. This change replaces the use of weak definition inside the runtime with a weak alias. We place the compiler generated symbol inside a COMDAT group so dead definition can be garbage collected by the linker. We also disable the use of runtime counter relocation on Darwin since Mach-O doesn't support weak external references, but Darwin already uses a different continous mode that relies on overmapping so runtime counter relocation isn't needed there. Differential Revision: https://reviews.llvm.org/D105176
This commit is contained in:
@@ -426,33 +426,6 @@ static void truncateCurrentFile(void) {
|
||||
fclose(File);
|
||||
}
|
||||
|
||||
#if !defined(__Fuchsia__) && !defined(_WIN32)
|
||||
static void assertIsZero(int *i) {
|
||||
if (*i)
|
||||
PROF_WARN("Expected flag to be 0, but got: %d\n", *i);
|
||||
}
|
||||
|
||||
/* Write a partial profile to \p Filename, which is required to be backed by
|
||||
* the open file object \p File. */
|
||||
static int writeProfileWithFileObject(const char *Filename, FILE *File) {
|
||||
setProfileFile(File);
|
||||
int rc = writeFile(Filename);
|
||||
if (rc)
|
||||
PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
|
||||
setProfileFile(NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Unlock the profile \p File and clear the unlock flag. */
|
||||
static void unlockProfile(int *ProfileRequiresUnlock, FILE *File) {
|
||||
if (!*ProfileRequiresUnlock) {
|
||||
PROF_WARN("%s", "Expected to require profile unlock\n");
|
||||
}
|
||||
lprofUnlockFileHandle(File);
|
||||
*ProfileRequiresUnlock = 0;
|
||||
}
|
||||
#endif // !defined(__Fuchsia__) && !defined(_WIN32)
|
||||
|
||||
static int writeMMappedFile(FILE *OutputFile, char **Profile) {
|
||||
if (!OutputFile)
|
||||
return -1;
|
||||
@@ -481,83 +454,38 @@ static int writeMMappedFile(FILE *OutputFile, char **Profile) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void relocateCounters(void) {
|
||||
if (!__llvm_profile_is_continuous_mode_enabled() ||
|
||||
!lprofRuntimeCounterRelocation())
|
||||
return;
|
||||
// TODO: Move these functions into InstrProfilingPlatform* files.
|
||||
#if defined(__APPLE__)
|
||||
static void assertIsZero(int *i) {
|
||||
if (*i)
|
||||
PROF_WARN("Expected flag to be 0, but got: %d\n", *i);
|
||||
}
|
||||
|
||||
/* Get the sizes of various profile data sections. Taken from
|
||||
* __llvm_profile_get_size_for_buffer(). */
|
||||
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||
const uint64_t *CountersBegin = __llvm_profile_begin_counters();
|
||||
const uint64_t *CountersEnd = __llvm_profile_end_counters();
|
||||
uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
|
||||
const uint64_t CountersOffset = sizeof(__llvm_profile_header) +
|
||||
(DataSize * sizeof(__llvm_profile_data));
|
||||
/* Write a partial profile to \p Filename, which is required to be backed by
|
||||
* the open file object \p File. */
|
||||
static int writeProfileWithFileObject(const char *Filename, FILE *File) {
|
||||
setProfileFile(File);
|
||||
int rc = writeFile(Filename);
|
||||
if (rc)
|
||||
PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
|
||||
setProfileFile(NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int Length = getCurFilenameLength();
|
||||
char *FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
|
||||
const char *Filename = getCurFilename(FilenameBuf, 0);
|
||||
if (!Filename)
|
||||
return;
|
||||
|
||||
FILE *File = NULL;
|
||||
char *Profile = NULL;
|
||||
|
||||
if (!doMerging()) {
|
||||
File = fopen(Filename, "w+b");
|
||||
if (!File)
|
||||
return;
|
||||
|
||||
if (writeMMappedFile(File, &Profile) == -1) {
|
||||
fclose(File);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
File = lprofOpenFileEx(Filename);
|
||||
if (!File)
|
||||
return;
|
||||
|
||||
uint64_t ProfileFileSize = 0;
|
||||
if (getProfileFileSizeForMerging(File, &ProfileFileSize) == -1) {
|
||||
lprofUnlockFileHandle(File);
|
||||
fclose(File);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ProfileFileSize) {
|
||||
if (writeMMappedFile(File, &Profile) == -1) {
|
||||
fclose(File);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* The merged profile has a non-zero length. Check that it is compatible
|
||||
* with the data in this process. */
|
||||
if (mmapProfileForMerging(File, ProfileFileSize, &Profile) == -1) {
|
||||
fclose(File);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lprofUnlockFileHandle(File);
|
||||
/* Unlock the profile \p File and clear the unlock flag. */
|
||||
static void unlockProfile(int *ProfileRequiresUnlock, FILE *File) {
|
||||
if (!*ProfileRequiresUnlock) {
|
||||
PROF_WARN("%s", "Expected to require profile unlock\n");
|
||||
}
|
||||
|
||||
/* Update the profile fields based on the current mapping. */
|
||||
__llvm_profile_counter_bias =
|
||||
(intptr_t)Profile - (uintptr_t)CountersBegin + CountersOffset;
|
||||
|
||||
/* Return the memory allocated for counters to OS. */
|
||||
lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin, (uintptr_t)CountersEnd);
|
||||
lprofUnlockFileHandle(File);
|
||||
*ProfileRequiresUnlock = 0;
|
||||
}
|
||||
|
||||
static void initializeProfileForContinuousMode(void) {
|
||||
if (!__llvm_profile_is_continuous_mode_enabled())
|
||||
return;
|
||||
|
||||
#if defined(__Fuchsia__) || defined(_WIN32)
|
||||
PROF_ERR("%s\n", "Continuous mode not yet supported on Fuchsia or Windows.");
|
||||
#else // defined(__Fuchsia__) || defined(_WIN32)
|
||||
/* Get the sizes of various profile data sections. Taken from
|
||||
* __llvm_profile_get_size_for_buffer(). */
|
||||
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
||||
@@ -683,8 +611,109 @@ static void initializeProfileForContinuousMode(void) {
|
||||
|
||||
if (ProfileRequiresUnlock)
|
||||
unlockProfile(&ProfileRequiresUnlock, File);
|
||||
#endif // defined(__Fuchsia__) || defined(_WIN32)
|
||||
}
|
||||
#elif defined(__ELF__) || defined(_WIN32)
|
||||
|
||||
#define INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR \
|
||||
INSTR_PROF_CONCAT(INSTR_PROF_PROFILE_COUNTER_BIAS_VAR, _default)
|
||||
intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR = 0;
|
||||
|
||||
/* This variable is a weak external reference which could be used to detect
|
||||
* whether or not the compiler defined this symbol. */
|
||||
#if defined(_WIN32)
|
||||
COMPILER_RT_VISIBILITY extern intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_VAR;
|
||||
#pragma comment(linker, "/alternatename:" \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_COUNTER_BIAS_VAR) "=" \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR))
|
||||
#else
|
||||
COMPILER_RT_VISIBILITY extern intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_VAR
|
||||
__attribute__((weak, alias(INSTR_PROF_QUOTE(
|
||||
INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR))));
|
||||
#endif
|
||||
|
||||
static void initializeProfileForContinuousMode(void) {
|
||||
if (!__llvm_profile_is_continuous_mode_enabled())
|
||||
return;
|
||||
|
||||
/* This symbol is defined by the compiler when runtime counter relocation is
|
||||
* used and runtime provides a weak alias so we can check if it's defined. */
|
||||
void *BiasAddr = &INSTR_PROF_PROFILE_COUNTER_BIAS_VAR;
|
||||
void *BiasDefaultAddr = &INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR;
|
||||
if (BiasAddr == BiasDefaultAddr) {
|
||||
PROF_ERR("%s\n", "__llvm_profile_counter_bias is undefined");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the sizes of various profile data sections. Taken from
|
||||
* __llvm_profile_get_size_for_buffer(). */
|
||||
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||
const uint64_t *CountersBegin = __llvm_profile_begin_counters();
|
||||
const uint64_t *CountersEnd = __llvm_profile_end_counters();
|
||||
uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
|
||||
const uint64_t CountersOffset =
|
||||
sizeof(__llvm_profile_header) + (DataSize * sizeof(__llvm_profile_data));
|
||||
|
||||
int Length = getCurFilenameLength();
|
||||
char *FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
|
||||
const char *Filename = getCurFilename(FilenameBuf, 0);
|
||||
if (!Filename)
|
||||
return;
|
||||
|
||||
FILE *File = NULL;
|
||||
char *Profile = NULL;
|
||||
|
||||
if (!doMerging()) {
|
||||
File = fopen(Filename, "w+b");
|
||||
if (!File)
|
||||
return;
|
||||
|
||||
if (writeMMappedFile(File, &Profile) == -1) {
|
||||
fclose(File);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
File = lprofOpenFileEx(Filename);
|
||||
if (!File)
|
||||
return;
|
||||
|
||||
uint64_t ProfileFileSize = 0;
|
||||
if (getProfileFileSizeForMerging(File, &ProfileFileSize) == -1) {
|
||||
lprofUnlockFileHandle(File);
|
||||
fclose(File);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ProfileFileSize) {
|
||||
if (writeMMappedFile(File, &Profile) == -1) {
|
||||
fclose(File);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* The merged profile has a non-zero length. Check that it is compatible
|
||||
* with the data in this process. */
|
||||
if (mmapProfileForMerging(File, ProfileFileSize, &Profile) == -1) {
|
||||
fclose(File);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lprofUnlockFileHandle(File);
|
||||
}
|
||||
|
||||
/* Update the profile fields based on the current mapping. */
|
||||
INSTR_PROF_PROFILE_COUNTER_BIAS_VAR =
|
||||
(intptr_t)Profile - (uintptr_t)CountersBegin +
|
||||
CountersOffset;
|
||||
|
||||
/* Return the memory allocated for counters to OS. */
|
||||
lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin, (uintptr_t)CountersEnd);
|
||||
}
|
||||
#else
|
||||
static void initializeProfileForContinuousMode(void) {
|
||||
PROF_ERR("%s\n", "continuous mode is unsupported on this platform");
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *DefaultProfileName = "default.profraw";
|
||||
static void resetFilenameToDefault(void) {
|
||||
@@ -784,9 +813,14 @@ static int parseFilenamePattern(const char *FilenamePat,
|
||||
FilenamePat);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__) || defined(__ELF__) || defined(_WIN32)
|
||||
__llvm_profile_set_page_size(getpagesize());
|
||||
__llvm_profile_enable_continuous_mode();
|
||||
#else
|
||||
PROF_WARN("%s", "Continous mode is currently only supported for Mach-O,"
|
||||
" ELF and COFF formats.");
|
||||
return -1;
|
||||
#endif
|
||||
} else {
|
||||
unsigned MergePoolSize = getMergePoolSize(FilenamePat, &I);
|
||||
if (!MergePoolSize)
|
||||
@@ -843,12 +877,8 @@ static void parseAndSetFilename(const char *FilenamePat,
|
||||
}
|
||||
|
||||
truncateCurrentFile();
|
||||
if (__llvm_profile_is_continuous_mode_enabled()) {
|
||||
if (lprofRuntimeCounterRelocation())
|
||||
relocateCounters();
|
||||
else
|
||||
initializeProfileForContinuousMode();
|
||||
}
|
||||
if (__llvm_profile_is_continuous_mode_enabled())
|
||||
initializeProfileForContinuousMode();
|
||||
}
|
||||
|
||||
/* Return buffer length that is required to store the current profile
|
||||
@@ -1004,9 +1034,6 @@ void __llvm_profile_initialize_file(void) {
|
||||
ProfileNameSpecifier PNS = PNS_unknown;
|
||||
int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR[0] != 0);
|
||||
|
||||
if (__llvm_profile_counter_bias != -1)
|
||||
lprofSetRuntimeCounterRelocation(1);
|
||||
|
||||
EnvFilenamePat = getFilenamePatFromEnv();
|
||||
if (EnvFilenamePat) {
|
||||
/* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
|
||||
|
||||
Reference in New Issue
Block a user