@@ -683,11 +683,15 @@ void LongJmpPass::relaxLocalBranches(BinaryFunction &BF) {
683683 DenseMap<const BinaryBasicBlock *, BinaryBasicBlock *> FragmentTrampolines;
684684
685685 // Create a trampoline code after \p BB or at the end of the fragment if BB
686- // is nullptr.
686+ // is nullptr. If /p UpdateOffsets is true, update FragmentSize and offsets
687+ // for basic blocks affected by the insertion of the trampoline.
687688 auto addTrampolineAfter = [&](BinaryBasicBlock *BB,
688689 BinaryBasicBlock *TargetBB, uint64_t Count,
689690 bool UpdateOffsets = true ) {
690- std::unique_ptr<BinaryBasicBlock> TrampolineBB = BF.createBasicBlock ();
691+ FunctionTrampolines.emplace_back (BB ? BB : FF.back (),
692+ BF.createBasicBlock ());
693+ BinaryBasicBlock *TrampolineBB = FunctionTrampolines.back ().second .get ();
694+
691695 MCInst Inst;
692696 {
693697 auto L = BC.scopeLock ();
@@ -702,37 +706,46 @@ void LongJmpPass::relaxLocalBranches(BinaryFunction &BF) {
702706 TrampolineBB->setOutputEndAddress (TrampolineAddress + TrampolineSize);
703707 TrampolineBB->setFragmentNum (FF.getFragmentNum ());
704708
705- if (UpdateOffsets) {
706- FragmentSize += TrampolineSize;
707- for (BinaryBasicBlock *IBB : FF) {
708- if (IBB->getOutputStartAddress () >= TrampolineAddress) {
709- IBB->setOutputStartAddress (IBB->getOutputStartAddress () +
710- TrampolineSize);
711- IBB->setOutputEndAddress (IBB->getOutputEndAddress () +
709+ if (!FragmentTrampolines.lookup (TargetBB))
710+ FragmentTrampolines[TargetBB] = TrampolineBB;
711+
712+ if (!UpdateOffsets)
713+ return TrampolineBB;
714+
715+ FragmentSize += TrampolineSize;
716+
717+ // If the trampoline was added at the end of the fragment, offsets of
718+ // other fragments should stay intact.
719+ if (!BB)
720+ return TrampolineBB;
721+
722+ // Update offsets for blocks after BB.
723+ for (BinaryBasicBlock *IBB : FF) {
724+ if (IBB->getOutputStartAddress () >= TrampolineAddress) {
725+ IBB->setOutputStartAddress (IBB->getOutputStartAddress () +
712726 TrampolineSize);
713- }
727+ IBB-> setOutputEndAddress (IBB-> getOutputEndAddress () + TrampolineSize);
714728 }
715- for (auto &Pair : FunctionTrampolines) {
716- BinaryBasicBlock *IBB = Pair.second .get ();
717- if (IBB->getFragmentNum () != TrampolineBB->getFragmentNum ())
718- continue ;
719- if (IBB == TrampolineBB.get ())
720- continue ;
721- if (IBB->getOutputStartAddress () >= TrampolineAddress) {
722- IBB->setOutputStartAddress (IBB->getOutputStartAddress () +
723- TrampolineSize);
724- IBB->setOutputEndAddress (IBB->getOutputEndAddress () +
729+ }
730+
731+ // Update offsets for trampolines in this fragment that are placed after
732+ // the new trampoline. Note that trampoline blocks are not part of the
733+ // function/fragment layout until we add them right before the return
734+ // from relaxLocalBranches().
735+ for (auto &Pair : FunctionTrampolines) {
736+ BinaryBasicBlock *IBB = Pair.second .get ();
737+ if (IBB->getFragmentNum () != TrampolineBB->getFragmentNum ())
738+ continue ;
739+ if (IBB == TrampolineBB)
740+ continue ;
741+ if (IBB->getOutputStartAddress () >= TrampolineAddress) {
742+ IBB->setOutputStartAddress (IBB->getOutputStartAddress () +
725743 TrampolineSize);
726- }
744+ IBB-> setOutputEndAddress (IBB-> getOutputEndAddress () + TrampolineSize);
727745 }
728746 }
729747
730- if (!FragmentTrampolines.lookup (TargetBB))
731- FragmentTrampolines[TargetBB] = TrampolineBB.get ();
732- FunctionTrampolines.emplace_back (BB ? BB : FF.back (),
733- std::move (TrampolineBB));
734-
735- return FunctionTrampolines.back ().second .get ();
748+ return TrampolineBB;
736749 };
737750
738751 // Pre-populate trampolines by splitting unconditional branches from the
0 commit comments