This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

elf32-hppa shared lib support part 7


Munge in vtable support for tc-hppa.c, inform elf back-end about
millicode, and make $PIC_pcrel$0 work.

gas/ChangeLog
	* config/tc-hppa.c: (md_apply_fix): Handle vtable relocs.
	(hppa_force_relocation): Handle vtable relocs.
	(pa_vtable_entry): New.
	(pa_vtable_inherit): New.
	(md_pseudo_table): Add entries for vtable pseudos.
	(hppa_fix_adjustable): Reject reduction of R_PARISC_GNU_VTINHERIT
	and R_PARISC_GNU_VTENTRY relocs.  Reject reduction of relocs
	against weak syms.
	(tc_gen_reloc): Remove ELF_ARG_RELOC_INSN code.
	(pa_type_args): Don't call symbol_get_bfdsym multiple times.
	Set STT_PARISC_MILLICODE for OBJ_ELF when encountering a
	millicode import.
	* config/obj-elf.c (obj_elf_type): Allow md_elf_symbol_type to
	specify a symbol type.

	* config/tc-hppa.h: Reorganize file a little, grouping OBJ_ELF
	dependent things together.
	(md_elf_symbol_type): Define.

	* config/tc-hppa.c (fix_new_hppa): Elide "$PIC_pcrel$0" pseudo
	symbol.
	* config/tc-hppa.h (tc_frob_symbol): Elide "$PIC_pcrel$0" here too.

	* config/obj-elf.h (obj_elf_vtable_inherit): Declare.
	(obj_elf_vtable_entry): Declare.

	* config/obj-elf.c (obj_elf_vtable_inherit): Return struct fix *
	and export function.
	(obj_elf_vtable_entry): Similarly.
	(elf_pseudo_table): Fix the damage with a cast.

Alan Modra
-- 
Linuxcare.  Support for the Revolution.

diff -uprN -x*~ -xCVS -xTAGS -x.#* binutils-current/gas/config/obj-elf.c parisc/gas/config/obj-elf.c
--- binutils-current/gas/config/obj-elf.c	Mon Jul 31 11:36:23 2000
+++ parisc/gas/config/obj-elf.c	Sun Aug 27 14:07:17 2000
@@ -75,8 +75,6 @@ static void obj_elf_weak PARAMS ((int));
 static void obj_elf_local PARAMS ((int));
 static void obj_elf_visibility PARAMS ((int));
 static void obj_elf_symver PARAMS ((int));
-static void obj_elf_vtable_inherit PARAMS ((int));
-static void obj_elf_vtable_entry PARAMS ((int));
 static void obj_elf_subsection PARAMS ((int));
 static void obj_elf_popsection PARAMS ((int));
 
@@ -113,8 +111,8 @@ static const pseudo_typeS elf_pseudo_tab
   {"subsection", obj_elf_subsection, 0},
 
   /* These are GNU extensions to aid in garbage collecting C++ vtables.  */
-  {"vtable_inherit", obj_elf_vtable_inherit, 0},
-  {"vtable_entry", obj_elf_vtable_entry, 0},
+  {"vtable_inherit", (void (*) PARAMS ((int))) &obj_elf_vtable_inherit, 0},
+  {"vtable_entry", (void (*) PARAMS ((int))) &obj_elf_vtable_entry, 0},
 
   /* These are used for dwarf. */
   {"2byte", cons, 2},
@@ -1156,7 +1154,7 @@ obj_elf_symver (ignore)
    to the linker the hierarchy in which a particular table resides.  The
    syntax is ".vtable_inherit CHILDNAME, PARENTNAME".  */
 
