bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Fix selector bug on hppa elf targets


From: John David Anglin
Subject: Fix selector bug on hppa elf targets
Date: Mon, 4 Feb 2002 14:59:54 -0500 (EST)

The following patch fixes a problem that I found trying to bootstrap the
current main branch of gcc on hppa-linux.  I found that the function "fold"
in fold-const.c was being miscompiled.  A long branch fell 0x1000 short of
its target causing a segementation fault compiling crtbegin.o.

Because the first stage is normally built without optimization, this results
in the generation of long branches to the return in large functions.  The
problematic code output by gcc was:

        ldil    L'Lxxxx,%r1
        be      R'Lxxxx,(%sr4,%r1)

This generates relocation types DIR21L and DIR17R for the ldil and be,
respectively.  The DIR17L is not reduced because hppa_fix_adjustable
doesn't reduce "absolute" jumps.  However, the ldil is reduced to a
section offset.  Then, in the final link, LR and RR selectors are
applied to the addends which differ in this case by substantial amounts
because reduction was applied in one case but not the other.

Because the "Processor-Specific ELF Supplement for PA-RISC" doesn't
provide a way to pass selectors, every relocation type is implicitly
associated with a selector used in the final link.  In this case,
there is no way to tell the final link that we would like L/R instead
of LR/RR.

Now reduction can't be done with LR/RR selectors since writing

        ldil    LR%foo+0,%r21
        ldw     RR%foo+0(%r21),%r26
        ldw     RR%foo+4(%r21),%r25

will potentially fail because of the different rounding.  Thus, we
can't reduce relocation types that implicitly use LR/RR selectors
even if a different selector is actually specified.  The downside
to this is that we end up with many more local labels in object
files.

Possibly, a warning should be generated.  However, I believe that
the SOM format can pass the selctor information to the linker.  Thus,
I don't thing gcc should be changed to use LR/RR selectors.

As far as I can tell, this patch causes GNU as and ld to behave in
a manner similar to the HP hppa64 tools.  I have tested this patch
by running the binutils testsuite under hppa-linux and hppa64-hp-hpux11.11.
I have also done gcc builds and checks with the patch.

The fix to selective.exp is self explanatory although my fix is
unique.  The other systems that need to link against libgcc seem
to have provided a solution that assumes that it is in a predetermined
location.

Please apply if ok.

Dave
-- 
J. David Anglin                                  address@hidden
National Research Council of Canada              (613) 990-0752 (FAX: 952-6605)

2002-02-04  John David Anglin  <address@hidden>

        * bfd/elf-hppa.h (elf_hppa_reloc_final_type): New function stripped
        from _bfd_elf_hppa_gen_reloc_type.
        * bfd/elf32-hppa.h (elf_hppa_reloc_final_type): Add protptype.
        * bfd/elf64-hppa.h (elf_hppa_reloc_final_type): Add protptype.
        * gas/config/tc-hppa.c (hppa_fix_adjustable): Don't adjust final types
        that implicitly use LR and RR selectors.
        * gas/testsuite/gas/hppa/reloc/reloc.exp (labelopbug.s): Change test
        to reflect above change.

        * ld/testsuite/ld-selective/selective.exp: Link against libgcc
        on hppa*-*-linux* targets.

Index: bfd/elf-hppa.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-hppa.h,v
retrieving revision 1.52
diff -u -3 -p -r1.52 elf-hppa.h
--- elf-hppa.h  2001/11/23 12:17:18     1.52
+++ elf-hppa.h  2002/02/03 23:52:47
@@ -44,6 +44,9 @@ Foundation, Inc., 59 Temple Place - Suit
 #define elf_hppa_final_link elf32_hppa_final_link
 #endif
 
+elf_hppa_reloc_type elf_hppa_reloc_final_type
+  PARAMS ((bfd *, elf_hppa_reloc_type, int, unsigned int));
+
 elf_hppa_reloc_type ** _bfd_elf_hppa_gen_reloc_type
   PARAMS ((bfd *, elf_hppa_reloc_type, int, unsigned int, int, asymbol *));
 
@@ -605,41 +608,18 @@ static reloc_howto_type elf_hppa_howto_t
 #define OFFSET_14R_FROM_21L 4
 #define OFFSET_14F_FROM_21L 5
 
-/* Return one (or more) BFD relocations which implement the base
-   relocation with modifications based on format and field.  */
+/* Return the final relocation type for the given base type, instruction
+   format, and field selector.  */
 
