X-Git-Url: https://oss.titaniummirror.com/gitweb?p=msp430-binutils.git;a=blobdiff_plain;f=gas%2Fwrite.c;h=8adb87b94a302c67d7874756e9688203289c70a0;hp=03641dfa4b320618b2a37911b32eeb9572347ba4;hb=88750007d7869f178f0ba528f41efd3b74c424cf;hpb=6df9443a374e2b81278c61b8afc0a1eef7db280b diff --git a/gas/write.c b/gas/write.c index 03641df..8adb87b 100644 --- a/gas/write.c +++ b/gas/write.c @@ -1,6 +1,6 @@ /* write.c - emit .o file Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -54,26 +54,34 @@ (! SEG_NORMAL (SEG)) #endif +#ifndef md_register_arithmetic +# define md_register_arithmetic 1 +#endif + #ifndef TC_FORCE_RELOCATION_SUB_ABS -#define TC_FORCE_RELOCATION_SUB_ABS(FIX) 0 +#define TC_FORCE_RELOCATION_SUB_ABS(FIX, SEG) \ + (!md_register_arithmetic && (SEG) == reg_section) #endif #ifndef TC_FORCE_RELOCATION_SUB_LOCAL #ifdef DIFF_EXPR_OK -#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX) 0 +#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) \ + (!md_register_arithmetic && (SEG) == reg_section) #else -#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX) 1 +#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) 1 #endif #endif #ifndef TC_VALIDATE_FIX_SUB #ifdef UNDEFINED_DIFFERENCE_OK /* The PA needs this for PIC code generation. */ -#define TC_VALIDATE_FIX_SUB(FIX) 1 +#define TC_VALIDATE_FIX_SUB(FIX, SEG) \ + (md_register_arithmetic || (SEG) != reg_section) #else -#define TC_VALIDATE_FIX_SUB(FIX) \ - ((FIX)->fx_r_type == BFD_RELOC_GPREL32 \ - || (FIX)->fx_r_type == BFD_RELOC_GPREL16) +#define TC_VALIDATE_FIX_SUB(FIX, SEG) \ + ((md_register_arithmetic || (SEG) != reg_section) \ + && ((FIX)->fx_r_type == BFD_RELOC_GPREL32 \ + || (FIX)->fx_r_type == BFD_RELOC_GPREL16)) #endif #endif @@ -148,7 +156,7 @@ fix_new_internal (fragS *frag, /* Which frag? */ n_fixups++; - fixP = obstack_alloc (¬es, sizeof (fixS)); + fixP = (fixS *) obstack_alloc (¬es, sizeof (fixS)); fixP->fx_frag = frag; fixP->fx_where = where; @@ -378,7 +386,7 @@ chain_frchains_together_1 (segT section, struct frchain *frchp) { prev_frag->fr_next = frchp->frch_root; prev_frag = frchp->frch_last; - assert (prev_frag->fr_type != 0); + gas_assert (prev_frag->fr_type != 0); if (frchp->fix_root != (fixS *) NULL) { if (seg_info (section)->fix_root == (fixS *) NULL) @@ -388,8 +396,8 @@ chain_frchains_together_1 (segT section, struct frchain *frchp) prev_fix = frchp->fix_tail; } } - assert (prev_frag->fr_type != 0); - assert (prev_frag != &dummy); + gas_assert (prev_frag->fr_type != 0); + gas_assert (prev_frag != &dummy); prev_frag->fr_next = 0; return prev_frag; } @@ -470,7 +478,7 @@ cvt_frag_to_fill (segT sec ATTRIBUTE_UNUSED, fragS *fragP) case rs_machine_dependent: md_convert_frag (stdoutput, sec, fragP); - assert (fragP->fr_next == NULL + gas_assert (fragP->fr_next == NULL || ((offsetT) (fragP->fr_next->fr_address - fragP->fr_address) == fragP->fr_fix)); @@ -552,21 +560,24 @@ size_seg (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED) size = 0; flags = bfd_get_section_flags (abfd, sec); + if (size == 0 && bfd_get_section_size (sec) != 0 && + (flags & SEC_HAS_CONTENTS) != 0) + return; if (size > 0 && ! seginfo->bss) flags |= SEC_HAS_CONTENTS; flags &= ~SEC_RELOC; x = bfd_set_section_flags (abfd, sec, flags); - assert (x); + gas_assert (x); newsize = md_section_align (sec, size); x = bfd_set_section_size (abfd, sec, newsize); - assert (x); + gas_assert (x); /* If the size had to be rounded up, add some padding in the last non-empty frag. */ - assert (newsize >= size); + gas_assert (newsize >= size); if (size != newsize) { fragS *last = seginfo->frchainP->frch_last; @@ -924,14 +935,14 @@ fixup_segment (fixS *fixP, segT this_segment) #endif } else if (sub_symbol_segment == absolute_section - && !TC_FORCE_RELOCATION_SUB_ABS (fixP)) + && !TC_FORCE_RELOCATION_SUB_ABS (fixP, add_symbol_segment)) { add_number -= S_GET_VALUE (fixP->fx_subsy); fixP->fx_offset = add_number; fixP->fx_subsy = NULL; } else if (sub_symbol_segment == this_segment - && !TC_FORCE_RELOCATION_SUB_LOCAL (fixP)) + && !TC_FORCE_RELOCATION_SUB_LOCAL (fixP, add_symbol_segment)) { add_number -= S_GET_VALUE (fixP->fx_subsy); fixP->fx_offset = (add_number + fixP->fx_dot_value @@ -953,14 +964,20 @@ fixup_segment (fixS *fixP, segT this_segment) fixP->fx_subsy = NULL; fixP->fx_pcrel = 1; } - else if (!TC_VALIDATE_FIX_SUB (fixP)) + else if (!TC_VALIDATE_FIX_SUB (fixP, add_symbol_segment)) { - as_bad_where (fixP->fx_file, fixP->fx_line, - _("can't resolve `%s' {%s section} - `%s' {%s section}"), - fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0", - segment_name (add_symbol_segment), - S_GET_NAME (fixP->fx_subsy), - segment_name (sub_symbol_segment)); + if (!md_register_arithmetic + && (add_symbol_segment == reg_section + || sub_symbol_segment == reg_section)) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("register value used as expression")); + else + as_bad_where (fixP->fx_file, fixP->fx_line, + _("can't resolve `%s' {%s section} - `%s' {%s section}"), + fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0", + segment_name (add_symbol_segment), + S_GET_NAME (fixP->fx_subsy), + segment_name (sub_symbol_segment)); } } @@ -1084,6 +1101,15 @@ install_reloc (asection *sec, arelent *reloc, fragS *fragp, { char *err; bfd_reloc_status_type s; + asymbol *sym; + + if (reloc->sym_ptr_ptr != NULL + && (sym = *reloc->sym_ptr_ptr) != NULL + && (sym->flags & BSF_KEEP) == 0 + && ((sym->flags & BSF_SECTION_SYM) == 0 + || (EMIT_SECTION_SYMBOLS + && !bfd_is_abs_section (sym->section)))) + as_bad_where (file, line, _("redefined symbol cannot be used on reloc")); s = bfd_install_relocation (stdoutput, reloc, fragp->fr_literal, fragp->fr_address, @@ -1144,7 +1170,7 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED) rp = &r->next; } - relocs = xcalloc (n, sizeof (arelent *)); + relocs = (arelent **) xcalloc (n, sizeof (arelent *)); i = 0; for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next) @@ -1276,7 +1302,7 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED, char *fill_literal; offsetT count; - assert (f->fr_type == rs_fill); + gas_assert (f->fr_type == rs_fill); if (f->fr_fix) { x = bfd_set_section_contents (stdoutput, sec, @@ -1290,7 +1316,7 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED, fill_literal = f->fr_literal + f->fr_fix; fill_size = f->fr_var; count = f->fr_offset; - assert (count >= 0); + gas_assert (count >= 0); if (fill_size && count) { char buf[256]; @@ -1372,18 +1398,22 @@ set_symtab (void) int i; bfd_size_type amt = (bfd_size_type) nsyms * sizeof (asymbol *); - asympp = bfd_alloc (stdoutput, amt); + asympp = (asymbol **) bfd_alloc (stdoutput, amt); symp = symbol_rootP; for (i = 0; i < nsyms; i++, symp = symbol_next (symp)) { asympp[i] = symbol_get_bfdsym (symp); + if (asympp[i]->flags != BSF_SECTION_SYM + || !(bfd_is_const_section (asympp[i]->section) + && asympp[i]->section->symbol == asympp[i])) + asympp[i]->flags |= BSF_KEEP; symbol_mark_written (symp); } } else asympp = 0; result = bfd_set_symtab (stdoutput, asympp, nsyms); - assert (result); + gas_assert (result); symbol_table_frozen = 1; } @@ -1644,18 +1674,22 @@ write_object_file (void) if (lie->added == 2) continue; /* Patch the jump table. */ - /* This is the offset from ??? to table_ptr+0. */ - to_addr = table_addr - S_GET_VALUE (lie->sub); -#ifdef TC_CHECK_ADJUSTED_BROKEN_DOT_WORD - TC_CHECK_ADJUSTED_BROKEN_DOT_WORD (to_addr, lie); -#endif - md_number_to_chars (lie->word_goes_here, to_addr, 2); - for (untruth = lie->next_broken_word; + for (untruth = (struct broken_word *) (fragP->fr_symbol); untruth && untruth->dispfrag == fragP; untruth = untruth->next_broken_word) { if (untruth->use_jump == lie) - md_number_to_chars (untruth->word_goes_here, to_addr, 2); + { + /* This is the offset from ??? to table_ptr+0. + The target is the same for all users of this + md_long_jump, but the "sub" bases (and hence the + offsets) may be different. */ + addressT to_word = table_addr - S_GET_VALUE (untruth->sub); +#ifdef TC_CHECK_ADJUSTED_BROKEN_DOT_WORD + TC_CHECK_ADJUSTED_BROKEN_DOT_WORD (to_word, untruth); +#endif + md_number_to_chars (untruth->word_goes_here, to_word, 2); + } } /* Install the long jump. */ @@ -1763,6 +1797,13 @@ write_object_file (void) as_bad (_("Local symbol `%s' can't be equated to common symbol `%s'"), name, S_GET_NAME (e->X_add_symbol)); } + if (S_GET_SEGMENT (symp) == reg_section) + { + /* Report error only if we know the symbol name. */ + if (S_GET_NAME (symp) != reg_section->name) + as_bad (_("can't make global register symbol `%s'"), + name); + } symbol_remove (symp, &symbol_rootP, &symbol_lastP); continue; } @@ -1830,6 +1871,10 @@ write_object_file (void) obj_adjust_symtab (); #endif + /* Stop if there is an error. */ + if (had_errors ()) + return; + /* Now that all the sizes are known, and contents correct, we can start writing to the file. */ set_symtab (); @@ -1844,7 +1889,9 @@ write_object_file (void) #ifdef obj_frob_file obj_frob_file (); #endif - +#ifdef obj_coff_generate_pdata + obj_coff_generate_pdata (); +#endif bfd_map_over_sections (stdoutput, write_relocs, (char *) 0); #ifdef tc_frob_file_after_relocs @@ -2188,13 +2235,17 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass) S_GET_NAME (lie->sub), buf); } - lie->added = 1; if (fragP->fr_subtype == 0) { fragP->fr_subtype++; growth += md_short_jump_size; } - for (untruth = lie->next_broken_word; + + /* Redirect *all* words of this table with the same + target, lest we have to handle the case where the + same target but with a offset that fits on this + round overflows at the next relaxation round. */ + for (untruth = (struct broken_word *) (fragP->fr_symbol); untruth && untruth->dispfrag == lie->dispfrag; untruth = untruth->next_broken_word) if ((symbol_get_frag (untruth->add) @@ -2205,6 +2256,8 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass) untruth->added = 2; untruth->use_jump = lie; } + + lie->added = 1; growth += md_long_jump_size; } } @@ -2294,7 +2347,7 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass) } know (fragP->fr_next); - after = fragP->fr_next->fr_address; + after = fragP->fr_next->fr_address + stretch; growth = target - after; if (growth < 0) { @@ -2329,14 +2382,10 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass) fragP->fr_type = rs_align; fragP->fr_subtype = 0; fragP->fr_offset = 0; - fragP->fr_fix = after - was_address; - break; + fragP->fr_fix = after - address; } - - /* This is an absolute growth factor */ - growth -= stretch; - break; } + break; case rs_space: growth = 0; @@ -2509,7 +2558,8 @@ print_fixup (fixS *fixp) fprintf_vma (stderr, (bfd_vma) ((bfd_hostptr_t) fixp->fx_frag)); fprintf (stderr, " where=%ld offset=%lx addnumber=%lx", (long) fixp->fx_where, - (long) fixp->fx_offset, (long) fixp->fx_addnumber); + (unsigned long) fixp->fx_offset, + (unsigned long) fixp->fx_addnumber); fprintf (stderr, "\n %s (%d)", bfd_get_reloc_code_name (fixp->fx_r_type), fixp->fx_r_type); if (fixp->fx_addsy)