@@ -140,7 +140,7 @@ class BinaryEmitter {
140140
141141 void emitCFIInstruction (const MCCFIInstruction &Inst) const ;
142142
143- // / Emit exception handling ranges for the function.
143+ // / Emit exception handling ranges for the function fragment .
144144 void emitLSDA (BinaryFunction &BF, const FunctionFragment &FF);
145145
146146 // / Emit line number information corresponding to \p NewLoc. \p PrevLoc
@@ -416,17 +416,6 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF,
416416 BF.duplicateConstantIslands ();
417417 }
418418
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-
430419 // Track the first emitted instruction with debug info.
431420 bool FirstInstr = true ;
432421 for (BinaryBasicBlock *const BB : FF) {
@@ -926,39 +915,72 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
926915 // Emit the LSDA header.
927916
928917 // 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
918+ // landing pad displacements. Then, if a cold fragment starts with
930919 // 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.
920+ // However, C++ runtime will treat 0 as if there is no landing pad, thus we
921+ // cannot emit LP offset as 0.
935922 //
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 offset LP start by one byte.
925+ bool NeedsLPAdjustment = false ;
945926 std::function<void (const MCSymbol *)> emitLandingPad;
946- if (BC.HasFixedLoadAddress ) {
927+
928+ // Check if there's a symbol associated with a landing pad fragment.
929+ const MCSymbol *LPStartSymbol = BF.getLPStartSymbol (FF.getFragmentNum ());
930+ if (!LPStartSymbol) {
931+ // Since landing pads are not in the same fragment, we fall back to emitting
932+ // absolute addresses for this FDE.
933+ if (opts::Verbosity >= 2 ) {
934+ BC.outs () << " BOLT-INFO: falling back to generating absolute-address "
935+ << " exception ranges for " << BF << ' \n ' ;
936+ }
937+
938+ assert (BC.HasFixedLoadAddress &&
939+ " Cannot emit absolute-address landing pads for PIE/DSO" );
940+
947941 Streamer.emitIntValue (dwarf::DW_EH_PE_udata4, 1 ); // LPStart format
948942 Streamer.emitIntValue (0 , 4 ); // LPStart
949943 emitLandingPad = [&](const MCSymbol *LPSymbol) {
950- if (!LPSymbol)
951- Streamer.emitIntValue (0 , 4 );
952- else
944+ if (LPSymbol)
953945 Streamer.emitSymbolValue (LPSymbol, 4 );
946+ else
947+ Streamer.emitIntValue (0 , 4 );
954948 };
955949 } else {
956- Streamer.emitIntValue (dwarf::DW_EH_PE_omit, 1 ); // LPStart format
950+ std::optional<FragmentNum> LPFN = BF.getLPFragment (FF.getFragmentNum ());
951+ const FunctionFragment &LPFragment = BF.getLayout ().getFragment (*LPFN);
952+ NeedsLPAdjustment =
953+ (!LPFragment.empty () && LPFragment.front ()->isLandingPad ());
954+
955+ // Emit LPStart encoding and optionally LPStart.
956+ if (NeedsLPAdjustment || LPStartSymbol != StartSymbol) {
957+ Streamer.emitIntValue (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1 );
958+ MCSymbol *DotSymbol = BC.Ctx ->createTempSymbol (" LPBase" );
959+ Streamer.emitLabel (DotSymbol);
960+
961+ const MCExpr *LPStartExpr = MCBinaryExpr::createSub (
962+ MCSymbolRefExpr::create (LPStartSymbol, *BC.Ctx ),
963+ MCSymbolRefExpr::create (DotSymbol, *BC.Ctx ), *BC.Ctx );
964+ if (NeedsLPAdjustment)
965+ LPStartExpr = MCBinaryExpr::createSub (
966+ LPStartExpr, MCConstantExpr::create (1 , *BC.Ctx ), *BC.Ctx );
967+ Streamer.emitValue (LPStartExpr, 4 );
968+ } else {
969+ // DW_EH_PE_omit means FDE start (StartSymbol) will be used as LPStart.
970+ Streamer.emitIntValue (dwarf::DW_EH_PE_omit, 1 );
971+ }
957972 emitLandingPad = [&](const MCSymbol *LPSymbol) {
958- if (!LPSymbol)
959- Streamer.emitIntValue (0 , 4 );
960- else
961- Streamer.emitAbsoluteSymbolDiff (LPSymbol, StartSymbol, 4 );
973+ if (LPSymbol) {
974+ const MCExpr *LPOffsetExpr = MCBinaryExpr::createSub (
975+ MCSymbolRefExpr::create (LPSymbol, *BC.Ctx ),
976+ MCSymbolRefExpr::create (LPStartSymbol, *BC.Ctx ), *BC.Ctx );
977+ if (NeedsLPAdjustment)
978+ LPOffsetExpr = MCBinaryExpr::createAdd (
979+ LPOffsetExpr, MCConstantExpr::create (1 , *BC.Ctx ), *BC.Ctx );
980+ Streamer.emitULEB128Value (LPOffsetExpr);
981+ } else {
982+ Streamer.emitULEB128IntValue (0 );
983+ }
962984 };
963985 }
964986
@@ -972,10 +994,12 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
972994 Streamer.emitLabel (TTBaseRefLabel);
973995 }
974996
975- // Emit the landing pad call site table. We use signed data4 since we can emit
976- // a landing pad in a different part of the split function that could appear
977- // earlier in the address space than LPStart.
978- Streamer.emitIntValue (dwarf::DW_EH_PE_sdata4, 1 );
997+ // Emit encoding of entries in the call site table. The format is used for the
998+ // call site start, length, and corresponding landing pad.
999+ if (!LPStartSymbol)
1000+ Streamer.emitIntValue (dwarf::DW_EH_PE_sdata4, 1 );
1001+ else
1002+ Streamer.emitIntValue (dwarf::DW_EH_PE_uleb128, 1 );
9791003
9801004 MCSymbol *CSTStartLabel = BC.Ctx ->createTempSymbol (" CSTStart" );
9811005 MCSymbol *CSTEndLabel = BC.Ctx ->createTempSymbol (" CSTEnd" );
@@ -992,8 +1016,13 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
9921016
9931017 // Start of the range is emitted relative to the start of current
9941018 // function split part.
995- Streamer.emitAbsoluteSymbolDiff (BeginLabel, StartSymbol, 4 );
996- Streamer.emitAbsoluteSymbolDiff (EndLabel, BeginLabel, 4 );
1019+ if (!LPStartSymbol) {
1020+ Streamer.emitAbsoluteSymbolDiff (BeginLabel, StartSymbol, 4 );
1021+ Streamer.emitAbsoluteSymbolDiff (EndLabel, BeginLabel, 4 );
1022+ } else {
1023+ Streamer.emitAbsoluteSymbolDiffAsULEB128 (BeginLabel, StartSymbol);
1024+ Streamer.emitAbsoluteSymbolDiffAsULEB128 (EndLabel, BeginLabel);
1025+ }
9971026 emitLandingPad (CallSite.LP );
9981027 Streamer.emitULEB128IntValue (CallSite.Action );
9991028 }
0 commit comments