-elf_hppa_reloc_type **
-_bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym)
+elf_hppa_reloc_type
+elf_hppa_reloc_final_type (abfd, base_type, format, field)
      bfd *abfd;
      elf_hppa_reloc_type base_type;
      int format;
      unsigned int field;
-     int ignore ATTRIBUTE_UNUSED;
-     asymbol *sym ATTRIBUTE_UNUSED;
 {
-  elf_hppa_reloc_type *finaltype;
-  elf_hppa_reloc_type **final_types;
-  bfd_size_type amt = sizeof (elf_hppa_reloc_type *) * 2;
-
-  /* Allocate slots for the BFD relocation.  */
-  final_types = (elf_hppa_reloc_type **) bfd_alloc (abfd, amt);
-  if (final_types == NULL)
-    return NULL;
+  elf_hppa_reloc_type final_type = base_type;
 
-  /* Allocate space for the relocation itself.  */
-  amt = sizeof (elf_hppa_reloc_type);
-  finaltype = (elf_hppa_reloc_type *) bfd_alloc (abfd, amt);
-  if (finaltype == NULL)
-    return NULL;
-
-  /* Some reasonable defaults.  */
-  final_types[0] = finaltype;
-  final_types[1] = NULL;
-
-#define final_type finaltype[0]
-
-  final_type = base_type;
-
   /* Just a tangle of nested switch statements to deal with the braindamage
      that a different field selector means a completely different relocation
      for PA ELF.  */
@@ -677,7 +657,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = R_PARISC_PLABEL14R;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
@@ -693,7 +673,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = R_PARISC_DIR17R;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
@@ -717,7 +697,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = R_PARISC_PLABEL21L;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
@@ -736,7 +716,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = R_PARISC_PLABEL32;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
@@ -750,12 +730,12 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = R_PARISC_FPTR64;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
        default:
-         return NULL;
+         return R_PARISC_NONE;
        }
       break;
 
@@ -776,7 +756,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = base_type + OFFSET_14F_FROM_21L;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
@@ -792,12 +772,12 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = base_type;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
        default:
-         return NULL;
+         return R_PARISC_NONE;
        }
       break;
 
@@ -811,7 +791,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = R_PARISC_PCREL12F;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
@@ -829,7 +809,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = R_PARISC_PCREL14F;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
@@ -845,7 +825,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = R_PARISC_PCREL17F;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
@@ -860,7 +840,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = R_PARISC_PCREL21L;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
@@ -871,12 +851,12 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
              final_type = R_PARISC_PCREL22F;
              break;
            default:
-             return NULL;
+             return R_PARISC_NONE;
            }
          break;
 
        default:
-         return NULL;
+         return R_PARISC_NONE;
        }
       break;
 
@@ -888,8 +868,44 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base
       break;
 
     default:
-      return NULL;
+      return R_PARISC_NONE;
     }
+
+  return final_type;
+}
+
+/* Return one (or more) BFD relocations which implement the base
+   relocation with modifications based on format and field.  */
+
+elf_hppa_reloc_type **
+_bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym)
+     bfd *abfd;
+     elf_hppa_reloc_type base_type;
+     int format;
+     unsigned int field;
+     int ignore ATTRIBUTE_UNUSED;
+     asymbol *sym ATTRIBUTE_UNUSED;
+{
+  elf_hppa_reloc_type *finaltype;
+  elf_hppa_reloc_type **final_types;
+  bfd_size_type amt = sizeof (elf_hppa_reloc_type *) * 2;
+
+  /* Allocate slots for the BFD relocation.  */
+  final_types = (elf_hppa_reloc_type **) bfd_alloc (abfd, amt);
+  if (final_types == NULL)
+    return NULL;
+
+  /* Allocate space for the relocation itself.  */
+  amt = sizeof (elf_hppa_reloc_type);
+  finaltype = (elf_hppa_reloc_type *) bfd_alloc (abfd, amt);
+  if (finaltype == NULL)
+    return NULL;
+
+  /* Some reasonable defaults.  */
+  final_types[0] = finaltype;
+  final_types[1] = NULL;
+
+  finaltype[0] = elf_hppa_reloc_final_type (abfd, base_type, format, field);
 
   return final_types;
 }
