@@ -416,17 +416,6 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF,
416
416
BF.duplicateConstantIslands ();
417
417
}
418
418
419
- if (!FF.empty () && FF.front ()->isLandingPad ()) {
420
- assert (!FF.front ()->isEntryPoint () &&
421
- " Landing pad cannot be entry point of function" );
422
- // If the first block of the fragment is a landing pad, it's offset from the
423
- // start of the area that the corresponding LSDA describes is zero. In this
424
- // case, the call site entries in that LSDA have 0 as offset to the landing
425
- // pad, which the runtime interprets as "no handler". To prevent this,
426
- // insert some padding.
427
- Streamer.emitBytes (BC.MIB ->getTrapFillValue ());
428
- }
429
-
430
419
// Track the first emitted instruction with debug info.
431
420
bool FirstInstr = true ;
432
421
for (BinaryBasicBlock *const BB : FF) {
@@ -926,39 +915,54 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
926
915
// Emit the LSDA header.
927
916
928
917
// If LPStart is omitted, then the start of the FDE is used as a base for
929
- // landing pad displacements. Then if a cold fragment starts with
930
- // a landing pad, this means that the first landing pad offset will be 0.
931
- // As a result, the exception handling runtime will ignore this landing pad
932
- // because zero offset denotes the absence of a landing pad.
933
- // For this reason, when the binary has fixed starting address we emit LPStart
934
- // as 0 and output the absolute value of the landing pad in the table.
918
+ // landing pad displacements. Then, if a cold fragment starts with a landing
919
+ // pad, this means that the first landing pad offset will be 0. However, C++
920
+ // runtime treats 0 as if there is no landing pad present, thus we *must* emit
921
+ // non-zero offsets for all valid LPs.
935
922
//
936
- // If the base address can change, we cannot use absolute addresses for
937
- // landing pads (at least not without runtime relocations). Hence, we fall
938
- // back to emitting landing pads relative to the FDE start.
939
- // As we are emitting label differences, we have to guarantee both labels are
940
- // defined in the same section and hence cannot place the landing pad into a
941
- // cold fragment when the corresponding call site is in the hot fragment.
942
- // Because of this issue and the previously described issue of possible
943
- // zero-offset landing pad we have to place landing pads in the same section
944
- // as the corresponding invokes for shared objects.
923
+ // As a solution, for fixed-address binaries we set LPStart to 0, and for
924
+ // position-independent binaries we set LP start to FDE start minus one byte
925
+ // for FDEs that start with a landing pad.
926
+ const bool NeedsLPAdjustment = !FF.empty () && FF.front ()->isLandingPad ();
945
927
std::function<void (const MCSymbol *)> emitLandingPad;
946
928
if (BC.HasFixedLoadAddress ) {
947
929
Streamer.emitIntValue (dwarf::DW_EH_PE_udata4, 1 ); // LPStart format
948
930
Streamer.emitIntValue (0 , 4 ); // LPStart
949
931
emitLandingPad = [&](const MCSymbol *LPSymbol) {
950
- if (!LPSymbol)
951
- Streamer.emitIntValue (0 , 4 );
952
- else
932
+ if (LPSymbol)
953
933
Streamer.emitSymbolValue (LPSymbol, 4 );
934
+ else
935
+ Streamer.emitIntValue (0 , 4 );
954
936
};
955
937
} else {
956
- Streamer.emitIntValue (dwarf::DW_EH_PE_omit, 1 ); // LPStart format
938
+ if (NeedsLPAdjustment) {
939
+ // Use relative LPStart format and emit LPStart as [SymbolStart - 1].
940
+ Streamer.emitIntValue (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1 );
941
+ MCSymbol *DotSymbol = BC.Ctx ->createTempSymbol (" LPBase" );
942
+ Streamer.emitLabel (DotSymbol);
943
+
944
+ const MCExpr *LPStartExpr = MCBinaryExpr::createSub (
945
+ MCSymbolRefExpr::create (StartSymbol, *BC.Ctx ),
946
+ MCSymbolRefExpr::create (DotSymbol, *BC.Ctx ), *BC.Ctx );
947
+ LPStartExpr = MCBinaryExpr::createSub (
948
+ LPStartExpr, MCConstantExpr::create (1 , *BC.Ctx ), *BC.Ctx );
949
+ Streamer.emitValue (LPStartExpr, 4 );
950
+ } else {
951
+ // DW_EH_PE_omit means FDE start (StartSymbol) will be used as LPStart.
952
+ Streamer.emitIntValue (dwarf::DW_EH_PE_omit, 1 );
953
+ }
957
954
emitLandingPad = [&](const MCSymbol *LPSymbol) {
958
- if (!LPSymbol)
955
+ if (LPSymbol) {
956
+ const MCExpr *LPOffsetExpr = MCBinaryExpr::createSub (
957
+ MCSymbolRefExpr::create (LPSymbol, *BC.Ctx ),
958
+ MCSymbolRefExpr::create (StartSymbol, *BC.Ctx ), *BC.Ctx );
959
+ if (NeedsLPAdjustment)
960
+ LPOffsetExpr = MCBinaryExpr::createAdd (
961
+ LPOffsetExpr, MCConstantExpr::create (1 , *BC.Ctx ), *BC.Ctx );
962
+ Streamer.emitValue (LPOffsetExpr, 4 );
963
+ } else {
959
964
Streamer.emitIntValue (0 , 4 );
960
- else
961
- Streamer.emitAbsoluteSymbolDiff (LPSymbol, StartSymbol, 4 );
965
+ }
962
966
};
963
967
}
964
968
0 commit comments