elf32-hppa.c lacks support for several 14-bit PA 2.0 relocations (e.g., DPREL14WR and DPREL14DR). Primarily, support is lacking for floating point loads and stores with long displacements. We lack both non-pic and pic relocations. Details can be found in the "Processor-Specific ELF Supplement for PA-RISC": https://www.google.com/url?sa=t&source=web&rct=j&opi=89978449&url=https://refspecs.linuxfoundation.org/elf/elf-pa.pdf&ved=2ahUKEwjzx8bvkvmEAxU_5ckDHbCQCLYQFnoECBQQAQ&usg=AOvVaw3MBtDH0Qd2IHQpBF_3vBbN Because of the lack of support for these relocations, gcc must block generation of both integer and floating-point instructions that potentially use these relocations before the reload pass completes. This results in an extra addil instruction to compute each memory address. After reload, it is possible to remove the extra addil when we have an integer move but this results in less optimal code than would be generated if symbolic references could be handled before reload. Not sure if addil removal is actually supported.
It appears gas always generates R_PARISC_DPREL14 for dp relative relocations in loads and stores. This gives us format 14 and hppa_rebuild_insn gives case 14: return (insn & ~ 0x3fff) | re_assemble_14 (value); This clears the least significant three bits of the insn, so it will clobber the t field at bit 30 in a fldw instruction.
Created attachment 15431 [details] Assembly file Attached is an assembly file demonstrating the problem. It's derived from the assembly output at -O1 for the gcc.c-torture/execute/packed-aligned.c test. I changed this code addil LR'g_expect-$global$,%r27 fstd %fr22,RR'g_expect-$global$(%r1) in main to addil LR'g_expect-$global$,%r27 fstd %fr22,RR'g_expect-$global$(%r1) ldo RR'g_expect-$global$(%r1),%r1 fstd %fr22,0(%r1) so I could see what was happening to the symbolic relocation in the fstd instruction. This is the code in the final executable: 10574: 2b 60 00 00 addil L%0,dp,r1 10578: 70 36 00 20 std r22,10(r1) 1057c: 34 21 00 20 ldo 10(r1),r1 10580: 2c 20 12 16 fstd fr22,0(r1) The fstd instruction has changed to a std instruction. In the .o object file, we have: 7c: 2b 60 00 00 addil L%0,dp,r1 80: 70 36 00 02 fstd fr22,0(r1) 84: 34 21 00 00 ldo 0(r1),r1 88: 2c 20 12 16 fstd fr22,0(r1) We have the following relocations: 0000007c R_PARISC_DPREL21L g_expect 00000080 R_PARISC_DPREL14R g_expect 00000084 R_PARISC_DPREL14R g_expect The format 3 (im10a) variants of ldd and fldd differ in bit 30. ldd has a 0 and fldd a 1.
Created attachment 15432 [details] Patch Fixes testcase. I think elf64-hppa.c is also broken in a similar way.
Created attachment 15436 [details] Patch Update original patch to check whether symbolic displacements are valid.
Created attachment 15439 [details] Patch This version fixes corrects previous patch. There still be issues with $global$ not being 8-byte aligned. It is provided by: DATA_START_SYMBOLS='PROVIDE ($global$ = .);' I added a hack to elf_hppa_fake_sections to increase alignment of the .data section to 8 bytes minimum. I now see an alignment of 8 for .data in .o files. But the alignment of .data may get reduced to 4 in final link when a .o file contains comdat groups. Not sure why. Is there a better way to align .data? This doesn't happen if I align .data to 8 in elf.sc. But this would affect all users. I guess I could use a separate script for 32-bit elf hppa but I would like to avoid this if possible.
This fails to align $global$ value under all circumstances: diff --git a/ld/emulparams/hppalinux.sh b/ld/emulparams/hppalinux.sh index 7892df9130d..f302606360a 100644 --- a/ld/emulparams/hppalinux.sh +++ b/ld/emulparams/hppalinux.sh @@ -25,7 +25,7 @@ NOP=0x08000240 START="_start" OTHER_READONLY_SECTIONS=" .PARISC.unwind ${RELOCATING-0} : { *(.PARISC.unwind) }" -DATA_START_SYMBOLS='PROVIDE ($global$ = .);' +DATA_START_SYMBOLS='PROVIDE ($global$ = (. + 7) & ~ 7);' DATA_PLT= PLT_BEFORE_GOT= GENERATE_SHLIB_SCRIPT=yes Will try aligning .data.
That should use ALIGN(8).
I already tried it. It also sometimes fails to align the $global$ address. spawn -ignore SIGHUP /home/dave/gnu/gcc/objdir/./gcc/xg++ -shared-libgcc -B/home /dave/gnu/gcc/objdir/./gcc -nostdinc++ -L/home/dave/gnu/gcc/objdir/hppa-linux-gn u/libstdc++-v3/src -L/home/dave/gnu/gcc/objdir/hppa-linux-gnu/libstdc++-v3/src/. libs -L/home/dave/gnu/gcc/objdir/hppa-linux-gnu/libstdc++-v3/libsupc++/.libs -B/ home/dave/opt/gnu/gcc/gcc-14/hppa-linux-gnu/bin/ -B/home/dave/opt/gnu/gcc/gcc-14 /hppa-linux-gnu/lib/ -isystem /home/dave/opt/gnu/gcc/gcc-14/hppa-linux-gnu/inclu de -isystem /home/dave/opt/gnu/gcc/gcc-14/hppa-linux-gnu/sys-include -fchecking= 1 -B/home/dave/gnu/gcc/objdir/hppa-linux-gnu/./libstdc++-v3/src/.libs -fmessage- length=0 -fno-show-column -ffunction-sections -fdata-sections -g -O2 -D_GNU_SOUR CE -DLOCALEDIR="." -nostdinc++ -I/home/dave/gnu/gcc/objdir/hppa-linux-gnu/libstd c++-v3/include/hppa-linux-gnu -I/home/dave/gnu/gcc/objdir/hppa-linux-gnu/libstdc ++-v3/include -I/home/dave/gnu/gcc/gcc/libstdc++-v3/libsupc++ -I/home/dave/gnu/g cc/gcc/libstdc++-v3/include/backward -I/home/dave/gnu/gcc/gcc/libstdc++-v3/tests uite/util /home/dave/gnu/gcc/gcc/libstdc++-v3/testsuite/23_containers/vector/req uirements/exception/generation_prohibited.cc -std=gnu++17 -include bits/stdc++.h -fdiagnostics-plain-output ./libtestc++.a -Wl,--gc-sections -L/home/dave/gnu/gc c/objdir/hppa-linux-gnu/libstdc++-v3/src/filesystem/.libs -L/home/dave/gnu/gcc/o bjdir/hppa-linux-gnu/libstdc++-v3/src/experimental/.libs -lm -o ./generation_pro hibited.exe /home/dave/opt/gnu/bin/ld: /tmp/cc2Eie9V.o(.text._ZN10__gnu_test10setup_base8populateISt6vectorIN9__gnu_cxx18throw_value_randomENS3_22throw_allocator_randomIS4_EEELb1EEC2ERS7_[_ZN10__gnu_test10setup_base8populateISt6vectorIN9__gnu_cxx18throw_value_randomENS3_22throw_allocator_randomIS4_EEELb1EEC5ERS7_]+0x288): displacement 0x5cc for insn 0x51370002 is not a multiple of 8 (gp 0x161c4) /home/dave/opt/gnu/bin/ld: /tmp/cc2Eie9V.o(.text._ZN10__gnu_test10setup_base8populateISt6vectorIN9__gnu_cxx18throw_value_randomENS3_22throw_allocator_randomIS4_EEELb1EEC2ERS7_[_ZN10__gnu_test10setup_base8populateISt6vectorIN9__gnu_cxx18throw_value_randomENS3_22throw_allocator_randomIS4_EEELb1EEC5ERS7_]+0x288): cannot handle R_PARISC_DPREL14R for _ZZN9__gnu_cxx16random_condition8generateEvE9generator /home/dave/opt/gnu/bin/ld: final link failed: bad value collect2: error: ld returned 1 exit status compiler exited with status 1 FAIL: 23_containers/vector/requirements/exception/generation_prohibited.cc -std=gnu++17 (test for excess errors) Excess errors: /home/dave/opt/gnu/bin/ld: /tmp/cc2Eie9V.o(.text._ZN10__gnu_test10setup_base8populateISt6vectorIN9__gnu_cxx18throw_value_randomENS3_22throw_allocator_randomIS4_EEELb1EEC2ERS7_[_ZN10__gnu_test10setup_base8populateISt6vectorIN9__gnu_cxx18throw_value_randomENS3_22throw_allocator_randomIS4_EEELb1EEC5ERS7_]+0x288): displacement 0x5cc for insn 0x51370002 is not a multiple of 8 (gp 0x161c4) /home/dave/opt/gnu/bin/ld: /tmp/cc2Eie9V.o(.text._ZN10__gnu_test10setup_base8populateISt6vectorIN9__gnu_cxx18throw_value_randomENS3_22throw_allocator_randomIS4_EEELb1EEC2ERS7_[_ZN10__gnu_test10setup_base8populateISt6vectorIN9__gnu_cxx18throw_value_randomENS3_22throw_allocator_randomIS4_EEELb1EEC5ERS7_]+0x288): cannot handle R_PARISC_DPREL14R for _ZZN9__gnu_cxx16random_condition8generateEvE9generator /home/dave/opt/gnu/bin/ld: final link failed: bad value collect2: error: ld returned 1 exit status The gp value is 4-byte aligned (0x161c4).
(In reply to Andreas Schwab from comment #7) > That should use ALIGN(8). ALIGN inside an output section statement doesn't align the section, just the current *relative* value of dot. So the effect is exacly the same as John's expression. They both align zero to a multiple of eight and thus do nothing.
On 2024-03-28 7:20 p.m., amodra at gmail dot com wrote: > https://sourceware.org/bugzilla/show_bug.cgi?id=31503 > > --- Comment #9 from Alan Modra <amodra at gmail dot com> --- > (In reply to Andreas Schwab from comment #7) >> That should use ALIGN(8). > ALIGN inside an output section statement doesn't align the section, just the > current *relative* value of dot. So the effect is exacly the same as John's > expression. They both align zero to a multiple of eight and thus do nothing. Okay. I was hoping that the expression would align the value assigned to $global$. This change appears to successfully align .data: dave@mx3210:~/gnu/binutils/src/ld/scripttempl$ diff -u elf.sc elf32hppa.sc --- elf.sc 2024-03-28 21:45:32.560456976 +0000 +++ elf32hppa.sc 2024-03-28 22:26:32.625611275 +0000 @@ -669,7 +669,7 @@ ${DATA_PLT+${PLT_BEFORE_GOT-${PLT}}} - .data ${RELOCATING-0} : + .data ${RELOCATING-0} ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+ALIGN(8)}}} : { ${RELOCATING+${DATA_START_SYMBOLS}} *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*}) But it causes two testsuite fails: PASS: Build pr23162b FAIL: Build libpr23161a.so PASS: Build pr23161a FAIL: Build libpr23161b.so regexp_diff match failure regexp "^Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains [0-9 ]+ entries:$" line "Relocation section '.rela.got' at offset 0x19c contains 3 entries:" output is Relocation section '.rela.got' at offset 0x19c contains 3 entries: Offset Info Type Sym. Value Symbol's Name + Addend 00001088 00000501 R_PARISC_DIR32 00001094 __bss_start + 0 0000108c 00000301 R_PARISC_DIR32 00001094 _edata + 0 00001090 00000401 R_PARISC_DIR32 00001094 _end + 0 If this isn't serious, I can just modify the regexp. Otherwise, do you have any thoughts on how to work around this issue.
On 2024-03-28 7:34 p.m., dave.anglin at bell dot net wrote: > https://sourceware.org/bugzilla/show_bug.cgi?id=31503 > > --- Comment #10 from dave.anglin at bell dot net --- > On 2024-03-28 7:20 p.m., amodra at gmail dot com wrote: >> https://sourceware.org/bugzilla/show_bug.cgi?id=31503 >> >> --- Comment #9 from Alan Modra <amodra at gmail dot com> --- >> (In reply to Andreas Schwab from comment #7) >>> That should use ALIGN(8). >> ALIGN inside an output section statement doesn't align the section, just the >> current *relative* value of dot. So the effect is exacly the same as John's >> expression. They both align zero to a multiple of eight and thus do nothing. > Okay. I was hoping that the expression would align the value assigned to > $global$. > > This change appears to successfully align .data: > > dave@mx3210:~/gnu/binutils/src/ld/scripttempl$ diff -u elf.sc elf32hppa.sc > --- elf.sc 2024-03-28 21:45:32.560456976 +0000 > +++ elf32hppa.sc 2024-03-28 22:26:32.625611275 +0000 > @@ -669,7 +669,7 @@ > > ${DATA_PLT+${PLT_BEFORE_GOT-${PLT}}} > > - .data ${RELOCATING-0} : > + .data ${RELOCATING-0} ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+ALIGN(8)}}} : > { > ${RELOCATING+${DATA_START_SYMBOLS}} > *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*}) > > But it causes two testsuite fails: > > PASS: Build pr23162b > FAIL: Build libpr23161a.so > PASS: Build pr23161a > FAIL: Build libpr23161b.so > > regexp_diff match failure > regexp "^Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains > [0-9 > ]+ entries:$" > line "Relocation section '.rela.got' at offset 0x19c contains 3 entries:" > output is > Relocation section '.rela.got' at offset 0x19c contains 3 entries: > Offset Info Type Sym. Value Symbol's Name + Addend > 00001088 00000501 R_PARISC_DIR32 00001094 __bss_start + 0 > 0000108c 00000301 R_PARISC_DIR32 00001094 _edata + 0 > 00001090 00000401 R_PARISC_DIR32 00001094 _end + 0 > > If this isn't serious, I can just modify the regexp. Otherwise, do you have > any thoughts > on how to work around this issue. Found it. Need to define "GENERATE_COMBRELOC_SCRIPT=yes".
Created attachment 15446 [details] Patch Fixes alignment of .data. Maybe the alignment for .data could be done in elf.sc so a new script isn't required?
Patch: https://sourceware.org/pipermail/binutils/2024-April/133261.html
The master branch has been updated by John David Anglin <danglin@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a82e3815dfffe60a257021c592e2dceca719a04a commit a82e3815dfffe60a257021c592e2dceca719a04a Author: John David Anglin <danglin@gcc.gnu.org> Date: Mon Apr 1 23:00:52 2024 +0000 hppa: Implement PA 2.0 symbolic relocations for long displacements The PA 2.0 architecture introduced several new load and store instructions with long displacements. These include floating point loads and stores for word mode, and integer and floating point loads and stores for double words. Currently, ld does not correctly support symbolic relocations for these instructions. If these are used, ld applies the standard R_PARISC_DPREL14R relocation and corrupts the instruction. This change uses bfd_hppa_insn2fmt to determine the correct relocation format. We need to check the computed displacement as the immediate value used in these instruction must be a multiple of 4 or 8 depending on whether the access is for a word or double word. A misaligned offset can potentially occur if the symbol is not properly aligned or if $global$ (the global pointer) is not double word aligned. $global$ is provided as a .data section start symbol. The patch adjusts elf.sc and hppalinux.sh to align .data to a 8-byte boundary in non-shared and non-pie links. 2024-04-01 John David Anglin <danglin@gcc.gnu.org> PR ld/31503 bfd/ChangeLog: * elf32-hppa.c (final_link_relocate): Output ld/ChangeLog: * emulparams/hppalinux.sh (DATA_SECTION_ALIGNMENT): Define. * scripttempl/elf.sc: Align .data section to DATA_SECTION_ALIGNMENT when relocating.
Fixed on trunk.
The binutils-2_42-branch branch has been updated by John David Anglin <danglin@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d125f9675372b1ae01ceb1893c06ccb27bc7bf22 commit d125f9675372b1ae01ceb1893c06ccb27bc7bf22 Author: John David Anglin <danglin@gcc.gnu.org> Date: Mon Apr 1 23:00:52 2024 +0000 hppa: Implement PA 2.0 symbolic relocations for long displacements The PA 2.0 architecture introduced several new load and store instructions with long displacements. These include floating point loads and stores for word mode, and integer and floating point loads and stores for double words. Currently, ld does not correctly support symbolic relocations for these instructions. If these are used, ld applies the standard R_PARISC_DPREL14R relocation and corrupts the instruction. This change uses bfd_hppa_insn2fmt to determine the correct relocation format. We need to check the computed displacement as the immediate value used in these instruction must be a multiple of 4 or 8 depending on whether the access is for a word or double word. A misaligned offset can potentially occur if the symbol is not properly aligned or if $global$ (the global pointer) is not double word aligned. $global$ is provided as a .data section start symbol. The patch adjusts elf.sc and hppalinux.sh to align .data to a 8-byte boundary in non-shared and non-pie links. 2024-04-01 John David Anglin <danglin@gcc.gnu.org> PR ld/31503 bfd/ChangeLog: * elf32-hppa.c (final_link_relocate): Output ld/ChangeLog: * emulparams/hppalinux.sh (DATA_SECTION_ALIGNMENT): Define. * scripttempl/elf.sc: Align .data section to DATA_SECTION_ALIGNMENT when relocating.