X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fwrite.c;h=91871da548ee4ee06766e22e1b8afc4b3eea4e05;hb=96fe71e1d5874b8796145e7e73bd7efedb578666;hp=df8f66e984d04f1788b7b7c8e24ff3a664c934f5;hpb=d4083e293a41b03d62c8e8f5a9d3c16766f58e70;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/write.c b/gas/write.c index df8f66e984..91871da548 100644 --- a/gas/write.c +++ b/gas/write.c @@ -43,6 +43,14 @@ #define TC_FORCE_RELOCATION(FIXP) 0 #endif +#ifndef TC_FORCE_RELOCATION_SECTION +#define TC_FORCE_RELOCATION_SECTION(FIXP,SEG) TC_FORCE_RELOCATION(FIXP) +#endif + +#ifndef MD_PCREL_FROM_SECTION +#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from(FIXP) +#endif + #ifndef WORKING_DOT_WORD extern CONST int md_short_jump_size; extern CONST int md_long_jump_size; @@ -130,6 +138,12 @@ fix_new_internal (frag, where, size, add_symbol, sub_symbol, offset, pcrel, fixP->fx_frag = frag; fixP->fx_where = where; fixP->fx_size = size; + /* We've made fx_size a narrow field; check that it's wide enough. */ + if (fixP->fx_size != size) + { + as_bad ("field fx_size too small to hold %d", size); + abort (); + } fixP->fx_addsy = add_symbol; fixP->fx_subsy = sub_symbol; fixP->fx_offset = offset; @@ -142,12 +156,11 @@ fix_new_internal (frag, where, size, add_symbol, sub_symbol, offset, pcrel, fixP->fx_pcrel_adjust = 0; fixP->fx_bit_fixP = 0; fixP->fx_addnumber = 0; - fixP->tc_fix_data = NULL; fixP->fx_tcbit = 0; fixP->fx_done = 0; -#if defined (TC_I960) || defined (TC_NS32K) - fixP->fx_bsr = 0; +#ifdef TC_FIX_TYPE + TC_INIT_FIX_DATA(fixP); #endif as_where (&fixP->fx_file, &fixP->fx_line); @@ -230,7 +243,7 @@ fix_new_exp (frag, where, size, exp, pcrel, r_type) symbolS *add = NULL; symbolS *sub = NULL; offsetT off = 0; - + switch (exp->X_op) { case O_absent: @@ -249,6 +262,19 @@ fix_new_exp (frag, where, size, exp, pcrel, r_type) return fix_new_exp (frag, where, size, exp, pcrel, r_type); } + case O_symbol_rva: + add = exp->X_add_symbol; + off = exp->X_add_number; + +#if defined(BFD_ASSEMBLER) + r_type = BFD_RELOC_RVA; +#elif defined(TC_RVA_RELOC) + r_type = TC_RVA_RELOC; +#else + as_fatal("rva not supported"); +#endif + break; + case O_uminus: sub = exp->X_add_symbol; off = exp->X_add_number; @@ -305,6 +331,8 @@ record_alignment (seg, align) boundary, etc.) */ int align; { + if (seg == absolute_section) + return; #ifdef BFD_ASSEMBLER if (align > bfd_get_section_alignment (stdoutput, seg)) bfd_set_section_alignment (stdoutput, seg, align); @@ -348,6 +376,7 @@ chain_frchains_together_1 (section, frchp) { prev_frag->fr_next = frchp->frch_root; prev_frag = frchp->frch_last; + assert (prev_frag->fr_type != 0); #ifdef BFD_ASSEMBLER if (frchp->fix_root != (fixS *) NULL) { @@ -359,6 +388,7 @@ chain_frchains_together_1 (section, frchp) } #endif } + assert (prev_frag->fr_type != 0); prev_frag->fr_next = 0; return prev_frag; } @@ -500,6 +530,8 @@ relax_and_size_seg (abfd, sec, xxx) int x; valueT size, newsize; + subseg_change (sec, 0); + flags = bfd_get_section_flags (abfd, sec); seginfo = seg_info (sec); @@ -630,6 +662,12 @@ adjust_reloc_syms (abfd, sec, xxx) sym = fixp->fx_addsy; symsec = sym->bsym->section; + if (sym != NULL && sym->sy_mri_common) + { + /* These symbols are handled specially in fixup_segment. */ + goto done; + } + /* If it's one of these sections, assume the symbol is definitely going to be output. The code in md_estimate_size_before_relax in tc-mips.c uses this test @@ -932,66 +970,56 @@ write_contents (abfd, sec, xxx) count = f->fr_offset; assert (count >= 0); if (fill_size && count) -#ifdef BFD_FAST_SECTION_FILL { char buf[256]; - if (fill_size > sizeof(buf)) { - /* Do it the old way. Can this ever happen? */ - while (count--) - { - x = bfd_set_section_contents (stdoutput, sec, - fill_literal, (file_ptr) offset, - (bfd_size_type) fill_size); - if (x == false) - { - bfd_perror (stdoutput->filename); - as_perror ("FATAL: Can't write %s", stdoutput->filename); - exit (EXIT_FAILURE); - } - offset += fill_size; - } - } - else { - /* Build a buffer full of fill objects and output it as - * often as necessary. This saves on the overhead of potentially - * lots of bfd_set_section_contents calls. - */ - int n_per_buf, i; - if (fill_size == 1) - { - n_per_buf = sizeof (buf); - memset (buf, *fill_literal, n_per_buf); - } - else - { - char *bufp; - n_per_buf = sizeof(buf)/fill_size; - for (i = n_per_buf, bufp = buf; i; i--, bufp += fill_size) - memcpy(bufp, fill_literal, fill_size); - } - for (; count > 0; count -= n_per_buf) - { - n_per_buf = n_per_buf > count ? count : n_per_buf; - x = bfd_set_section_contents (stdoutput, sec, - buf, (file_ptr) offset, - (bfd_size_type) n_per_buf * fill_size); - if (x != true) - as_fatal ("Cannot write to output file."); - offset += n_per_buf * fill_size; - } - } + if (fill_size > sizeof(buf)) + { + /* Do it the old way. Can this ever happen? */ + while (count--) + { + x = bfd_set_section_contents (stdoutput, sec, + fill_literal, + (file_ptr) offset, + (bfd_size_type) fill_size); + if (x == false) + { + bfd_perror (stdoutput->filename); + as_perror ("FATAL: Can't write %s", stdoutput->filename); + exit (EXIT_FAILURE); + } + offset += fill_size; + } + } + else + { + /* Build a buffer full of fill objects and output it as + often as necessary. This saves on the overhead of + potentially lots of bfd_set_section_contents calls. */ + int n_per_buf, i; + if (fill_size == 1) + { + n_per_buf = sizeof (buf); + memset (buf, *fill_literal, n_per_buf); + } + else + { + char *bufp; + n_per_buf = sizeof(buf)/fill_size; + for (i = n_per_buf, bufp = buf; i; i--, bufp += fill_size) + memcpy(bufp, fill_literal, fill_size); + } + for (; count > 0; count -= n_per_buf) + { + n_per_buf = n_per_buf > count ? count : n_per_buf; + x = bfd_set_section_contents (stdoutput, sec, + buf, (file_ptr) offset, + (bfd_size_type) n_per_buf * fill_size); + if (x != true) + as_fatal ("Cannot write to output file."); + offset += n_per_buf * fill_size; + } + } } -#else - while (count--) - { - x = bfd_set_section_contents (stdoutput, sec, - fill_literal, (file_ptr) offset, - (bfd_size_type) fill_size); - if (x != true) - as_fatal ("Cannot write to output file."); - offset += fill_size; - } -#endif } } #endif @@ -1578,6 +1606,15 @@ write_object_file () int punt = 0; const char *name; + if (symp->sy_mri_common) + { + if (S_IS_EXTERNAL (symp)) + as_bad ("%s: global symbols not supported in common sections", + S_GET_NAME (symp)); + symbol_remove (symp, &symbol_rootP, &symbol_lastP); + continue; + } + name = S_GET_NAME (symp); if (name) { @@ -2154,17 +2191,36 @@ fixup_segment (fixP, this_segment_type) pcrel = fixP->fx_pcrel; plt = fixP->fx_plt; + if (add_symbolP != NULL + && add_symbolP->sy_mri_common) + { + know (add_symbolP->sy_value.X_op == O_symbol); + add_number += S_GET_VALUE (add_symbolP); + fixP->fx_offset = add_number; + add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol; + } + if (add_symbolP) add_symbol_segment = S_GET_SEGMENT (add_symbolP); if (sub_symbolP) { resolve_symbol_value (sub_symbolP); - if (!add_symbolP) + if (add_symbolP == NULL || add_symbol_segment == absolute_section) { - /* Its just -sym */ + if (add_symbolP != NULL) + { + add_number += S_GET_VALUE (add_symbolP); + add_symbolP = NULL; + fixP->fx_addsy = NULL; + } + + /* It's just -sym */ if (S_GET_SEGMENT (sub_symbolP) == absolute_section) - add_number -= S_GET_VALUE (sub_symbolP); + { + add_number -= S_GET_VALUE (sub_symbolP); + fixP->fx_subsy = NULL; + } else if (pcrel && S_GET_SEGMENT (sub_symbolP) == this_segment_type) { @@ -2177,9 +2233,8 @@ fixup_segment (fixP, this_segment_type) "Negative of non-absolute symbol %s", S_GET_NAME (sub_symbolP)); } - else if ((S_GET_SEGMENT (sub_symbolP) == add_symbol_segment) - && (SEG_NORMAL (add_symbol_segment) - || (add_symbol_segment == absolute_section))) + else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment + && SEG_NORMAL (add_symbol_segment)) { /* Difference of 2 symbols from same segment. Can't make difference of 2 undefineds: 'value' means @@ -2200,10 +2255,11 @@ fixup_segment (fixP, this_segment_type) /* Let the target machine make the final determination as to whether or not a relocation will be needed to handle this fixup. */ - if (!TC_FORCE_RELOCATION (fixP)) + if (!TC_FORCE_RELOCATION_SECTION (fixP, this_segment_type)) { fixP->fx_pcrel = 0; fixP->fx_addsy = NULL; + fixP->fx_subsy = NULL; } } else @@ -2225,7 +2281,7 @@ fixup_segment (fixP, this_segment_type) ) { /* Make it pc-relative. */ - add_number += (md_pcrel_from (fixP) + add_number += (MD_PCREL_FROM_SECTION (fixP, this_segment_type) - S_GET_VALUE (sub_symbolP)); pcrel = 1; fixP->fx_pcrel = 1; @@ -2281,7 +2337,7 @@ fixup_segment (fixP, this_segment_type) #endif /* TC_I960 */ add_number += S_GET_VALUE (add_symbolP); - add_number -= md_pcrel_from (fixP); + add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment_type); pcrel = 0; /* Lie. Don't want further pcrel processing. */ /* Let the target machine make the final determination @@ -2306,6 +2362,7 @@ fixup_segment (fixP, this_segment_type) /* Let the target machine make the final determination as to whether or not a relocation will be needed to handle this fixup. */ + if (!TC_FORCE_RELOCATION (fixP)) { fixP->fx_addsy = NULL; @@ -2354,7 +2411,7 @@ fixup_segment (fixP, this_segment_type) if (pcrel) { - add_number -= md_pcrel_from (fixP); + add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment_type); if (add_symbolP == 0) { #ifndef BFD_ASSEMBLER @@ -2367,7 +2424,7 @@ fixup_segment (fixP, this_segment_type) } } - if (!fixP->fx_bit_fixP && size > 0) + if (!fixP->fx_bit_fixP && !fixP->fx_no_overflow && size > 0) { valueT mask = 0; if (size < sizeof (mask))