-static void
+struct fix *
 obj_elf_vtable_inherit (ignore)
      int ignore ATTRIBUTE_UNUSED;
 {
@@ -1189,7 +1187,7 @@ obj_elf_vtable_inherit (ignore)
     {
       as_bad ("expected comma after name in .vtable_inherit");
       ignore_rest_of_line ();
-      return;
+      return NULL;
     }
 
   ++input_line_pointer;
@@ -1216,19 +1214,19 @@ obj_elf_vtable_inherit (ignore)
   demand_empty_rest_of_line ();
 
   if (bad)
-    return;
+    return NULL;
 
   assert (symbol_get_value_expression (csym)->X_op == O_constant);
-  fix_new (symbol_get_frag (csym),
-	   symbol_get_value_expression (csym)->X_add_number, 0, psym, 0, 0,
-	   BFD_RELOC_VTABLE_INHERIT);
+  return fix_new (symbol_get_frag (csym),
+		  symbol_get_value_expression (csym)->X_add_number,
+		  0, psym, 0, 0, BFD_RELOC_VTABLE_INHERIT);
 }
 
 /* This handles the .vtable_entry pseudo-op, which is used to indicate
    to the linker that a vtable slot was used.  The syntax is
    ".vtable_entry tablename, offset".  */
 
-static void
+struct fix *
 obj_elf_vtable_entry (ignore)
      int ignore ATTRIBUTE_UNUSED;
 {
@@ -1250,7 +1248,7 @@ obj_elf_vtable_entry (ignore)
     {
       as_bad ("expected comma after name in .vtable_entry");
       ignore_rest_of_line ();
-      return;
+      return NULL;
     }
 
   ++input_line_pointer;
@@ -1259,10 +1257,10 @@ obj_elf_vtable_entry (ignore)
 
   offset = get_absolute_expression ();
 
-  fix_new (frag_now, frag_now_fix (), 0, sym, offset, 0,
-	   BFD_RELOC_VTABLE_ENTRY);
-
   demand_empty_rest_of_line ();
+
+  return fix_new (frag_now, frag_now_fix (), 0, sym, offset, 0,
+		  BFD_RELOC_VTABLE_ENTRY);
 }
 
 void
@@ -1424,10 +1422,12 @@ obj_elf_type (ignore)
   int type;
   const char *typename;
   symbolS *sym;
+  elf_symbol_type *elfsym;
 
   name = input_line_pointer;
   c = get_symbol_end ();
   sym = symbol_find_or_make (name);
+  elfsym = (elf_symbol_type *) symbol_get_bfdsym (sym);
   *input_line_pointer = c;
 
   SKIP_WHITESPACE ();
@@ -1451,6 +1451,10 @@ obj_elf_type (ignore)
   else if (strcmp (typename, "object") == 0
 	   || strcmp (typename, "STT_OBJECT") == 0)
     type = BSF_OBJECT;
+#ifdef md_elf_symbol_type
+  else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
+    ;
+#endif
   else
     as_bad (_("ignoring unrecognized symbol type \"%s\""), typename);
 
@@ -1459,7 +1463,7 @@ obj_elf_type (ignore)
   if (*input_line_pointer == '"')
     ++input_line_pointer;
 
-  symbol_get_bfdsym (sym)->flags |= type;
+  elfsym->symbol.flags |= type;
 
   demand_empty_rest_of_line ();
 }