Index: bfd/elf32-hppa.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-hppa.h,v
retrieving revision 1.10
diff -u -3 -p -r1.10 elf32-hppa.h
--- elf32-hppa.h        2001/03/08 21:03:59     1.10
+++ elf32-hppa.h        2002/02/03 23:52:47
@@ -47,6 +47,9 @@ boolean elf32_hppa_set_gp
 boolean elf32_hppa_build_stubs
   PARAMS ((struct bfd_link_info *));
 
+elf_hppa_reloc_type elf_hppa_reloc_final_type
+  PARAMS ((bfd *, elf_hppa_reloc_type, int, unsigned int));
+
 extern elf_hppa_reloc_type ** _bfd_elf32_hppa_gen_reloc_type
   PARAMS ((bfd *, elf_hppa_reloc_type, int, unsigned int, int, asymbol *));
 
Index: bfd/elf64-hppa.h
===================================================================
RCS file: /cvs/src/src/bfd/elf64-hppa.h,v
retrieving revision 1.3
diff -u -3 -p -r1.3 elf64-hppa.h
--- elf64-hppa.h        2001/03/08 21:04:00     1.3
+++ elf64-hppa.h        2002/02/03 23:52:47
@@ -25,6 +25,9 @@ Foundation, Inc., 59 Temple Place - Suit
 #include "libhppa.h"
 #include "elf/hppa.h"
 
+elf_hppa_reloc_type elf_hppa_reloc_final_type
+  PARAMS ((bfd *, elf_hppa_reloc_type, int, unsigned int));
+
 extern elf_hppa_reloc_type ** _bfd_elf64_hppa_gen_reloc_type
   PARAMS ((bfd *, elf_hppa_reloc_type, int, unsigned int, int, asymbol *));
 
