diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 5 | ||||
-rw-r--r-- | llvm/test/ExecutionEngine/RuntimeDyld/PowerPC/ppc64_reloc.s | 48 |
2 files changed, 51 insertions, 2 deletions
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 322883f4fea..e15fd0b124b 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -772,8 +772,9 @@ void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section, int64_t delta = static_cast<int64_t>(Value - FinalAddress + Addend); if (SignExtend64<26>(delta) != delta) llvm_unreachable("Relocation R_PPC64_REL24 overflow"); - // Generates a 'bl <address>' instruction - writeInt32BE(LocalAddress, 0x48000001 | (delta & 0x03FFFFFC)); + // We preserve bits other than LI field, i.e. PO and AA/LK fields. + uint32_t Inst = readBytesUnaligned(LocalAddress, 4); + writeInt32BE(LocalAddress, (Inst & 0xFC000003) | (delta & 0x03FFFFFC)); } break; case ELF::R_PPC64_REL32: { uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); diff --git a/llvm/test/ExecutionEngine/RuntimeDyld/PowerPC/ppc64_reloc.s b/llvm/test/ExecutionEngine/RuntimeDyld/PowerPC/ppc64_reloc.s new file mode 100644 index 00000000000..9a859ead22c --- /dev/null +++ b/llvm/test/ExecutionEngine/RuntimeDyld/PowerPC/ppc64_reloc.s @@ -0,0 +1,48 @@ +# test for little endian +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=powerpc64le-unknown-linux-gnu -filetype=obj -o %t/ppc64_reloc.o %s +# RUN: llvm-mc -triple=powerpc64le-unknown-linux-gnu -filetype=obj -o %t/ppc64_elf_module_b.o %S/Inputs/ppc64_elf_module_b.s +# RUN: llvm-rtdyld -triple=powerpc64le-unknown-linux-gnu -verify -check=%s %t/ppc64_reloc.o %t/ppc64_elf_module_b.o +# test for big endian +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=powerpc64-unknown-linux-gnu -filetype=obj -o %t/ppc64_reloc.o %s +# RUN: llvm-mc -triple=powerpc64-unknown-linux-gnu -filetype=obj -o %t/ppc64_elf_module_b.o %S/Inputs/ppc64_elf_module_b.s +# RUN: llvm-rtdyld -triple=powerpc64-unknown-linux-gnu -verify -check=%s %t/ppc64_reloc.o %t/ppc64_elf_module_b.o + + .text + .abiversion 2 + .file "test.c" + .globl func + .p2align 4 + .type func,@function +func: # @func +.Lfunc_begin0: +.Lfunc_gep0: + addis 2, 12, .TOC.-.Lfunc_gep0@ha + addi 2, 2, .TOC.-.Lfunc_gep0@l +.Lfunc_lep0: + .localentry func, .Lfunc_lep0-.Lfunc_gep0 + mflr 0 + std 31, -8(1) + std 0, 16(1) + stdu 1, -112(1) + mr 31, 1 +# confirm that LK flag is set for bl +# rtdyld-check: (*{4}call_bl) & 1 = 1 +call_bl: + bl foo + nop + + li 3, 0 + addi 1, 1, 112 + ld 0, 16(1) + ld 31, -8(1) + mtlr 0 +# confirm that LK flag is not set for b +# rtdyld-check: (*{4}call_b) & 1 = 0 +call_b: + b foo + .long 0 + .quad 0 +.Lfunc_end0: + .size func, .Lfunc_end0-.Lfunc_begin0 |