diff -uprN -x*~ -xCVS -xTAGS -x.#* binutils-current/gas/config/obj-elf.h parisc/gas/config/obj-elf.h
--- binutils-current/gas/config/obj-elf.h	Tue May 23 08:50:30 2000
+++ parisc/gas/config/obj-elf.h	Thu Jun  8 14:12:50 2000
@@ -151,6 +151,8 @@ extern void obj_elf_version PARAMS ((int
 extern void obj_elf_common PARAMS ((int));
 extern void obj_elf_data PARAMS ((int));
 extern void obj_elf_text PARAMS ((int));
+extern struct fix *obj_elf_vtable_inherit PARAMS ((int));
+extern struct fix *obj_elf_vtable_entry PARAMS ((int));
 
 /* BFD wants to write the udata field, which is a no-no for the
    globally defined sections.  */
diff -uprN -x*~ -xCVS -xTAGS -x.#* binutils-current/gas/config/tc-hppa.c parisc/gas/config/tc-hppa.c
--- binutils-current/gas/config/tc-hppa.c	Thu Jul 27 11:44:25 2000
+++ parisc/gas/config/tc-hppa.c	Mon Sep  4 23:04:48 2000
@@ -579,6 +562,8 @@ static int pa_parse_ftest_gfx_completer 
 #ifdef OBJ_ELF
 static void hppa_elf_mark_end_of_function PARAMS ((void));
 static void pa_build_unwind_subspace PARAMS ((struct call_info *));
+static void pa_vtable_entry PARAMS ((int));
+static void pa_vtable_inherit  PARAMS ((int));
 #endif
 
 /* File and gloally scoped variable declarations.  */
@@ -695,6 +680,10 @@ const pseudo_typeS md_pseudo_table[] =
   {"text", pa_text, 0},
 #endif
   {"version", pa_version, 0},
+#ifdef OBJ_ELF
+  {"vtable_entry", pa_vtable_entry, 0},
+  {"vtable_inherit", pa_vtable_inherit, 0},
+#endif
   {"word", pa_cons, 4},
   {NULL, 0, 0}
 };
@@ -1308,9 +1306,10 @@ fix_new_hppa (frag, where, size, add_sym
 
   /* foo-$global$ is used to access non-automatic storage.  $global$
      is really just a marker and has served its purpose, so eliminate
-     it now so as not to confuse write.c.  */
+     it now so as not to confuse write.c.  Ditto for $PIC_pcrel$0.  */
   if (new_fix->fx_subsy
-      && !strcmp (S_GET_NAME (new_fix->fx_subsy), "$global$"))
+      && (strcmp (S_GET_NAME (new_fix->fx_subsy), "$global$") == 0
+	  || strcmp (S_GET_NAME (new_fix->fx_subsy), "$PIC_pcrel$0") == 0))
     new_fix->fx_subsy = NULL;
 }
 
@@ -4099,9 +4053,8 @@ tc_gen_reloc (section, fixp)
 	case R_PARISC_PLABEL14R:
 	  /* For plabel relocations, the addend of the
 	     relocation should be either 0 (no static link) or 2
-	     (static link required).
-
-	     FIXME: We always assume no static link!
+	     (static link required).  This adjustment is done in
+	     bfd/elf32-hppa.c:elf32_hppa_relocate_section.
 
 	     We also slam a zero addend into the DLT relative relocs;
 	     it doesn't make a lot of sense to use any addend since
@@ -4115,52 +4068,10 @@ tc_gen_reloc (section, fixp)
 	case R_PARISC_PCREL17C:
 	case R_PARISC_DIR17R:
 	case R_PARISC_DIR17F:
-	  {
-	    char *buf = fixp->fx_where + fixp->fx_frag->fr_literal;
-	    int insn = bfd_get_32 (stdoutput, buf);
-
-#ifdef ELF_ARG_RELOC_INSN
-	    /* Store the arg reloc in the instruction.  */
-	    insn = ((insn & ~ 0x1ff8)
-		    | ((hppa_fixp->fx_arg_reloc << 3) & 0x1ff8));
-	    bfd_put_32 (stdoutput, insn, buf);
-	    reloc->addend = fixp->fx_offset;
-#else
-	    /* The high 22 bits of the constant are stored in the
-	       reloc.  The remaining 10 bits can be retrieved from the
-	       instruction.  */
-	    insn = (insn & ~ 0x7f8) | ((fixp->fx_offset & 0x3fc) << 1);
-	    bfd_put_32 (stdoutput, insn, buf);
-	    reloc->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc,
-					   fixp->fx_offset >> 10);
-#endif
-	  }
-	  break;
-
 	case R_PARISC_PCREL21L:
 	case R_PARISC_DIR21L:
