[BOLT] Fix data race while running split functions pass

Summary:
In BinaryContext::calculateEmittedSize(), after the temporary code
emission, we have to perform a cleanup and mark all symbols used
during the emission as undefined and unregistered (so that we can emit
them again later). The cleanup is happening even for symbols that were
referenced and not defined by emitted code.

If all emitted symbols are local, there is no risk that one thread will
define a symbol while some other thread will undefine it in its cleanup
code. Such behavior is expected as local symbols can only be referenced
within the containing function and each function is processed in one
thread. However, secondary entry points have associated global symbols
and if we emit them, then it is possible for a thread to undefine
a symbol while the other thread had defined it and was in the process of
emitting the fragment with it. In such case, a data race may happen and
the thread that contains the definition of the symbol may define it
twice causing a redefinition error.

To avoid the data race, we skip the emission of secondary entry global
symbols when emitting code used only for the size estimation.

(cherry picked from FBD24986007)
This commit is contained in:
Maksim Panchenko 2020-11-16 14:34:51 -08:00
parent 1e9b733008
commit 7eaf63a118
3 changed files with 11 additions and 7 deletions

View File

@ -1948,10 +1948,11 @@ BinaryContext::calculateEmittedSize(BinaryFunction &BF, bool FixBranches) {
auto *Section = MCEInstance.LocalMOFI->getTextSection();
Section->setHasInstructions(true);
auto *StartLabel = LocalCtx->getOrCreateSymbol("__hstart");
auto *EndLabel = LocalCtx->getOrCreateSymbol("__hend");
auto *ColdStartLabel = LocalCtx->getOrCreateSymbol("__cstart");
auto *ColdEndLabel = LocalCtx->getOrCreateSymbol("__cend");
// Create symbols in the LocalCtx so that they get destroyed with it.
MCSymbol *StartLabel = LocalCtx->createTempSymbol();
MCSymbol *EndLabel = LocalCtx->createTempSymbol();
MCSymbol *ColdStartLabel = LocalCtx->createTempSymbol();
MCSymbol *ColdEndLabel = LocalCtx->createTempSymbol();
Streamer->SwitchSection(Section);
Streamer->EmitLabel(StartLabel);

View File

@ -1190,7 +1190,8 @@ public:
MCEInstance.LocalMOFI = llvm::make_unique<MCObjectFileInfo>();
MCEInstance.LocalCtx = llvm::make_unique<MCContext>(
AsmInfo.get(), MRI.get(), MCEInstance.LocalMOFI.get());
MCEInstance.LocalMOFI->InitMCObjectFileInfo(*TheTriple, /*PIC=*/false,
MCEInstance.LocalMOFI->InitMCObjectFileInfo(*TheTriple,
/*PIC=*/!HasFixedLoadAddress,
*MCEInstance.LocalCtx);
MCEInstance.MCE.reset(
TheTarget->createMCCodeEmitter(*MII, *MRI, *MCEInstance.LocalCtx));

View File

@ -398,9 +398,11 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, bool EmitColdPart,
BB->getAlignmentMaxBytes());
}
Streamer.EmitLabel(BB->getLabel());
if (!EmitCodeOnly) {
if (auto *EntrySymbol = BF.getSecondaryEntryPointSymbol(*BB)) {
Streamer.EmitLabel(EntrySymbol);
}
}
// Check if special alignment for macro-fusion is needed.
bool MayNeedMacroFusionAlignment =