Bug 31503 - [hppa] Unsupported 14-bit PA 2.0 relocations for 32-bit (narrow) mode (elf32-hppa.c)
Summary: [hppa] Unsupported 14-bit PA 2.0 relocations for 32-bit (narrow) mode (elf32-...
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: unspecified
: P2 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-03-16 16:21 UTC by John David Anglin
Modified: 2024-04-03 22:12 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Assembly file (628 bytes, text/plain)
2024-03-23 15:54 UTC, John David Anglin
Details
Patch (391 bytes, patch)
2024-03-23 20:37 UTC, John David Anglin
Details | Diff
Patch (606 bytes, patch)
2024-03-25 22:21 UTC, John David Anglin
Details | Diff
Patch (957 bytes, patch)
2024-03-27 22:04 UTC, John David Anglin
Details | Diff
Patch (8.38 KB, patch)
2024-03-29 14:50 UTC, John David Anglin
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description John David Anglin 2024-03-16 16:21:14 UTC
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.
Comment 1 John David Anglin 2024-03-18 17:08:47 UTC
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.
Comment 2 John David Anglin 2024-03-23 15:54:55 UTC
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.
Comment 3 John David Anglin 2024-03-23 20:37:51 UTC
Created attachment 15432 [details]
Patch

Fixes testcase.

I think elf64-hppa.c is also broken in a similar way.
Comment 4 John David Anglin 2024-03-25 22:21:35 UTC
Created attachment 15436 [details]
Patch

Update original patch to check whether symbolic displacements are valid.
Comment 5 John David Anglin 2024-03-27 22:04:03 UTC
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.
Comment 6 John David Anglin 2024-03-28 13:31:14 UTC
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.
Comment 7 Andreas Schwab 2024-03-28 13:47:42 UTC
That should use ALIGN(8).
Comment 8 dave.anglin 2024-03-28 15:11:51 UTC
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).
Comment 9 Alan Modra 2024-03-28 23:20:51 UTC
(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.
Comment 10 dave.anglin 2024-03-28 23:34:12 UTC
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.
Comment 11 dave.anglin 2024-03-29 00:43:39 UTC
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".
Comment 12 John David Anglin 2024-03-29 14:50:10 UTC
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?
Comment 13 John David Anglin 2024-04-01 18:12:50 UTC
Patch:
https://sourceware.org/pipermail/binutils/2024-April/133261.html
Comment 14 Sourceware Commits 2024-04-01 23:01:57 UTC
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.
Comment 15 John David Anglin 2024-04-01 23:04:51 UTC
Fixed on trunk.
Comment 16 Sourceware Commits 2024-04-03 22:12:37 UTC
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.