https://sourceware.org/bugzilla/show_bug.cgi?id=24896
Bug ID: 24896 Summary: [powerpc] gas should emit R_PPC_UADDR32/R_PPC64_UADDR64 at unaligned locations if the section is sufficiently aligned Product: binutils Version: 2.33 (HEAD) Status: UNCONFIRMED Severity: normal Priority: P2 Component: gas Assignee: unassigned at sourceware dot org Reporter: maskray at google dot com Target Milestone: --- Related to both gas and ld. gas emits R_PPC_ADDR32 and R_PPC64_ADDR64 at unaligned locations. ld converts R_PPC64_ADDR64 to R_PPC64_UADDR64 if unaligned, and R_PPC64_UADDR64 to R_PPC64_ADDR64 if aligned. bfd/elf64-ppc.c:ppc64_elf_relocate_section /* Optimize unaligned reloc use. */ if ((r_type == R_PPC64_ADDR64 && (out_off & 7) != 0) || (r_type == R_PPC64_UADDR64 && (out_off & 7) == 0)) r_type ^= R_PPC64_ADDR64 ^ R_PPC64_UADDR64; else if ((r_type == R_PPC64_ADDR32 && (out_off & 3) != 0) || (r_type == R_PPC64_UADDR32 && (out_off & 3) == 0)) r_type ^= R_PPC64_ADDR32 ^ R_PPC64_UADDR32; else if ((r_type == R_PPC64_ADDR16 && (out_off & 1) != 0) || (r_type == R_PPC64_UADDR16 && (out_off & 1) == 0)) r_type ^= R_PPC64_ADDR16 ^ R_PPC64_UADDR16; % d.c char y; struct{char _; const char *x; char *y;} __attribute__((packed)) _ = {'_', "a", &y}; void _start() {} % powerpc64le-linux-gnu-gcc -c -fpic d.c; readelf -Wr d.o | grep R_PPC64 0000000000000001 0000000500000026 R_PPC64_ADDR64 0000000000000000 .rodata + 0 0000000000000009 0000000900000026 R_PPC64_ADDR64 0000000000000001 y + 0 % powerpc64le-linux-gnu-ld -pie d.o -o d; readelf -Wr d | grep R_PPC64 0000000000020001 000000010000002b R_PPC64_UADDR64 0000000000000298 .text + 28 0000000000020009 000000020000002b R_PPC64_UADDR64 0000000000020000 .data + 11 % powerpc64le-linux-gnu-ld -shared d.o -o d.so; readelf -Wr d.so | grep R_PPC64 0000000000020001 000000010000002b R_PPC64_UADDR64 0000000000000288 .text + 28 0000000000020009 000000040000002b R_PPC64_UADDR64 0000000000020011 y + 0 This is not the case on powerpc. ld doesn't do such unaligned reloc optimization: % powerpc-linux-gnu-gcc -c -fpic d.c; readelf -Wr d.o | grep R_PPC 00000001 00000501 R_PPC_ADDR32 00000000 .rodata + 0 00000005 00000901 R_PPC_ADDR32 00000001 y + 0 % powerpc-linux-gnu-ld -pie d.o -o d; re -Wr d | grep R_PPC 00020001 00000016 R_PPC_RELATIVE 1b8 00020005 00000016 R_PPC_RELATIVE 2001c % powerpc-linux-gnu-ld -shared d.o -o d.so; re -Wr d.so | grep R_PPC 00020001 00000016 R_PPC_RELATIVE 1c4 00020005 00000301 R_PPC_ADDR32 0002001c y + 0 * gcc/as: R_PPC_UADDR32 and R_PPC64_UADDR64 should be produced. If sh_addralign is sufficiently aligned, gas should emit UADDR at an unaligned location. Otherwise (e.g. sh_addralign=1), gas probably can't reasonably decide whether ADDR/UADDR should be used at an unaligned location. Maybe gcc should emit more information to help gas? * ld: I am still not clear whether the ADDR -> UADDR conversion is reasonable, but 64-bit UADDR -> ADDR conversion can probably be dropped, it has very little benefit. The expected result: % powerpc-linux-gnu-gcc -c -fpic d.c; readelf -Wr d.o | grep R_PPC ... R_PPC_UADDR32 ... R_PPC_UADDR32 % powerpc-linux-gnu-ld -pie d.o -o d; re -Wr d | grep R_PPC ... R_PPC_UADDR32 # ADDR can use RELATIVE if the target symbol is non-preemptable but UADDR can't. ... R_PPC_UADDR32 % powerpc-linux-gnu-ld -shared d.o -o d.so; re -Wr d.so | grep R_PPC ... R_PPC_UADDR32 ... R_PPC_UADDR32 -- You are receiving this mail because: You are on the CC list for the bug. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils