diff options
author | Nick Clifton <nickc@redhat.com> | 2007-10-30 15:18:29 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2007-10-30 15:18:29 +0000 |
commit | 569006e5824adcb39d114e815712b7aa3f5e136c (patch) | |
tree | 327248411133c3dd62a95c7ff69c33935c168e0f /gas/config/tc-mn10300.c | |
parent | 4e188d170a4a1c89ab9969c638a0bf5490d27984 (diff) | |
download | gdb-569006e5824adcb39d114e815712b7aa3f5e136c.zip gdb-569006e5824adcb39d114e815712b7aa3f5e136c.tar.gz gdb-569006e5824adcb39d114e815712b7aa3f5e136c.tar.bz2 |
* mn10300.h (R_MN10300_ALIGN): Define.
* reloc.c (BFD_RELOC_MN10300_ALIGN): Add.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elf-m10300.h: Handle R_MN10300_ALIGN relocs.
* mn10300_elf_relax_delete_bytes): Honour R_MN10300_ALIGN relocs.
Re-fix off by one error in comparisons.
* config/tc-mn10300.c (tc_gen_reloc): Fix test that decides when
sym_diff relocs should be generated.
(md_apply_fix): Skip R_MN10300_ALIGN relocs.
(mn10300_fix_adjustable): Do not adjust R_MN10300_ALIGN relocs.
(mn10300_handle_align): New function. Generate R_MN10300_ALIGN
relocs to record alignment requests.
* config/tc-mn10300.h (TC_FORCE_RELOCATION_SUB_SAME): Also force
R_MN10300_ALIGN relocs.
(HANDLE_ALIGN): Define. Call mn10300_handle_align.
* gas/all/gas.exp: Do not run diff1.s test for mn10300.
* ld-mn10300/mn10300.exp: Run new tests. Skip i126256 test if
a compiler is not available.
* ld-mn10300/i112045-3.s: New test.
* ld-mn10300/i112045-3.d: Expected disassembly.
* ld-mn10300/i135409.s: Rename to i135409-1.s.
* ld-mn10300/i135409.d: Rename to i135409-1.d
* ld-mn10300/i135409-2.s: New test.
* ld-mn10300/i135409-2.d: Expected symbol table.
* ld-mn10300/i36434.d: Adjust expected disassembly.
Diffstat (limited to 'gas/config/tc-mn10300.c')
-rw-r--r-- | gas/config/tc-mn10300.c | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/gas/config/tc-mn10300.c b/gas/config/tc-mn10300.c index 5ec58bb..e16a764 100644 --- a/gas/config/tc-mn10300.c +++ b/gas/config/tc-mn10300.c @@ -2181,13 +2181,18 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) if (fixp->fx_addsy && fixp->fx_subsy) { + asection *asec, *ssec; + + asec = S_GET_SEGMENT (fixp->fx_addsy); + ssec = S_GET_SEGMENT (fixp->fx_subsy); + reloc->sym_ptr_ptr = NULL; /* If we have a difference between two (non-absolute) symbols we must generate two relocs (one for each symbol) and allow the linker to resolve them - relaxation may change the distances between symbols, - even local symbols defined in the same segment. */ - if (S_GET_SEGMENT (fixp->fx_subsy) == seg) + even local symbols defined in the same section. */ + if (ssec != absolute_section || asec != absolute_section) { arelent * reloc2 = xmalloc (sizeof * reloc); @@ -2201,7 +2206,7 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) *reloc2->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy); reloc->addend = fixp->fx_offset; - if (S_GET_SEGMENT (fixp->fx_addsy) == absolute_section) + if (asec == absolute_section) reloc->addend += S_GET_VALUE (fixp->fx_addsy); reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); @@ -2211,13 +2216,6 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) fixp->fx_done = 1; return relocs; } - - if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy)) - || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section) - { - as_bad_where (fixp->fx_file, fixp->fx_line, - "Difference of symbols in different sections is not supported"); - } else { char *fixpos = fixp->fx_where + fixp->fx_frag->fr_literal; @@ -2248,12 +2246,12 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr; return relocs; } - } - if (reloc->sym_ptr_ptr) - free (reloc->sym_ptr_ptr); - free (reloc); - return & no_relocs; + if (reloc->sym_ptr_ptr) + free (reloc->sym_ptr_ptr); + free (reloc); + return & no_relocs; + } } else { @@ -2357,6 +2355,10 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) fixP->fx_done = 0; return; + case BFD_RELOC_MN10300_ALIGN: + fixP->fx_done = 1; + return; + case BFD_RELOC_NONE: default: as_bad_where (fixP->fx_file, fixP->fx_line, @@ -2562,3 +2564,29 @@ mn10300_allow_local_subtract (expressionS * left, expressionS * right, segT sect return result; } + +/* When relaxing, we need to output a reloc for any .align directive + that requests alignment to a two byte boundary or larger. */ + +void +mn10300_handle_align (fragS *frag) +{ + if (! linkrelax) + return; + + if ((frag->fr_type == rs_align + || frag->fr_type == rs_align_code) + && frag->fr_address + frag->fr_fix > 0 + && frag->fr_offset > 1 + && now_seg != bss_section + /* Do not create relocs for the merging sections - such + relocs will prevent the contents from being merged. */ + && (bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE) == 0) + /* Create a new fixup to record the alignment request. The symbol is + irrelevent but must be present so we use the absolute section symbol. + The offset from the symbol is used to record the power-of-two alignment + value. The size is set to 0 because the frag may already be aligned, + thus causing cvt_frag_to_fill to reduce the size of the frag to zero. */ + fix_new (frag, frag->fr_fix, 0, & abs_symbol, frag->fr_offset, FALSE, + BFD_RELOC_MN10300_ALIGN); +} |