-	  {
-	    char *buf = fixp->fx_where + fixp->fx_frag->fr_literal;
-	    int insn = bfd_get_32 (stdoutput, buf);
-
-#ifdef ELF_ARG_RELOC_INSN
-	    /* Store the arg reloc in the instruction.  */
-	    insn = ((insn & ~ 0xff9)
-		    | ((hppa_fixp->fx_arg_reloc >> 9) & 1)
-		    | ((hppa_fixp->fx_arg_reloc << 3) & 0xff8));
-	    bfd_put_32 (stdoutput, insn, buf);
-	    reloc->addend = fixp->fx_offset;
-#else
-	    /* In this case, the instruction stores the high bits, so
-	       the reloc stores the low 22 bits.  */
-	    insn = ((insn & ~ 0xff9)
-		    | ((fixp->fx_offset >> 31) & 1)
-		    | ((fixp->fx_offset >> 19) & 0xff8));
-	    bfd_put_32 (stdoutput, insn, buf);
-	    reloc->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc,
-					   fixp->fx_offset);
-#endif
-	  }
+	  reloc->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc,
+					 fixp->fx_offset);
 	  break;
 #endif
 
@@ -4454,6 +4365,11 @@ md_apply_fix (fixP, valp)
       return 1;
     }
 #endif
+#ifdef OBJ_ELF
+  if (fixP->fx_r_type == (int) R_PARISC_GNU_VTENTRY
+      || fixP->fx_r_type == (int) R_PARISC_GNU_VTINHERIT)
+    return 1;
+#endif
 
   insn = bfd_get_32 (stdoutput, (unsigned char *) buf);
   /* There should have been an HPPA specific fixup associated
@@ -6643,12 +6589,13 @@ pa_type_args (symbolP, is_export)
   char *name, c, *p;
   unsigned int temp, arg_reloc;
   pa_symbol_type type = SYMBOL_TYPE_UNKNOWN;
+  asymbol *bfdsym = symbol_get_bfdsym (symbolP);
 
   if (strncasecmp (input_line_pointer, "absolute", 8) == 0)
 
     {
       input_line_pointer += 8;
-      symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION;
+      bfdsym->flags &= ~BSF_FUNCTION;
       S_SET_SEGMENT (symbolP, bfd_abs_section_ptr);
       type = SYMBOL_TYPE_ABSOLUTE;
     }
@@ -6667,50 +6614,58 @@ pa_type_args (symbolP, is_export)
 	    as_tsktsk (_("Using ENTRY rather than CODE in export directive for %s"),
 		       S_GET_NAME (symbolP));
 
-	  symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
+	  bfdsym->flags |= BSF_FUNCTION;
 	  type = SYMBOL_TYPE_ENTRY;
 	}
       else
 	{
-	  symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION;
+	  bfdsym->flags &= ~BSF_FUNCTION;
 	  type = SYMBOL_TYPE_CODE;
 	}
     }
   else if (strncasecmp (input_line_pointer, "data", 4) == 0)
     {
       input_line_pointer += 4;
-      symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION;
-      symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
+      bfdsym->flags &= ~BSF_FUNCTION;
+      bfdsym->flags |= BSF_OBJECT;
       type = SYMBOL_TYPE_DATA;
     }
   else if ((strncasecmp (input_line_pointer, "entry", 5) == 0))
     {
       input_line_pointer += 5;
-      symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
+      bfdsym->flags |= BSF_FUNCTION;
       type = SYMBOL_TYPE_ENTRY;
     }
   else if (strncasecmp (input_line_pointer, "millicode", 9) == 0)
     {
       input_line_pointer += 9;
-      symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
+      bfdsym->flags |= BSF_FUNCTION;
+#ifdef OBJ_ELF
+      {
+	elf_symbol_type *elfsym = (elf_symbol_type *) bfdsym;
+	elfsym->internal_elf_sym.st_info =
+	  ELF_ST_INFO (ELF_ST_BIND (elfsym->internal_elf_sym.st_info),
+		       STT_PARISC_MILLI);
+      }
+#endif
       type = SYMBOL_TYPE_MILLICODE;
     }
   else if (strncasecmp (input_line_pointer, "plabel", 6) == 0)
     {
       input_line_pointer += 6;
-      symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION;
+      bfdsym->flags &= ~BSF_FUNCTION;
       type = SYMBOL_TYPE_PLABEL;
     }
   else if (strncasecmp (input_line_pointer, "pri_prog", 8) == 0)
     {
       input_line_pointer += 8;
-      symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
+      bfdsym->flags |= BSF_FUNCTION;
       type = SYMBOL_TYPE_PRI_PROG;
     }
   else if (strncasecmp (input_line_pointer, "sec_prog", 8) == 0)
     {
       input_line_pointer += 8;
-      symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
+      bfdsym->flags |= BSF_FUNCTION;
       type = SYMBOL_TYPE_SEC_PROG;
     }
 
@@ -6718,7 +6673,7 @@ pa_type_args (symbolP, is_export)
      than BFD understands.  This is how we get this information
      to the SOM BFD backend.  */
 #ifdef obj_set_symbol_type