Index: gas/config/tc-hppa.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-hppa.c,v
retrieving revision 1.92
diff -u -3 -p -r1.92 tc-hppa.c
--- tc-hppa.c   2001/12/31 23:47:02     1.92
+++ tc-hppa.c   2002/02/03 23:52:47
@@ -8373,6 +8373,7 @@ int
 hppa_fix_adjustable (fixp)
      fixS *fixp;
 {
+  reloc_type code;
   struct hppa_fix_struct *hppa_fix;
 
   hppa_fix = (struct hppa_fix_struct *) fixp->tc_fix_data;
@@ -8384,9 +8385,57 @@ hppa_fix_adjustable (fixp)
 #endif
 
 #ifdef OBJ_ELF
-  if (fixp->fx_r_type == (int) R_PARISC_GNU_VTINHERIT
-      || fixp->fx_r_type ==  (int) R_PARISC_GNU_VTENTRY)
-    return 0;
+  /* LR/RR selectors are implicitly used for a number of different relocation
+     types.  We must ensure that none of these types are adjusted (see below)
+     even if they occur with a different selector.  */
+  code = elf_hppa_reloc_final_type (stdoutput, fixp->fx_r_type,
+                                   hppa_fix->fx_r_format,
+                                   hppa_fix->fx_r_field);
+
+  switch (code)
+    {
+    /* Relocation types which use e_lrsel.  */
+    case R_PARISC_DIR21L:
+    case R_PARISC_DLTIND21L:
+    case R_PARISC_DLTREL21L:
+    case R_PARISC_DPREL21L:
+    case R_PARISC_LTOFF_FPTR21L:
+    case R_PARISC_LTOFF_TP21L:
+    case R_PARISC_PCREL21L:
+    case R_PARISC_PLABEL21L:
+    case R_PARISC_PLTOFF21L:
+
+    /* Relocation types which use e_rrsel.  */
+    case R_PARISC_DIR14R:
+    case R_PARISC_DIR14DR:
+    case R_PARISC_DIR14WR:
+    case R_PARISC_DIR17R:
+    case R_PARISC_DLTIND14R:
+    case R_PARISC_DLTIND14DR:
+    case R_PARISC_DLTIND14WR:
+    case R_PARISC_DLTREL14R:
+    case R_PARISC_DLTREL14DR:
+    case R_PARISC_DLTREL14WR:
+    case R_PARISC_DPREL14R:
+    case R_PARISC_DPREL14DR:
+    case R_PARISC_DPREL14WR:
+    case R_PARISC_PCREL14R:
+    case R_PARISC_PCREL17R:
+    case R_PARISC_PLABEL14R:
+    case R_PARISC_LTOFF_FPTR14R:
+    case R_PARISC_LTOFF_FPTR14DR:
+    case R_PARISC_LTOFF_FPTR14WR:
+    case R_PARISC_LTOFF_TP14R:
+    case R_PARISC_LTOFF_TP14DR:
+    case R_PARISC_LTOFF_TP14WR:
+
+    /* Other types that we reject for reduction.  */
+    case R_PARISC_GNU_VTENTRY:
+    case R_PARISC_GNU_VTINHERIT:
+      return 0;
+    default:
+      break;
+    }
 #endif
 
   if (fixp->fx_addsy && (S_IS_EXTERNAL (fixp->fx_addsy)
Index: gas/testsuite/gas/hppa/reloc/reloc.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/hppa/reloc/reloc.exp,v
retrieving revision 1.5
diff -u -3 -p -r1.5 reloc.exp
--- reloc.exp   2000/09/28 10:16:33     1.5
+++ reloc.exp   2002/02/03 23:52:47
@@ -296,18 +296,37 @@ proc do_local_label_as_operand_test {} {
     if [gas_test_old "labelopbug.s" "" "Local label as operand (part 1)"] {
        objdump_start_no_subdir "a.out" "-r"
 
-       # Check to make sure we handle difference of local lables as an operand
-       # to a non-branching instruction correctly.
-       while 1 {
-           expect {
-               -re "^0+2c\[^\n\]*0x0+24\[^\n\]*\n" 
-                   { set x [expr $x+1] }
-               -re "^0+30\[^\n\]*0x0+24\[^\n\]*\n" 
-                   { set x [expr $x+1] }
-               -re "\[^\n\]*\n"                { }
-               timeout                         { perror "timeout\n"; break }
-               eof                             { break }
-            }
+       # Check to make sure we handle difference of local labels as an operand
+       # to a non-branching instruction correctly.  On hppa elf targets, the
+       # R_PARISC_DIR21 and R_PARISC_DIR14R relocations are done with LR and
+       # RR selectors, respectively.  As a result, we can't reduce these to
+       # section offsets without risking incorrect rounding.  So, we just
+       # check to see if the label hasn't been reduced.
+       if {[istarget hppa*64*-*-*]
+           || [istarget hppa*-*-*elf*] || [istarget hppa*-*-linux*]} then {
+           while 1 {
+               expect {
+                   -re "^0+2c\[^\n\]*L.0002\[^\n\]*\n" 
+                       { set x [expr $x+1] }
+                   -re "^0+30\[^\n\]*L.0002\[^\n\]*\n" 
+                       { set x [expr $x+1] }
+                   -re "\[^\n\]*\n"            { }
+                   timeout                     { perror "timeout\n"; break }
+                   eof                         { break }
+               }
+           }
+       } else {
+           while 1 {
+               expect {
+                   -re "^0+2c\[^\n\]*0x0+24\[^\n\]*\n" 
+                       { set x [expr $x+1] }
+                   -re "^0+30\[^\n\]*0x0+24\[^\n\]*\n" 
+                       { set x [expr $x+1] }
+                   -re "\[^\n\]*\n"            { }
+                   timeout                     { perror "timeout\n"; break }
+                   eof                         { break }
+               }
+           }
        }
 
        # This was intended to do any cleanup necessary.  It kinda looks like it
Index: ld/testsuite/ld-selective/selective.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-selective/selective.exp,v
retrieving revision 1.21
diff -u -3 -p -r1.21 selective.exp
--- selective.exp       2002/01/14 15:46:50     1.21
+++ selective.exp       2002/02/03 23:52:48
@@ -105,7 +105,13 @@ foreach testitem $seltests {
     if {[istarget arm-*-*] || [istarget xscale-*-*]} {
        set objfile "$objfile -L ../gcc -lgcc"
     }
-    
+ 
+    # HPPA linux targets need libgcc.a for millicode routines ($$dyncall).
+    if [istarget hppa*-*-linux*] {
+       catch "exec $CC -print-libgcc-file-name" libgcc
+       set objfile "$objfile $libgcc"
+    }
+
     # m6811/m6812 code has references to soft registers.
     if {[istarget m6811-*-*] || [istarget m6812-*-*]} {
        set objfile "$objfile --defsym _.frame=0 --defsym _.d1=0"



reply via email to

[Prev in Thread] Current Thread [Next in Thread]