diff options
-rw-r--r-- | gas/ChangeLog | 10 | ||||
-rw-r--r-- | gas/config/tc-bfin.h | 3 | ||||
-rw-r--r-- | gas/config/tc-h8300.h | 3 | ||||
-rw-r--r-- | gas/config/tc-mmix.h | 3 | ||||
-rw-r--r-- | gas/config/tc-sh.h | 5 | ||||
-rw-r--r-- | gas/config/tc-xstormy16.h | 3 | ||||
-rw-r--r-- | gas/write.c | 40 |
7 files changed, 59 insertions, 8 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index a4ac8f9..e68439d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2007-02-18 Alan Modra <amodra@bigpond.net.au> + + * write.c (TC_FX_SIZE_SLACK): Define. + (write_relocs): Reinstate check for fixup within frag. + * config/tc-bfin.h (TC_FX_SIZE_SLACK): Define. + * config/tc-h8300.h (TC_FX_SIZE_SLACK): Define. + * config/tc-mmix.h (TC_FX_SIZE_SLACK): Define. + * config/tc-sh.h (TC_FX_SIZE_SLACK): Define. + * config/tc-xstormy16.h (TC_FX_SIZE_SLACK): Define. + 2007-02-17 Mark Mitchell <mark@codesourcery.com> Nathan Sidwell <nathan@codesourcery.com> Vladimir Prus <vladimir@codesourcery.com diff --git a/gas/config/tc-bfin.h b/gas/config/tc-bfin.h index fb0c63c..e1f95a9 100644 --- a/gas/config/tc-bfin.h +++ b/gas/config/tc-bfin.h @@ -75,4 +75,7 @@ extern long md_pcrel_from_section PARAMS ((struct fix *, segT)); /* Values passed to md_apply_fix3 don't include symbol values. */ #define MD_APPLY_SYM_VALUE(FIX) 0 +/* This target is buggy, and sets fix size too large. */ +#define TC_FX_SIZE_SLACK(FIX) 2 + /* end of tc-bfin.h */ diff --git a/gas/config/tc-h8300.h b/gas/config/tc-h8300.h index bfc8f72..7191181 100644 --- a/gas/config/tc-h8300.h +++ b/gas/config/tc-h8300.h @@ -86,3 +86,6 @@ extern int Nmode; extern int SXmode; #define md_operand(x) + +/* This target is buggy, and sets fix size too large. */ +#define TC_FX_SIZE_SLACK(FIX) 1 diff --git a/gas/config/tc-mmix.h b/gas/config/tc-mmix.h index 61bc881..b4ab0c7 100644 --- a/gas/config/tc-mmix.h +++ b/gas/config/tc-mmix.h @@ -221,3 +221,6 @@ extern void mmix_md_do_align (int, char *, int, int); sequences sprinkled in, we can get unaligned DWARF2 offsets, so let's explicitly say one byte. */ #define DWARF2_LINE_MIN_INSN_LENGTH 1 + +/* This target is buggy, and sets fix size too large. */ +#define TC_FX_SIZE_SLACK(FIX) 6 diff --git a/gas/config/tc-sh.h b/gas/config/tc-sh.h index 93fdd90..0ad914e 100644 --- a/gas/config/tc-sh.h +++ b/gas/config/tc-sh.h @@ -81,6 +81,11 @@ extern int sh_force_relocation (struct fix *); #define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section (FIX, SEC) extern long md_pcrel_from_section (struct fix *, segT); +/* SH_COUNT relocs are allowed outside of frag. + The target is also buggy and sets fix size too large for other relocs. */ +#define TC_FX_SIZE_SLACK(FIX) \ + ((FIX)->fx_r_type == BFD_RELOC_SH_COUNT ? -1 : 2) + #define IGNORE_NONSTANDARD_ESCAPES #define LISTING_HEADER \ diff --git a/gas/config/tc-xstormy16.h b/gas/config/tc-xstormy16.h index 5425874..727a496 100644 --- a/gas/config/tc-xstormy16.h +++ b/gas/config/tc-xstormy16.h @@ -63,3 +63,6 @@ extern void xstormy16_cons_fix_new (fragS *f, int, int, expressionS *); /* Minimum instruction is two bytes. */ #define DWARF2_LINE_MIN_INSN_LENGTH 2 + +/* This target is buggy, and sets fix size too large. */ +#define TC_FX_SIZE_SLACK(FIX) 2 diff --git a/gas/write.c b/gas/write.c index afce604..46549b8 100644 --- a/gas/write.c +++ b/gas/write.c @@ -97,6 +97,16 @@ #define TC_FAKE_LABEL(NAME) (strcmp ((NAME), FAKE_LABEL_NAME) == 0) #endif +/* Positive values of TC_FX_SIZE_SLACK allow a target to define + fixups that far past the end of a frag. Having such fixups + is of course most most likely a bug in setting fx_size correctly. + A negative value disables the fixup check entirely, which is + appropriate for something like the Renesas / SuperH SH_COUNT + reloc. */ +#ifndef TC_FX_SIZE_SLACK +#define TC_FX_SIZE_SLACK(FIX) 0 +#endif + /* Used to control final evaluation of expressions. */ int finalize_syms = 0; @@ -1017,6 +1027,8 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED) { arelent *reloc; bfd_reloc_status_type s; + int fx_size, slack; + offsetT loc; if (fixp->fx_done) { @@ -1031,12 +1043,15 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED) continue; } - /* - This test is triggered inappropriately for the SH: - if (fixp->fx_where + fixp->fx_size - > fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset) - abort (); - */ + fx_size = fixp->fx_size; + slack = TC_FX_SIZE_SLACK (fixp); + if (slack > 0) + fx_size = fx_size > slack ? fx_size - slack : 0; + loc = fixp->fx_where + fx_size; + if (slack >= 0 + && loc > fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset) + as_bad_where (fixp->fx_file, fixp->fx_line, + _("internal error: fixup not contained within frag")); s = bfd_install_relocation (stdoutput, reloc, fixp->fx_frag->fr_literal, @@ -1071,6 +1086,8 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED) arelent **reloc; bfd_reloc_status_type s; int j; + int fx_size, slack; + offsetT loc; if (fixp->fx_done) { @@ -1085,10 +1102,17 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED) relocs[i++] = reloc[j]; assert (i <= n); } - if (fixp->fx_where + fixp->fx_size - > fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset) + + fx_size = fixp->fx_size; + slack = TC_FX_SIZE_SLACK (fixp); + if (slack > 0) + fx_size = fx_size > slack ? fx_size - slack : 0; + loc = fixp->fx_where + fx_size; + if (slack >= 0 + && loc > fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset) as_bad_where (fixp->fx_file, fixp->fx_line, _("internal error: fixup not contained within frag")); + for (j = 0; reloc[j]; j++) { s = bfd_install_relocation (stdoutput, reloc[j], |