From 904a31bffcb3c6d41f9f0c1753018396d167631b Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 5 Sep 2000 03:23:05 +0000 Subject: [PATCH] Munge in vtable support for tc-hppa.c, inform elf back-end about millicode, and make $PIC_pcrel$0 work. --- gas/ChangeLog | 33 +++++++++++ gas/config/obj-elf.c | 36 ++++++------ gas/config/obj-elf.h | 2 + gas/config/tc-hppa.c | 159 +++++++++++++++++++++++++++++++-------------------- gas/config/tc-hppa.h | 33 ++++++----- 5 files changed, 171 insertions(+), 92 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index c4b43e6..bf73a1d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,36 @@ +2000-09-05 Alan Modra + + * 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. + 2000-09-03 Richard Henderson * config/tc-ia64.c (emit_one_bundle): Stop collecting insns diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 378df9a..453a395 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -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_table[] = {"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 --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h index 7437765..77fec78 100644 --- a/gas/config/obj-elf.h +++ b/gas/config/obj-elf.h @@ -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 --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c index 7e59b42..c9d7cf0 100644 --- a/gas/config/tc-hppa.c +++ b/gas/config/tc-hppa.c @@ -579,6 +579,8 @@ static int pa_parse_ftest_gfx_completer PARAMS ((char **)); #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 +697,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 +1314,10 @@ fix_new_hppa (frag, where, size, add_symbol, offset, exp, pcrel, /* 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 +4106,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 +4121,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 +4418,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 +6612,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 +6637,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 +6696,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 +6744,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 +8345,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 +8411,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 +8449,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 @@ -8581,4 +8570,48 @@ 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 (¬es, 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 (¬es, 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 --git a/gas/config/tc-hppa.h b/gas/config/tc-hppa.h index 1ea9daa..dcd7966 100644 --- a/gas/config/tc-hppa.h +++ b/gas/config/tc-hppa.h @@ -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 fix *)); #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) -- 2.7.4