This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Assertion in gas/tc_gen_reloc in dlx-elf, arc-elf, perhaps other targets under some conditions


  There's this line in tc_gen_reloc for several targets:

config/tc-alpha.c:  assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
config/tc-arc.c:  assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
config/tc-dlx.c:  assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
config/tc-i960.c:  assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);

[also in gas_cgen_tc_gen_reloc, which is referenced from tc-fr30.h,
tc-frv.h, tc-ip2k.h, tc-iq2000.h, tc-m32r.h, tc-openrisc.h and
tc-xstormy16.h] which is fired by this test case (stripped down from the
sort of jump table sequences gcc produces):

---snip---
.text
	.align 2
	.word   0
	.section	.rodata
	.align 2
.L13:
	.word .L12-.L13
	.word .L12-.L13
	.word .L4-.L13
.text
.L4:
	.word   1
.L12:
	.word   2
    .end
---snip---

on the arc and dlx targets.

  The precise condition is that we have a fixup based on the difference of
two symbols, where the fx_subsy is in the same section as the address the
fixup is targetted at, but the fx_addsy is in a different section/segment.
(Note that if the fx_addsy is in the same segment and fx_subsy is in a
different one you get an "Error: can't resolve `.rodata' {.rodata section} -
`.L12' {.text section}" message.)

  The problem is caused by the following sequence of events:

 -  cons (...) creates the four bytes for the .word directive and also a
fixup, type BFD_RELOC_32, not marked as pc-relative, with both an fx_addsy
and an fx_subsy.

 -  fixup_segment (...) decide it wants the fixup to be pc-relative, since
the fx_subsy is in the same section as the fixup target.  It decides this
because the following conditional:

	  else if (sub_symbol_segment == this_segment
		   && !TC_FORCE_RELOCATION_SUB_LOCAL (fixP))
  
is satisfied.  There's an interesting comment just below this point, in the
clause that messes with the fixup:

	      /* Make it pc-relative.  If the back-end code has not
		 selected a pc-relative reloc, cancel the adjustment
		 we do later on all pc-relative relocs.  */

So, it marks the fixup as fx_pcrel, adjusts fx_offset, and clears the
fx_subsy field.  Note however that it doesn't adjust fx_r_type.

  - Finally, tc_gen_reloc is called to emit the left-over relocations.  It
uses bfd_reloc_type_lookup on fx_r_type (which still has the value
BFD_RELOC_32) and finds the appropriate target-dependent howto struct.  But
the original r_type was set for a non-pc-relative fixup, and the
target-dependent type returned on the basis of bfd_reloc_type_lookup will
also be a non-pc-relative type; however, the fixup was marked pc-relative by
fixup_segment, and so the assertion fails because fixup->fx_pcrel !=
howto->pc_relative.


  To sum it up, the problem seems to me to be that fixup_segment does
something broken, by setting the fx_pcrel flag without adjusting the
fx_r_type to correspond to a pc-relative reloc type.  But maybe it simply
shouldn't be trying to make the fixup pc relative at all when the sum and
difference symbols come from different sections?

  i960 turns out to be immune owing to it not having defined DIFF_EXPR_OK,
and the alpha turns out to be immune owing to md_apply_fix3 changing the
fx_r_type to a different value to cause tc_gen_reloc to choose a pc-relative
howto.  I don't think either of these are going to help me out, because
disabling DIFF_EXPR_OK when the target really ought to support it seems
wrong, and changing the fx_r_type just gets me a complaint about not being
able to export a PCREL_32 type of relocation.

  I'm not sure how I should be trying to solve this problem; I can't really
reconcile a codebase that both contains the assertion above that demands
consistency between the fixup and the struct howto with the code in
fixup_segment that alters one but not the other.  Has anyone got any idea
how this is meant to work?  Searching the list archives has been less than
enlightening, except to note that a couple of people seem to have stumbled
across this or similar assertions before, but not pursued it.

  I don't really understand what fixup_segment is trying to do, nor whether
that's the same as what it's actually doing, or what it ought to be doing if
it's doing something wrong.  If anyone is more familiar with this area of
the code with me, I'd be glad for any few crumbs of clue they could scatter
in my general direction...


    cheers, 
      DaveK
-- 
Can't think of a witty .sigline today....


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]