Index: llvm/lib/MC/WinCOFFObjectWriter.cpp =================================================================== --- llvm/lib/MC/WinCOFFObjectWriter.cpp +++ llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -944,6 +944,38 @@ Reloc.Data.Type = OWriter.TargetObjectWriter->getRelocType( Asm.getContext(), Target, Fixup, SymB, Asm.getBackend()); + if (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARM64 && + Reloc.Data.Type == COFF::IMAGE_REL_ARM64_BRANCH26 && + A.isTemporary()) { + // For a b/bl instruction that branches a temporary symbol + // (private assembly label), an IMAGE_REL_ARM64_BRANCH26 + // relocation to another symbol + a non-zero offset could be + // emitted but the linkers (link.exe and lld) don't currently + // support this type of relocation and cause incorrect relocations + // and crashes. Avoid this by using a relative offset without a + // relocation if within the same section or inserting a new symbol + // otherwise. + if (MCSec == &A.getSection()) { + // If within the same section, write the relative offset in the + // instruction to symbol A and drop the relocation. Set to the + // correct relative offset. + FixedValue = Layout.getSymbolOffset(A) - Reloc.Data.VirtualAddress; + // Cancel the increment above. + --Reloc.Symb->Relocations; + // Drop the relocation. + return; + } else { + // Add a non-temporary symbol at A and use a relocation to that + // symbol without an offset. + COFFSymbol *NewSymbol = createSymbol(("$L" + A.getName()).str()); + NewSymbol->Section = SectionMap[&A.getSection()]; + NewSymbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_LABEL; + NewSymbol->Data.Value = Layout.getSymbolOffset(A); + Reloc.Symb = NewSymbol; + FixedValue = 0; + } + } + // The *_REL32 relocations are relative to the end of the relocation, // not to the start. if ((Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 && Index: llvm/test/MC/AArch64/coff-relocations-branch26.s =================================================================== --- /dev/null +++ llvm/test/MC/AArch64/coff-relocations-branch26.s @@ -0,0 +1,31 @@ +// RUN: llvm-mc -triple aarch64-unknown-windows-msvc -filetype obj %s -o - | \ +// RUN: llvm-objdump -D -r - | FileCheck %s + + .text +main: + nop + b .Ltarget + b .Lother_target +.Ltarget: + ret + +// A privte label target in another section + .section "other" + nop +.Lother_target: + ret + +// Check that the first branch has a correct branch offset and that +// the second (cross-section) branch has a zero offset with a +// relocation. +// +// CHECK: 0000000000000000
: +// CHECK: 0: d503201f nop +// CHECK: 4: 14000002 b 0xc +// CHECK: 8: 14000000 b 0x8 +// CHECK: 0000000000000008: IMAGE_REL_ARM64_BRANCH26 $L.Lother_target +// CHECK: c: d65f03c0 ret +// CHECK: 0000000000000000 : +// CHECK: 0: d503201f nop +// CHECK: 0000000000000004 <$L.Lother_target>: +// CHECK: 4: d65f03c0 ret