From 5868b1fe68831aacbf3934406182a20466aeec20 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 14 Jul 1993 22:21:25 +0000 Subject: [PATCH] * Removed sy_forward and replaced it with an undefined expression as the value of a symbol. * struc-symbol.h (struct symbol): Removed sy_forward field. Added sy_resolved and sy_resolving single bit fields. * symbols.c (symbol_new): Don't initialize sy_forward field. (resolve_symbol_value): New function to adjust symbol value by fragment address, using recursion to resolve forward symbols. * symbols.h: Added prototype for new function. * read.c (pseudo_set): Set symbolP->sy_value to an undefined expression rather than setting symbolP->sy_forward. * write.c (write_object_file): Use resolve_symbol_value on symbols, keeping the common case (the old behaviour) inline. * config/obj-aout.c (obj_aout_frob_symbol): Removed sy_forward handling (subsumed by write.c change). * config/obj-coff.c, config/obj-coffbfd.c (obj_coff_val): Set sy_value rather than sy_forward. * config/obj-coffbfd.c (obj_coff_endef, yank_symbols): Check expression segment rather than sy_forward. (yank_symbols): Use resolve_symbol_value. (crawl_symbols): Removed extra pass over symbols. * config/obj-aout.c, config/obj-bout.c, config/obj-coff.c, config/obj-vms.c (obj_crawl_symbol_chain): Removed extra pass over symbols which handled sy_forward; use resolve_symbol_value instead. * config/obj-coff.h, config/obj-coffbfd.h (obj_frob_forward_symbol): Define. * config/obj-elf.c (obj_elf_stab_generic): Check expression segment rather than sy_forward. * config/obj-vms.c (VMS_Check_For_Main): Don't initialize sy_forward; do initialize sy_resolved and sy_resolving. * config/tc-hppa.h (STAB_FIXUP): Use sy_value, not sy_forward. --- gas/ChangeLog | 32 +++ gas/config/obj-aout.c | 26 +-- gas/config/obj-bout.c | 15 +- gas/config/obj-coff.c | 42 +--- gas/config/obj-coffbfd.c | 31 ++- gas/config/obj-coffbfd.h | 6 + gas/config/obj-elf.c | 2 +- gas/config/obj-vms.c | 18 +- gas/config/tc-hppa.h | 519 +++++++++++++++++++++++++++++++++++++++++++++++ gas/read.c | 10 +- gas/symbols.c | 50 ++++- gas/write.c | 18 +- 12 files changed, 656 insertions(+), 113 deletions(-) create mode 100644 gas/config/tc-hppa.h diff --git a/gas/ChangeLog b/gas/ChangeLog index 6027904..87b2827 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,37 @@ Wed Jul 14 15:09:32 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + * Removed sy_forward and replaced it with an undefined expression + as the value of a symbol. + * struc-symbol.h (struct symbol): Removed sy_forward field. Added + sy_resolved and sy_resolving single bit fields. + * symbols.c (symbol_new): Don't initialize sy_forward field. + (resolve_symbol_value): New function to adjust symbol value by + fragment address, using recursion to resolve forward symbols. + * symbols.h: Added prototype for new function. + * read.c (pseudo_set): Set symbolP->sy_value to an undefined + expression rather than setting symbolP->sy_forward. + * write.c (write_object_file): Use resolve_symbol_value on + symbols, keeping the common case (the old behaviour) inline. + * config/obj-aout.c (obj_aout_frob_symbol): Removed sy_forward + handling (subsumed by write.c change). + * config/obj-coff.c, config/obj-coffbfd.c (obj_coff_val): Set + sy_value rather than sy_forward. + * config/obj-coffbfd.c (obj_coff_endef, yank_symbols): Check + expression segment rather than sy_forward. + (yank_symbols): Use resolve_symbol_value. + (crawl_symbols): Removed extra pass over symbols. + * config/obj-aout.c, config/obj-bout.c, config/obj-coff.c, + config/obj-vms.c (obj_crawl_symbol_chain): Removed extra pass over + symbols which handled sy_forward; use resolve_symbol_value + instead. + * config/obj-coff.h, config/obj-coffbfd.h (obj_frob_forward_symbol): + Define. + * config/obj-elf.c (obj_elf_stab_generic): Check expression + segment rather than sy_forward. + * config/obj-vms.c (VMS_Check_For_Main): Don't initialize + sy_forward; do initialize sy_resolved and sy_resolving. + * config/tc-hppa.h (STAB_FIXUP): Use sy_value, not sy_forward. + * Changes to keep a full expression as the value of a symbol, not just a longword: * struc-symbol.h: New field sy_value. diff --git a/gas/config/obj-aout.c b/gas/config/obj-aout.c index c074df2..38fead5 100644 --- a/gas/config/obj-aout.c +++ b/gas/config/obj-aout.c @@ -110,17 +110,6 @@ obj_aout_frob_symbol (sym, punt) asection *sec; int desc, type, other; - /* Is this part format-dependent? */ - if (sym->sy_forward) - { - S_SET_VALUE (sym, - S_GET_VALUE (sym) - + S_GET_VALUE (sym->sy_forward) - + sym->sy_forward->sy_frag->fr_address - ); - sym->sy_forward = 0; - } - flags = sym->bsym->flags; desc = S_GET_DESC (sym); type = S_GET_TYPE (sym); @@ -450,19 +439,6 @@ obj_crawl_symbol_chain (headers) symbolS **symbolPP; int symbol_number = 0; - /* JF deal with forward references first... */ - for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - { - if (symbolP->sy_forward) - { - S_SET_VALUE (symbolP, S_GET_VALUE (symbolP) - + S_GET_VALUE (symbolP->sy_forward) - + symbolP->sy_forward->sy_frag->fr_address); - - symbolP->sy_forward = 0; - } /* if it has a forward reference */ - } /* walk the symbol chain */ - tc_crawl_symbol_chain (headers); symbolPP = &symbol_rootP; /*->last symbol chain link. */ @@ -473,7 +449,7 @@ obj_crawl_symbol_chain (headers) S_SET_SEGMENT (symbolP, SEG_TEXT); } /* if pusing data into text */ - S_SET_VALUE (symbolP, S_GET_VALUE (symbolP) + symbolP->sy_frag->fr_address); + resolve_symbol_value (symbolP); /* OK, here is how we decide which symbols go out into the brave new symtab. Symbols that do are: diff --git a/gas/config/obj-bout.c b/gas/config/obj-bout.c index 3ef289d..d467715 100644 --- a/gas/config/obj-bout.c +++ b/gas/config/obj-bout.c @@ -433,19 +433,6 @@ obj_crawl_symbol_chain (headers) symbolS *symbolP; int symbol_number = 0; - /* JF deal with forward references first... */ - for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - { - if (symbolP->sy_forward) - { - S_SET_VALUE (symbolP, S_GET_VALUE (symbolP) - + S_GET_VALUE (symbolP->sy_forward) - + symbolP->sy_forward->sy_frag->fr_address); - - symbolP->sy_forward = 0; - } /* if it has a forward reference */ - } /* walk the symbol chain */ - tc_crawl_symbol_chain (headers); symbolPP = &symbol_rootP; /*->last symbol chain link. */ @@ -456,7 +443,7 @@ obj_crawl_symbol_chain (headers) S_SET_SEGMENT (symbolP, SEG_TEXT); } /* if pusing data into text */ - S_SET_VALUE (symbolP, S_GET_VALUE (symbolP) + symbolP->sy_frag->fr_address); + resolve_symbol_value (symbolP); /* OK, here is how we decide which symbols go out into the brave new symtab. Symbols that do are: diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c index 3bf0e75..e0eca7a 100644 --- a/gas/config/obj-coff.c +++ b/gas/config/obj-coff.c @@ -1620,11 +1620,15 @@ obj_coff_val () } else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name)) { - def_symbol_in_progress->sy_forward = symbol_find_or_make (symbol_name); - - /* If the segment is undefined when the forward - reference is solved, then copy the segment id - from the forward symbol. */ + def_symbol_in_progress->sy_value.X_add_symbol = + symbol_find_or_make (symbol_name); + def_symbol_in_progress->sy_value.X_subtract_symbol = NULL; + def_symbol_in_progress->sy_value.X_add_number = 0; + def_symbol_in_progress->sy_value.X_seg = undefined_section; + + /* If the segment is undefined when the forward reference is + resolved, then copy the segment id from the forward + symbol. */ SF_SET_GET_SEGMENT (def_symbol_in_progress); } /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */ @@ -1720,32 +1724,6 @@ obj_crawl_symbol_chain (headers) /* Initialize the stack used to keep track of the matching .bb .be */ stack *block_stack = stack_init (512, sizeof (symbolS *)); - /* JF deal with forward references first... */ - for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - { - - if (symbolP->sy_forward) - { - S_SET_VALUE (symbolP, (S_GET_VALUE (symbolP) - + S_GET_VALUE (symbolP->sy_forward) - + symbolP->sy_forward->sy_frag->fr_address)); - - if ( -#ifndef TE_I386AIX - SF_GET_GET_SEGMENT (symbolP) -#else - SF_GET_GET_SEGMENT (symbolP) - && S_GET_SEGMENT (symbolP) == SEG_UNKNOWN -#endif /* TE_I386AIX */ - ) - { - S_SET_SEGMENT (symbolP, S_GET_SEGMENT (symbolP->sy_forward)); - } /* forward segment also */ - - symbolP->sy_forward = 0; - } /* if it has a forward reference */ - } /* walk the symbol chain */ - tc_crawl_symbol_chain (headers); /* The symbol list should be ordered according to the following sequence @@ -1864,7 +1842,7 @@ obj_crawl_symbol_chain (headers) S_SET_SEGMENT (symbolP, SEG_TEXT); } /* push data into text */ - S_SET_VALUE (symbolP, S_GET_VALUE (symbolP) + symbolP->sy_frag->fr_address); + resolve_symbol_value (symbolP); if (!S_IS_DEFINED (symbolP) && !SF_GET_LOCAL (symbolP)) { diff --git a/gas/config/obj-coffbfd.c b/gas/config/obj-coffbfd.c index d2884d3..d62bea7 100644 --- a/gas/config/obj-coffbfd.c +++ b/gas/config/obj-coffbfd.c @@ -990,7 +990,7 @@ DEFUN_VOID (obj_coff_endef) || (S_GET_SEGMENT (def_symbol_in_progress) == SEG_DEBUG && !SF_GET_TAG (def_symbol_in_progress)) || S_GET_SEGMENT (def_symbol_in_progress) == SEG_ABSOLUTE - || def_symbol_in_progress->sy_forward != NULL + || def_symbol_in_progress->sy_value.X_seg != absolute_section || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL || (SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP))) { @@ -1238,11 +1238,15 @@ obj_coff_val () } else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name)) { - def_symbol_in_progress->sy_forward = symbol_find_or_make (symbol_name); - - /* If the segment is undefined when the forward - reference is solved, then copy the segment id - from the forward symbol. */ + def_symbol_in_progress->sy_value.X_add_symbol = + symbol_find_or_make (symbol_name); + def_symbol_in_progress->sy_value.X_subtract_symbol = NULL; + def_symbol_in_progress->sy_value.X_add_number = 0; + def_symbol_in_progress->sy_value.X_seg = undefined_section; + + /* If the segment is undefined when the forward reference is + resolved, then copy the segment id from the forward + symbol. */ SF_SET_GET_SEGMENT (def_symbol_in_progress); /* FIXME: gcc can generate address expressions @@ -1369,7 +1373,7 @@ DEFUN_VOID (yank_symbols) /* L* and C_EFCN symbols never merge. */ if (!SF_GET_LOCAL (symbolP) && S_GET_STORAGE_CLASS (symbolP) != C_LABEL - && symbolP->sy_forward == NULL + && symbolP->sy_value.X_seg == absolute_section && (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP)) && real_symbolP != symbolP) { @@ -1396,8 +1400,7 @@ DEFUN_VOID (yank_symbols) S_SET_SEGMENT (symbolP, SEG_E0); } /* push data into text */ - S_SET_VALUE (symbolP, - S_GET_VALUE (symbolP) + symbolP->sy_frag->fr_address); + resolve_symbol_value (symbolP); if (!S_IS_DEFINED (symbolP) && !SF_GET_LOCAL (symbolP)) { @@ -1612,16 +1615,6 @@ DEFUN (crawl_symbols, (h, abfd), /* Initialize the stack used to keep track of the matching .bb .be */ block_stack = stack_init (512, sizeof (symbolS *)); - /* JF deal with forward references first... */ - for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - if (symbolP->sy_forward) - { - S_SET_VALUE (symbolP, (S_GET_VALUE (symbolP) - + S_GET_VALUE (symbolP->sy_forward) - + symbolP->sy_forward->sy_frag->fr_address)); - if (SF_GET_GET_SEGMENT (symbolP)) - S_SET_SEGMENT (symbolP, S_GET_SEGMENT (symbolP->sy_forward)); - } /* The symbol list should be ordered according to the following sequence * order : diff --git a/gas/config/obj-coffbfd.h b/gas/config/obj-coffbfd.h index 9823340..9984a72 100644 --- a/gas/config/obj-coffbfd.h +++ b/gas/config/obj-coffbfd.h @@ -518,4 +518,10 @@ extern SCNHDR text_section_header; #endif #endif +/* Forward the segment of a forwarded symbol. */ +#define obj_frob_forward_symbol(symp) \ + (SF_GET_GET_SEGMENT (symp) \ + ? (S_SET_SEGMENT (symp, S_GET_SEGMENT (symp->sy_value.X_add_symbol)), 0) \ + : 0) + /* end of obj-coffbfd.h */ diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 95ea6df..89e8a24 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -486,7 +486,7 @@ obj_elf_stab_generic (what, secname) subseg_new ((char *) saved_seg->name, subseg); if ((what == 's' || what == 'n') - && symbolP->sy_forward == NULL) + && symbolP->sy_value.X_seg == absolute_section) { /* symbol is not needed in the regular symbol table */ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); diff --git a/gas/config/obj-vms.c b/gas/config/obj-vms.c index 4e4ab80..3c29d18 100644 --- a/gas/config/obj-vms.c +++ b/gas/config/obj-vms.c @@ -546,18 +546,6 @@ obj_crawl_symbol_chain (headers) symbolS **symbolPP; int symbol_number = 0; - /* JF deal with forward references first... */ - for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - { - if (symbolP->sy_forward) - { - S_SET_VALUE (symbolP, S_GET_VALUE (symbolP) - + S_GET_VALUE (symbolP->sy_forward) - + symbolP->sy_forward->sy_frag->fr_address); - symbolP->sy_forward = 0; - } /* if it has a forward reference */ - } /* walk the symbol chain */ - { /* crawl symbol table */ register int symbol_number = 0; @@ -565,8 +553,7 @@ obj_crawl_symbol_chain (headers) symbolPP = &symbol_rootP; /* -> last symbol chain link. */ while ((symbolP = *symbolPP) != NULL) { - S_SET_VALUE (symbolP, - S_GET_VALUE (symbolP) + symbolP->sy_frag->fr_address); + resolve_symbol_value (symbolP); /* OK, here is how we decide which symbols go out into the brave new symtab. Symbols that do are: @@ -4548,7 +4535,8 @@ VMS_Check_For_Main () symbolP->sy_name_offset = 0; symbolP->sy_number = 0; symbolP->sy_frag = New_Frag; - symbolP->sy_forward = 0; + symbolP->sy_resolved = 0; + symbolP->sy_resolving = 0; /* this actually inserts at the beginning of the list */ symbol_append (symbol_rootP, symbolP, &symbol_rootP, &symbol_lastP); diff --git a/gas/config/tc-hppa.h b/gas/config/tc-hppa.h new file mode 100644 index 0000000..308863f --- /dev/null +++ b/gas/config/tc-hppa.h @@ -0,0 +1,519 @@ +/* tc-hppa.h -- Header file for the PA */ + +/* Copyright (C) 1989 Free Software Foundation, Inc. + +This file is part of GAS, the GNU Assembler. + +GAS is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 1, or (at your option) +any later version. + +GAS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GAS; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +/* + HP PA-RISC support was contributed by the Center for Software Science + at the University of Utah. + */ + +#ifndef _TC_HPPA_H +#define _TC_HPPA_H + +#ifndef TC_HPPA +#define TC_HPPA 1 +#endif + +#define TARGET_ARCH bfd_arch_hppa +#define TARGET_FORMAT "elf32-hppa" + +#define ASEC_NULL (asection *)0 + +/* We can do sym1 - sym2 as long as sym2 is $global$ */ + +#define SEG_DIFF_ALLOWED + +typedef enum FPOF + { + SGL, DBL, ILLEGAL_FMT, QUAD + } FP_Operand_Format; + +extern char *expr_end; + +extern void s_globl (), s_long (), s_short (), s_space (), cons (); +extern void stringer (); +extern unsigned int next_char_of_string (); + +extern void pa_big_cons (); +extern void pa_cons (); +extern void pa_data (); +extern void pa_desc (); +extern void pa_float_cons (); +extern void pa_fill (); +extern void pa_lcomm (); +extern void pa_lsym (); +extern void pa_stringer (); +extern void pa_text (); +extern void pa_version (); + +int pa_parse_number (); + +int pa_parse_fp_cmp_cond (); + +FP_Operand_Format pa_parse_fp_format (); + +#ifdef __STDC__ +int getExpression (char *str); +#else +int getExpression (); +#endif + +int getAbsoluteExpression (); + +int evaluateAbsolute (); + +int pa_build_arg_reloc (); + +unsigned int pa_align_arg_reloc (); + +void pa_skip (); + +int pa_parse_nullif (); + +int pa_parse_nonneg_cmpsub_cmpltr (); + +int pa_parse_neg_cmpsub_cmpltr (); + +int pa_parse_nonneg_add_cmpltr (); + +int pa_parse_neg_add_cmpltr (); + +int pa_build_arg_reloc (); + +void s_seg (), s_proc (), s_data1 (); + +void pa_block (), pa_call (), pa_call_args (), pa_callinfo (); +void pa_code (), pa_comm (), pa_copyright (), pa_end (); +void pa_enter (); +void pa_entry (), pa_equ (), pa_exit (), pa_export (); +void pa_export_args (), pa_import (), pa_label (), pa_leave (); +void pa_origin (), pa_proc (), pa_procend (), pa_space (); +void pa_spnum (), pa_subspace (), pa_version (); + +extern const pseudo_typeS md_pseudo_table[]; + +/* + PA-89 floating point registers are arranged like this: + + + +--------------+--------------+ + | 0 or 16L | 16 or 16R | + +--------------+--------------+ + | 1 or 17L | 17 or 17R | + +--------------+--------------+ + | | | + + . . . + . . . + . . . + + | | | + +--------------+--------------+ + | 14 or 30L | 30 or 30R | + +--------------+--------------+ + | 15 or 31L | 31 or 31R | + +--------------+--------------+ + + + The following is a version of pa_parse_number that + handles the L/R notation and returns the correct + value to put into the instruction register field. + The correct value to put into the instruction is + encoded in the structure 'pa_89_fp_reg_struct'. + + */ + +struct pa_89_fp_reg_struct + { + char number_part; + char L_R_select; + }; + +int need_89_opcode (); +int pa_89_parse_number (); + + +/* pa-ctrl-func.h -- Control Structures and Functions for the PA */ + +extern unsigned int assemble_3 ( /* unsigned int x; */ ); + +extern void dis_assemble_3 ( /* unsigned int x, *r; */ ); + +extern unsigned int assemble_12 ( /* unsigned int x,y; */ ); + +extern void dis_assemble_12 ( /* unsigned int as12, *x,*y */ ); + +extern unsigned long assemble_17 ( /* unsigned int x,y,z */ ); + +extern void dis_assemble_17 ( /* unsigned int as17, *x,*y,*z */ ); + +extern unsigned long assemble_21 ( /* unsigned int x; */ ); + +extern void dis_assemble_21 ( /* unsigned int as21,*x; */ ); + +extern void sign_unext ( /* unsigned int x,len; unsigned int *result */ ); + +extern void low_sign_unext ( /* unsigned int x,len; unsigned int *result */ ); + +struct call_desc + { + unsigned int arg_reloc; + unsigned int arg_count; + }; + +typedef struct call_desc call_descS; + +extern call_descS last_call_desc; + +/* GDB debug support */ + +#if defined(OBJ_SOME) +#define GDB_DEBUG_SPACE_NAME "$GDB_DEBUG$" +#define GDB_STRINGS_SUBSPACE_NAME "$GDB_STRINGS$" +#define GDB_SYMBOLS_SUBSPACE_NAME "$GDB_SYMBOLS$" +#else +#define GDB_DEBUG_SPACE_NAME ".stab" +#define GDB_STRINGS_SUBSPACE_NAME ".stabstr" +#define GDB_SYMBOLS_SUBSPACE_NAME ".stab" +#endif +/* pre-defined subsegments (subspaces) for the HP 9000 Series 800 */ + +#define SUBSEG_CODE 0 +#define SUBSEG_DATA 0 +#define SUBSEG_LIT 1 +#define SUBSEG_BSS 2 +#define SUBSEG_UNWIND 3 +#define SUBSEG_GDB_STRINGS 0 +#define SUBSEG_GDB_SYMBOLS 1 + +#define UNWIND_SECTION_NAME ".hppa_unwind" +/* subspace dictionary chain entry structure */ + +struct subspace_dictionary_chain + { +#if defined(OBJ_OSFROSE) | defined(OBJ_ELF) +#ifdef OBJ_OSFROSE + region_command_t *ssd_entry;/* XXX: not sure this is what we need here */ +#else + Elf_Internal_Shdr *ssd_entry; + unsigned long ssd_vm_addr; +#endif + char *ssd_name; /* used until time of writing object file */ + /* then we use ssd_entry->regc_region_name */ + unsigned char ssd_quadrant; + unsigned char ssd_sort_key; + unsigned char ssd_common; + unsigned char ssd_dup_common; + unsigned char ssd_loadable; + unsigned char ssd_code_only; +#else + subspace_dictS *ssd_entry; /* this dictionary */ +#endif + int ssd_defined; /* this subspace has been used */ + int ssd_space_number; /* space # this subspace is in */ + asection *ssd_seg; /* this subspace = this seg */ + int ssd_subseg; /* and subseg */ + int ssd_zero; + int object_file_index; /* index of this entry within + the subspace dictionary of + the object file (not used until + the object file is written */ + int ssd_last_align; /* the size of the last alignment + request for this subspace */ + symbolS *ssd_start_sym; /* a symbol whose value is the + start of this subspace */ + struct subspace_dictionary_chain *ssd_next; /* next subspace dict. entry */ + }; + +typedef struct subspace_dictionary_chain subspace_dict_chainS; + +/* space dictionary chain entry structure */ + +struct space_dictionary_chain + { +#ifdef OBJ_OSFROSE + region_command_t *sd_entry; /* XXX: not sure this is what we need here */ + char *sd_name; /* used until time of writing object file */ + /* then we use sd_entry->regc_region_name */ + unsigned int sd_loadable; + unsigned int sd_private; + unsigned int sd_spnum; + unsigned char sd_sort_key; +#else +#ifdef OBJ_ELF + Elf_Internal_Shdr *sd_entry; + char *sd_name; /* used until time of writing object file */ + /* then we use sd_entry->sh_name */ + unsigned int sd_loadable; + unsigned int sd_private; + unsigned int sd_spnum; + unsigned char sd_sort_key; +#else + space_dictS *sd_entry; /* this dictionary */ +#endif +#endif + int sd_defined; /* this space has been used */ + asection *sd_seg; /* GAS segment to which this space corresponds */ + int sd_last_subseg; /* current subsegment number we are using */ + subspace_dict_chainS *sd_subspaces; /* all subspaces in this space */ + struct space_dictionary_chain *sd_next; /* the next space dict. entry */ + }; + +typedef struct space_dictionary_chain space_dict_chainS; + +/* + Macros to maintain spaces and subspaces + */ + +#ifdef OBJ_OSFROSE +#define SPACE_DEFINED(space_chain) (space_chain)->sd_defined +#define SPACE_PRIVATE(space_chain) (space_chain)->sd_private +#define SPACE_LOADABLE(space_chain) (space_chain)->sd_loadable +#define SPACE_SPNUM(space_chain) (space_chain)->sd_spnum +#define SPACE_SORT(space_chain) (space_chain)->sd_sort_key +#define SPACE_NAME(space_chain) (space_chain)->sd_name + +#define SUBSPACE_QUADRANT(ss_chain) (ss_chain)->ssd_quadrant +#define SUBSPACE_ALIGN(ss_chain) (ss_chain)->ssd_entry->regc_addralign +#define SUBSPACE_ACCESS(ss_chain) (ss_chain)->ssd_entry->regc_initprot +#define SUBSPACE_SORT(ss_chain) (ss_chain)->ssd_sort_key +#define SUBSPACE_COMMON(ss_chain) (ss_chain)->ssd_common +#define SUBSPACE_ZERO(ss_chain) (ss_chain)->ssd_zero +#define SUBSPACE_DUP_COMM(ss_chain) (ss_chain)->ssd_dup_common +#define SUBSPACE_CODE_ONLY(ssch) ((ssch)->ssd_entry->regc_flags & REG_TEXT_T) +#define SET_SUBSPACE_CODE_ONLY(ssch,val) (ssch)->ssd_entry->regc_flags |= ((val) ? REG_TEXT_T : 0) +#define SUBSPACE_LOADABLE(ss_chain) (ss_chain)->ssd_loadable +#define SUBSPACE_SUBSPACE_START(ss_chain) (ss_chain)->ssd_entry->regc_addr.vm_addr +#define SUBSPACE_SUBSPACE_LENGTH(ss_chain) (ss_chain)->ssd_entry->regc_vm_size +#define SUBSPACE_REGION_NAME(ss_chain) (ss_chain)->ssd_entry->regc_region_name +#define SUBSPACE_NAME(ss_chain) (ss_chain)->ssd_name +#endif + +#ifdef OBJ_ELF +#define RELOC_EXPANSION_POSSIBLE +#define MAX_RELOC_EXPANSION 5 + +#define SPACE_DEFINED(space_chain) (space_chain)->sd_defined +#define SPACE_PRIVATE(space_chain) (space_chain)->sd_private +#define SPACE_LOADABLE(space_chain) (space_chain)->sd_loadable +#define SPACE_SPNUM(space_chain) (space_chain)->sd_spnum +#define SPACE_SORT(space_chain) (space_chain)->sd_sort_key +#define SPACE_NAME(space_chain) (space_chain)->sd_name + +#define SUBSPACE_QUADRANT(ss_chain) (ss_chain)->ssd_quadrant +#define SUBSPACE_ALIGN(ss_chain) (ss_chain)->ssd_entry->sh_addralign +#define SUBSPACE_ACCESS(ss_chain) (ss_chain)->ssd_entry->sh_flags +#define SUBSPACE_SORT(ss_chain) (ss_chain)->ssd_sort_key +#define SUBSPACE_COMMON(ss_chain) (ss_chain)->ssd_common +#define SUBSPACE_ZERO(ss_chain) (ss_chain)->ssd_zero +#define SUBSPACE_DUP_COMM(ss_chain) (ss_chain)->ssd_dup_common +#define SUBSPACE_CODE_ONLY(ssch) \ + (((ssch)->ssd_entry->sh_flags & (SHF_ALLOC | SHF_EXECINSTR | SHF_WRITE)) \ + == (SHF_ALLOC | SHF_EXECINSTR)) +#define SET_SUBSPACE_CODE_ONLY(ssch,val) \ + (ssch)->ssd_entry->sh_flags &= ((val) ? ~SHF_WRITE : 0xffffffff) +#define SUBSPACE_LOADABLE(ss_chain) (ss_chain)->ssd_loadable +#define SUBSPACE_SUBSPACE_START(ss_chain) (ss_chain)->ssd_vm_addr +#define SUBSPACE_SUBSPACE_LENGTH(ss_chain) (ss_chain)->ssd_entry->sh_size +#define SUBSPACE_NAME(ss_chain) (ss_chain)->ssd_name + +#define STAB_FIXUP(frag,toptr,symP,stab_type) \ + if ( (stab_type == 's' || stab_type == 'n') \ + && symP->sy_value.X_seg == undefined_section) \ + { \ + int i = S_GET_TYPE(symP) & N_TYPE; \ + fix_new_hppa(frag, \ + toptr-frag->fr_literal, /* where */ \ + 4, /* size */ \ + symP->sy_value.X_add_symbol, /* addr of sym for this stab */ \ + (asymbol *)NULL, \ + 0, \ + i == N_UNDF || i == N_ABS, /* 1 if internal reloc */ \ + R_HPPA, /* type */ \ + e_fsel, /* fixup fld = F% */ \ + 32, \ + 0, /* arg_reloc */ \ + (char *)0 \ + ); \ + } \ + else if ( stab_type == 'd' ) \ + { \ + fix_new_hppa (frag, \ + toptr-frag->fr_literal, /* where */ \ + 4, /* size */ \ + symP, /* addr of sym for this stab */ \ + (asymbol *)NULL, \ + 0, \ + 0, \ + R_HPPA, /* type */ \ + e_fsel, /* fixup fld = F% */ \ + 32, \ + 0, /* arg_reloc */ \ + (char *)0 \ + ); \ + } + +#endif + +#ifdef OBJ_SOM +#define SPACE_DEFINED(space_chain) (space_chain)->sd_entry->is_defined +#define SPACE_PRIVATE(space_chain) (space_chain)->sd_entry->is_private +#define SPACE_LOADABLE(space_chain) (space_chain)->sd_entry->is_loadable +#define SPACE_SPNUM(space_chain) (space_chain)->sd_entry->space_number +#define SPACE_SORT(space_chain) (space_chain)->sd_entry->sort_key +#define SPACE_NAME(space_chain) (space_chain)->sd_entry->name + +#define SUBSPACE_QUADRANT(ss_chain) (ss_chain)->ssd_entry->quadrant +#define SUBSPACE_ALIGN(ss_chain) (ss_chain)->ssd_entry->alignment +#define SUBSPACE_ACCESS(ss_chain) (ss_chain)->ssd_entry->access_control_bits +#define SUBSPACE_SORT(ss_chain) (ss_chain)->ssd_entry->sort_key +#define SUBSPACE_COMMON(ss_chain) (ss_chain)->ssd_entry->is_common +#define SUBSPACE_ZERO(ss_chain) (ss_chain)->ssd_zero +#define SUBSPACE_DUP_COMM(ss_chain) (ss_chain)->ssd_entry->dup_common +#define SUBSPACE_CODE_ONLY(ss_chain) (ss_chain)->ssd_entry->code_only +#define SUBSPACE_LOADABLE(ss_chain) (ss_chain)->ssd_entry->is_loadable +#define SUBSPACE_SUBSPACE_START(ss_chain) (ss_chain)->ssd_entry->subspace_start +#define SUBSPACE_SUBSPACE_LENGTH(ss_chain) (ss_chain)->ssd_entry->subspace_length +#define SUBSPACE_NAME(ss_chain) (ss_chain)->ssd_entry->name +#endif + +extern space_dict_chainS *space_dict_root; +extern space_dict_chainS *space_dict_last; + +extern space_dict_chainS *current_space; +extern subspace_dict_chainS *current_subspace; + +extern space_dict_chainS *create_new_space (); + +extern subspace_dict_chainS *create_new_subspace (); + +extern subspace_dict_chainS *update_subspace (); + +extern space_dict_chainS *is_defined_space (); + +extern space_dict_chainS *pa_segment_to_space (); + +extern subspace_dict_chainS *is_defined_subspace (); + +extern subspace_dict_chainS *pa_subsegment_to_subspace (); + +extern space_dict_chainS *pa_find_space_by_number (); + +extern unsigned int pa_subspace_start (); + +extern int is_last_defined_subspace (); + +/* symbol support */ + +extern symbolS *pa_get_start_symbol (); + +extern symbolS *pa_set_start_symbol (); + +/* default space and subspace dictionaries */ + +struct default_subspace_dict + { + char *name; + char defined; + char loadable, code_only, common, dup_common, zero, sort; + int access, space_index, alignment, quadrant; +#ifdef OBJ_SOM + segT segment; +#else + int def_space_index; /* this is an index in the default spaces array */ + char *alias; /* an alias for this section (or NULL if there isn't one) */ +#endif + subsegT subsegment; + }; + +extern struct default_subspace_dict pa_def_subspaces[]; + +struct default_space_dict + { + char *name; + int spnum; + char loadable; + char defined; + char private; + char sort; +#ifdef OBJ_SOM + segT segment; +#else + asection *segment; + char *alias; /* an alias for this section (or NULL if there isn't one) */ +#endif + }; + +extern struct default_space_dict pa_def_spaces[]; + +/* + Support for keeping track of the most recent label in each + space. + */ + +typedef struct label_symbol_struct + { + symbolS *lss_label; /* the label symbol */ + space_dict_chainS *lss_space; /* the space to which it applies*/ + struct label_symbol_struct *lss_next; /* the next label symbol */ + } label_symbolS; + +extern label_symbolS *label_symbols_rootP; + +label_symbolS *pa_get_label (); +int pa_label_is_defined (); +void pa_define_label (); +void pa_undefine_label (); +int pa_pseudo_op_moves_pc (); + +/* end of label symbol support. */ + +#define is_DP_relative(exp) ( (exp).X_subtract_symbol \ + && strcmp((exp).X_subtract_symbol->bsym->name, \ + "$global$") == 0 ) + +#define is_PC_relative(exp) ( (exp).X_subtract_symbol \ + && strcmp((exp).X_subtract_symbol->bsym->name, \ + "$PIC_pcrel$0") == 0 ) + +#define is_complex(exp) ((exp).X_seg && (exp).X_seg == diff_section) + +#define tc_crawl_symbol_chain(headers) {;} /* Not used. */ + +#define tc_headers_hook(headers) {;} /* Not used. */ + +#define elf_tc_symbol elf_hppa_tc_symbol +#define elf_tc_make_sections elf_hppa_tc_make_sections +extern void elf_hppa_final_processing (); +#define elf_tc_final_processing elf_hppa_final_processing + +/* We need to parse field selectors in .byte, etc. */ + +#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \ + parse_cons_expression_hppa (exp) +#define TC_CONS_FIX_NEW cons_fix_new_hppa + +extern void parse_cons_expression_hppa PARAMS ((expressionS *exp)); +extern void cons_fix_new_hppa PARAMS ((fragS *frag, + int where, + int size, + expressionS *exp)); + +#endif /* _TC_HPPA_H */ diff --git a/gas/read.c b/gas/read.c index afe9023..2a5dabe 100644 --- a/gas/read.c +++ b/gas/read.c @@ -1499,13 +1499,19 @@ pseudo_set (symbolP) } else if (segment == pass1_section) { - symbolP->sy_forward = exp.X_add_symbol; + symbolP->sy_value.X_add_symbol = exp.X_add_symbol; + symbolP->sy_value.X_subtract_symbol = NULL; + symbolP->sy_value.X_add_number = 0; + symbolP->sy_value.X_seg = undefined_section; as_bad ("Unknown expression"); know (need_pass_2 == 1); } else if (segment == undefined_section) { - symbolP->sy_forward = exp.X_add_symbol; + symbolP->sy_value.X_add_symbol = exp.X_add_symbol; + symbolP->sy_value.X_subtract_symbol = NULL; + symbolP->sy_value.X_add_number = 0; + symbolP->sy_value.X_seg = undefined_section; } else { diff --git a/gas/symbols.c b/gas/symbols.c index 24fe3d8..05db99a 100644 --- a/gas/symbols.c +++ b/gas/symbols.c @@ -118,7 +118,6 @@ symbol_new (name, segment, value, frag) symbol_clear_list_pointers(symbolP); symbolP->sy_frag = frag; - symbolP->sy_forward = NULL; #ifndef BFD_ASSEMBLER symbolP->sy_number = ~0; symbolP->sy_name_offset = ~0; @@ -566,6 +565,53 @@ verify_symbol_chain_2 (sym) verify_symbol_chain (p, n); } +/* Resolve the value of a symbol. This is called during the final + pass over the symbol table to resolve any symbols with complex + values. */ + +void +resolve_symbol_value (symp) + symbolS *symp; +{ + if (symp->sy_resolved) + return; + + if (symp->sy_resolving) + { + as_bad ("Symbol definition loop encountered at %s", + S_GET_NAME (symp)); + S_SET_VALUE (symp, (valueT) 0); + } + else + { + symp->sy_resolving = 1; + + if (symp->sy_value.X_seg == absolute_section) + S_SET_VALUE (symp, S_GET_VALUE (symp) + symp->sy_frag->fr_address); + else if (symp->sy_value.X_seg == undefined_section) + { + resolve_symbol_value (symp->sy_value.X_add_symbol); + +#ifdef obj_frob_forward_symbol + /* Some object formats need to forward the segment. */ + obj_frob_forward_symbol (symp); +#endif + + S_SET_VALUE (symp, + (symp->sy_value.X_add_number + + symp->sy_frag->fr_address + + S_GET_VALUE (symp->sy_value.X_add_symbol))); + } + else + { + /* More cases need to be added here. */ + abort (); + } + } + + symp->sy_resolved = 1; +} + #ifdef LOCAL_LABELS_DOLLAR /* Dollar labels look like a number followed by a dollar sign. Eg, "42$". @@ -953,7 +999,7 @@ S_GET_VALUE (s) symbolS *s; { if (s->sy_value.X_seg != absolute_section) - as_bad ("Attempt to get value of unresolved symbol"); + as_bad ("Attempt to get value of unresolved symbol %s", S_GET_NAME (s)); return (valueT) s->sy_value.X_add_number; } diff --git a/gas/write.c b/gas/write.c index 63353e3..ca7c625 100644 --- a/gas/write.c +++ b/gas/write.c @@ -1172,18 +1172,30 @@ write_object_file () { int keep = 0; - S_SET_VALUE (symp, S_GET_VALUE (symp) + symp->sy_frag->fr_address); + if (! symp->sy_resolved) + { + if (symp->sy_value.X_seg == absolute_section) + { + /* This is the normal case; skip the call. */ + S_SET_VALUE (symp, + (S_GET_VALUE (symp) + + symp->sy_frag->fr_address)); + symp->sy_resolved = 1; + } + else + resolve_symbol_value (symp); + } + /* So far, common symbols have been treated like undefined symbols. Put them in the common section now. */ if (S_IS_DEFINED (symp) == 0 && S_GET_VALUE (symp) != 0) S_SET_SEGMENT (symp, &bfd_com_section); #if 0 - printf ("symbol `%s'\n\t@%x: value=%d flags=%x forward=%x seg=%s\n", + printf ("symbol `%s'\n\t@%x: value=%d flags=%x seg=%s\n", S_GET_NAME (symp), symp, S_GET_VALUE (symp), symp->bsym->flags, - symp->sy_forward, segment_name (symp->bsym->section)); #endif { -- 2.7.4