-  obj_set_symbol_type (symbol_get_bfdsym (symbolP), (int) type);
+  obj_set_symbol_type (bfdsym, (int) type);
 #endif
 
   /* Now that the type of the exported symbol has been handled,
@@ -6766,8 +6721,7 @@ pa_type_args (symbolP, is_export)
 	  input_line_pointer++;
 	  temp = atoi (input_line_pointer);
 #ifdef OBJ_SOM
-	  ((obj_symbol_type *) symbol_get_bfdsym (symbolP))
-	    ->tc_data.ap.hppa_priv_level = temp;
+	  ((obj_symbol_type *) bfdsym)->tc_data.ap.hppa_priv_level = temp;
 #endif
 	  c = get_symbol_end ();
 	  *input_line_pointer = c;
@@ -8368,6 +8324,12 @@ hppa_fix_adjustable (fixp)
     return 0;
 #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;
+#endif
+
   /* Reject reductions of symbols in sym1-sym2 expressions when
      the fixup will occur in a CODE subspace.
 
@@ -8428,7 +8390,8 @@ hppa_fix_adjustable (fixp)
       || hppa_fix->fx_r_field == e_lpsel)
     return 0;
 
-  if (fixp->fx_addsy && S_IS_EXTERNAL (fixp->fx_addsy))
+  if (fixp->fx_addsy && (S_IS_EXTERNAL (fixp->fx_addsy)
+			 || S_IS_WEAK (fixp->fx_addsy)))
     return 0;
 
   /* Reject absolute calls (jumps).  */
@@ -8465,6 +8428,11 @@ hppa_force_relocation (fixp)
 	  && (hppa_fixp->segment->flags & SEC_CODE) != 0))
     return 1;
 #endif
