diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp --- a/llvm/lib/MC/XCOFFObjectWriter.cpp +++ b/llvm/lib/MC/XCOFFObjectWriter.cpp @@ -635,6 +635,18 @@ report_fatal_error("TOCEntryOffset overflows in small code model mode"); FixedValue = TOCEntryOffset; + } else if (Type == XCOFF::RelocationType::R_RBR && + SymASec->getMappingClass() == XCOFF::XMC_PR) { + MCSectionXCOFF *ParentSec = cast(Fragment->getParent()); + // The address of the branch instruction should be the sum of section + // address, fragment offset and Fixup offset. + uint64_t BRInstrAddress = SectionMap[ParentSec]->Address + + Layout.getFragmentOffset(Fragment) + + Fixup.getOffset(); + // The FixedValue should be the difference between SymA csect address and BR + // instr address plus any constant value. + FixedValue = + SectionMap[SymASec]->Address - BRInstrAddress + Target.getConstant(); } assert((Fixup.getOffset() <= diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-funcsect.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-funcsect.ll --- a/llvm/test/CodeGen/PowerPC/aix-xcoff-funcsect.ll +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-funcsect.ll @@ -10,12 +10,14 @@ ; RUN: -filetype=obj -o %t32.o < %s ; RUN: llvm-objdump --syms --reloc --symbol-description %t32.o | \ ; RUN: FileCheck --check-prefix=XCOFF32 %s +; RUN: llvm-objdump -dr %t32.o | FileCheck --check-prefix=DIS32 %s ; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr4 \ ; RUN: -mattr=-altivec -function-sections -xcoff-traceback-table=true \ ; RUN: -filetype=obj -o %t64.o < %s ; RUN: llvm-objdump --syms --reloc --symbol-description %t64.o | \ ; RUN: FileCheck --check-prefix=XCOFF64 %s +; RUN: llvm-objdump -dr %t64.o | FileCheck --check-prefix=DIS64 %s @alias_foo = alias void (...), bitcast (void ()* @foo to void (...)*) @@ -176,3 +178,56 @@ ; XCOFF64-NEXT: 0000000000000038 R_POS (idx: 27) TOC[TC0] ; XCOFF64-NEXT: 0000000000000048 R_POS (idx: 15) .static_overalign_foo[PR] ; XCOFF64-NEXT: 0000000000000050 R_POS (idx: 27) TOC[TC0] + +; DIS32: Disassembly of section .text: +; DIS32: 00000000 <.alias_foo>: +; DIS32-NEXT: 0: 4e 80 00 20 blr +; DIS32: 00000020 <.hidden_foo>: +; DIS32-NEXT: 20: 4e 80 00 20 blr +; DIS32: 00000040 <.bar>: +; DIS32-NEXT: 40: 7c 08 02 a6 mflr 0 +; DIS32-NEXT: 44: 94 21 ff c0 stwu 1, -64(1) +; DIS32-NEXT: 48: 90 01 00 48 stw 0, 72(1) +; DIS32-NEXT: 4c: 4b ff ff b5 bl 0x0 <.alias_foo> +; DIS32-NEXT: 0000004c: R_RBR .foo +; DIS32-NEXT: 50: 60 00 00 00 nop +; DIS32-NEXT: 54: 48 00 00 6d bl 0xc0 <.static_overalign_foo> +; DIS32-NEXT: 00000054: R_RBR .static_overalign_foo +; DIS32-NEXT: 58: 60 00 00 00 nop +; DIS32-NEXT: 5c: 4b ff ff a5 bl 0x0 <.alias_foo> +; DIS32-NEXT: 0000005c: R_RBR .alias_foo +; DIS32-NEXT: 60: 60 00 00 00 nop +; DIS32-NEXT: 64: 4b ff ff 9d bl 0x0 <.alias_foo> +; DIS32-NEXT: 00000064: R_RBR .extern_foo +; DIS32-NEXT: 68: 60 00 00 00 nop +; DIS32-NEXT: 6c: 4b ff ff b5 bl 0x20 <.hidden_foo> +; DIS32-NEXT: 0000006c: R_RBR .hidden_foo +; DIS32: 000000c0 <.static_overalign_foo>: +; DIS32-NEXT: c0: 4e 80 00 20 blr + +; DIS64: Disassembly of section .text: +; DIS64: 0000000000000000 <.alias_foo>: +; DIS64-NEXT: 0: 4e 80 00 20 blr +; DIS64: 0000000000000020 <.hidden_foo>: +; DIS64-NEXT: 20: 4e 80 00 20 blr +; DIS64: 0000000000000040 <.bar>: +; DIS64-NEXT: 40: 7c 08 02 a6 mflr 0 +; DIS64-NEXT: 44: f8 21 ff 91 stdu 1, -112(1) +; DIS64-NEXT: 48: f8 01 00 80 std 0, 128(1) +; DIS64-NEXT: 4c: 4b ff ff b5 bl 0x0 <.alias_foo> +; DIS64-NEXT: 000000000000004c: R_RBR .foo +; DIS64-NEXT: 50: 60 00 00 00 nop +; DIS64-NEXT: 54: 48 00 00 6d bl 0xc0 <.static_overalign_foo> +; DIS64-NEXT: 0000000000000054: R_RBR .static_overalign_foo +; DIS64-NEXT: 58: 60 00 00 00 nop +; DIS64-NEXT: 5c: 4b ff ff a5 bl 0x0 <.alias_foo> +; DIS64-NEXT: 000000000000005c: R_RBR .alias_foo +; DIS64-NEXT: 60: 60 00 00 00 nop +; DIS64-NEXT: 64: 4b ff ff 9d bl 0x0 <.alias_foo> +; DIS64-NEXT: 0000000000000064: R_RBR .extern_foo +; DIS64-NEXT: 68: 60 00 00 00 nop +; DIS64-NEXT: 6c: 4b ff ff b5 bl 0x20 <.hidden_foo> +; DIS64-NEXT: 000000000000006c: R_RBR .hidden_foo +; DIS64-NEXT: 70: 60 00 00 00 nop +; DIS64: 00000000000000c0 <.static_overalign_foo>: +; DIS64-NEXT: c0: 4e 80 00 20 blr