Index: include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def =================================================================== --- include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def +++ include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def @@ -35,6 +35,7 @@ #undef R_PPC64_ADDR16_HIGHERA #undef R_PPC64_ADDR16_HIGHEST #undef R_PPC64_ADDR16_HIGHESTA +#undef R_PPC64_UADDR64 #undef R_PPC64_REL64 #undef R_PPC64_TOC16 #undef R_PPC64_TOC16_LO @@ -128,6 +129,7 @@ ELF_RELOC(R_PPC64_ADDR16_HIGHERA, 40) ELF_RELOC(R_PPC64_ADDR16_HIGHEST, 41) ELF_RELOC(R_PPC64_ADDR16_HIGHESTA, 42) +ELF_RELOC(R_PPC64_UADDR64, 43) ELF_RELOC(R_PPC64_REL64, 44) ELF_RELOC(R_PPC64_TOC16, 47) ELF_RELOC(R_PPC64_TOC16_LO, 48) Index: lib/MC/ELFObjectWriter.cpp =================================================================== --- lib/MC/ELFObjectWriter.cpp +++ lib/MC/ELFObjectWriter.cpp @@ -922,6 +922,7 @@ void ELFWriter::writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec) { std::vector &Relocs = OWriter.Relocations[&Sec]; + unsigned EMachine = OWriter.TargetObjectWriter->getEMachine(); // We record relocations by pushing to the end of a vector. Reverse the vector // to get the relocations in the order they were created. @@ -938,7 +939,7 @@ if (is64Bit()) { write(Entry.Offset); - if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) { + if (EMachine == ELF::EM_MIPS) { write(uint32_t(Index)); write(OWriter.TargetObjectWriter->getRSsym(Entry.Type)); @@ -947,7 +948,11 @@ write(OWriter.TargetObjectWriter->getRType(Entry.Type)); } else { struct ELF::Elf64_Rela ERE64; - ERE64.setSymbolAndType(Index, Entry.Type); + unsigned Type = Entry.Type; + if (EMachine == ELF::EM_PPC64 && Type == ELF::R_PPC64_ADDR64 && + Entry.Offset % 8 != 0) + Type = ELF::R_PPC64_UADDR64; + ERE64.setSymbolAndType(Index, Type); write(ERE64.r_info); } if (hasRelocationAddend()) @@ -956,13 +961,17 @@ write(uint32_t(Entry.Offset)); struct ELF::Elf32_Rela ERE32; - ERE32.setSymbolAndType(Index, Entry.Type); + unsigned Type = Entry.Type; + if (EMachine == ELF::EM_PPC && Type == ELF::R_PPC_ADDR32 && + Entry.Offset % 4 != 0) + Type = ELF::R_PPC_UADDR32; + ERE32.setSymbolAndType(Index, Type); write(ERE32.r_info); if (hasRelocationAddend()) write(uint32_t(Entry.Addend)); - if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) { + if (EMachine == ELF::EM_MIPS) { if (uint32_t RType = OWriter.TargetObjectWriter->getRType2(Entry.Type)) { write(uint32_t(Entry.Offset)); Index: lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp =================================================================== --- lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -400,6 +400,7 @@ Type = ELF::R_PPC64_TOC; break; case MCSymbolRefExpr::VK_None: + // R_PPC64_UADDR64 may be emitted if r_offset % 8 != 0. Type = ELF::R_PPC64_ADDR64; break; case MCSymbolRefExpr::VK_PPC_DTPMOD: @@ -414,6 +415,7 @@ } break; case FK_Data_4: + // R_PPC_UADDR32 may be emitted if r_offset % 4 != 0. Type = ELF::R_PPC_ADDR32; break; case FK_Data_2: Index: test/MC/PowerPC/ppc32-uaddr.s =================================================================== --- /dev/null +++ test/MC/PowerPC/ppc32-uaddr.s @@ -0,0 +1,9 @@ +# RUN: llvm-mc -filetype=obj -triple=powerpc %s | llvm-readobj -r | FileCheck %s + +# CHECK: 0x1 R_PPC_UADDR32 foo 0x0 +# CHECK-NEXT: 0x5 R_PPC_UADDR32 foo 0x1 + +.data +.byte 0 +.long foo +.long foo+1 Index: test/MC/PowerPC/ppc64-uaddr.s =================================================================== --- /dev/null +++ test/MC/PowerPC/ppc64-uaddr.s @@ -0,0 +1,10 @@ +# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s | llvm-readobj -r | FileCheck %s +# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s | llvm-readobj -r | FileCheck %s + +# CHECK: 0x1 R_PPC64_UADDR64 foo 0x0 +# CHECK-NEXT: 0x9 R_PPC64_UADDR64 foo 0x1 + +.data +.byte 0 +.quad foo +.quad foo+1