+#ifdef OBJ_ELF
+  if (fixp->fx_r_type == (int) R_PARISC_GNU_VTINHERIT
+      || fixp->fx_r_type == (int) R_PARISC_GNU_VTENTRY)
+    return 1;
+#endif
 
   /* It is necessary to force PC-relative calls/jumps to have a relocation
      entry if they're going to need either a argument relocation or long
@@ -8580,5 +8548,49 @@ pa_end_of_source ()
 {
   if (debug_type == DEBUG_DWARF2)
     dwarf2_finish ();
+}
+
+static void
+pa_vtable_entry (ignore)
+     int ignore ATTRIBUTE_UNUSED;
+{
+  struct fix *new_fix;
+
+  new_fix = obj_elf_vtable_entry (0);
+
+  if (new_fix)
+    {
+      struct hppa_fix_struct *hppa_fix = (struct hppa_fix_struct *)
+	obstack_alloc (&notes, sizeof (struct hppa_fix_struct));
+      hppa_fix->fx_r_type = R_HPPA;
+      hppa_fix->fx_r_field = e_fsel;
+      hppa_fix->fx_r_format = 32;
+      hppa_fix->fx_arg_reloc = 0;
+      hppa_fix->segment = now_seg;
+      new_fix->tc_fix_data = (void *) hppa_fix;
+      new_fix->fx_r_type = (int) R_PARISC_GNU_VTENTRY;
+    }
+}
+
+static void
+pa_vtable_inherit (ignore)
+     int ignore ATTRIBUTE_UNUSED;
+{
+  struct fix *new_fix;
+
+  new_fix = obj_elf_vtable_inherit (0);
+
+  if (new_fix)
+    {
+      struct hppa_fix_struct *hppa_fix = (struct hppa_fix_struct *)
+	obstack_alloc (&notes, sizeof (struct hppa_fix_struct));
+      hppa_fix->fx_r_type = R_HPPA;
+      hppa_fix->fx_r_field = e_fsel;
+      hppa_fix->fx_r_format = 32;
+      hppa_fix->fx_arg_reloc = 0;
+      hppa_fix->segment = now_seg;
+      new_fix->tc_fix_data = (void *) hppa_fix;
+      new_fix->fx_r_type = (int) R_PARISC_GNU_VTINHERIT;
+    }
 }
 #endif
diff -uprN -x*~ -xCVS -xTAGS -x.#* binutils-current/gas/config/tc-hppa.h parisc/gas/config/tc-hppa.h
--- binutils-current/gas/config/tc-hppa.h	Fri Jul 28 14:09:32 2000
+++ parisc/gas/config/tc-hppa.h	Sun Aug 27 14:07:14 2000
@@ -99,14 +99,6 @@ extern void pa_check_eof PARAMS ((void))
 #define RELOC_EXPANSION_POSSIBLE
 #define MAX_RELOC_EXPANSION 6
 
-/* FIXME.  More things which are both HPPA and ELF specific.  There is 
-   nowhere to put such things.  */
-#ifdef OBJ_ELF
-#define elf_tc_final_processing	elf_hppa_final_processing
-void elf_hppa_final_processing PARAMS ((void));
-void pa_end_of_source PARAMS ((void));
-#endif
-
 /* The PA needs to parse field selectors in .byte, etc.  */
 
 #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \
@@ -154,20 +146,35 @@ int hppa_fix_adjustable PARAMS((struct f
 #endif
 
 #ifdef OBJ_ELF
+/* Handle .type psuedo.  Given a type string of `millicode', set the
+   internal elf symbol type to STT_PARISC_MILLI, and return
+   BSF_FUNCTION for the BFD symbol type.  */
+#define md_elf_symbol_type(name, sym, elf)				\
+  ((strcmp ((name), "millicode") == 0					\
+    || strcmp ((name), "STT_PARISC_MILLI") == 0)			\
+   ? (((elf)->internal_elf_sym.st_info = ELF_ST_INFO			\
+       (ELF_ST_BIND ((elf)->internal_elf_sym.st_info), STT_PARISC_MILLI)\
+       ), BSF_FUNCTION)							\
+   : -1)
+
 #define tc_frob_symbol(sym,punt) \
   { \
     if ((S_GET_SEGMENT (sym) == &bfd_und_section && ! symbol_used_p (sym)) \
 	|| (S_GET_SEGMENT (sym) == &bfd_abs_section \
 	    && ! S_IS_EXTERNAL (sym)) \
-	|| strcmp (S_GET_NAME (sym), "$global$") == 0) \
+	|| strcmp (S_GET_NAME (sym), "$global$") == 0 \
+	|| strcmp (S_GET_NAME (sym), "$PIC_pcrel$0") == 0) \
       punt = 1; \
   }
-#endif
 
-#define md_operand(x)
-#ifdef OBJ_ELF
+#define elf_tc_final_processing	elf_hppa_final_processing
+void elf_hppa_final_processing PARAMS ((void));
+
 #define md_end() pa_end_of_source ()
-#endif
+void pa_end_of_source PARAMS ((void));
+#endif /* OBJ_ELF */
+
+#define md_operand(x)
 
 #define TC_FIX_TYPE PTR
 #define TC_INIT_FIX_DATA(FIXP) ((FIXP)->tc_fix_data = NULL)



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]