This is the mail archive of the binutils@sourceware.org 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]

Re: Strange reloc problem in large MIPS C++ programs


Paul Koning <Paul_Koning@dell.com> writes:
> My question: does this sound like a familiar problem that was indeed
> fixed between 2.14 and 2.18?  Or does the change to 2.18 simply move
> the bug to a different point and it will bite me later?  If the
> latter, any suggestions where I should start debugging?

Yeah, this sounds like a classic case of:

  /* If we aren't adjusting this fixup to be against the section
     symbol, we need to adjust the value.  */
#ifdef OBJ_ELF
  if (fixP->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour)
    {
      if (mips_need_elf_addend_fixup (fixP))
	{
	  reloc_howto_type *howto;
	  valueT symval = S_GET_VALUE (fixP->fx_addsy);

	  value -= symval;

	  howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
	  if (value != 0 && howto && howto->partial_inplace
	      && (! fixP->fx_pcrel || howto->pcrel_offset))
	    {
	      /* In this case, the bfd_install_relocation routine will
		 incorrectly add the symbol value back in.  We just want
		 the addend to appear in the object file.

		 howto->pcrel_offset is added for R_MIPS_PC16, which is
		 generated for code like

		 	globl g1 .text
			.text
			.space 20
		 g1:
		 x:
		 	bal g1
	       */
	      value -= symval;

	      /* Make sure the addend is still non-zero.  If it became zero
		 after the last operation, set it to a spurious value and
		 subtract the same value from the object file's contents.  */
	      if (value == 0)
		{
		  value = 8;

		  /* The in-place addends for LO16 relocations are signed;
		     leave the matching HI16 in-place addends as zero.  */
		  if (fixP->fx_r_type != BFD_RELOC_HI16_S)
		    {
		      bfd_vma contents, mask, field;

		      contents = bfd_get_bits (fixP->fx_frag->fr_literal
					       + fixP->fx_where,
					       fixP->fx_size * 8,
					       target_big_endian);

		      /* MASK has bits set where the relocation should go.
			 FIELD is -value, shifted into the appropriate place
			 for this relocation.  */
		      mask = 1 << (howto->bitsize - 1);
		      mask = (((mask - 1) << 1) | 1) << howto->bitpos;
		      field = (-value >> howto->rightshift) << howto->bitpos;

		      bfd_put_bits ((field & mask) | (contents & ~mask),
				    fixP->fx_frag->fr_literal + fixP->fx_where,
				    fixP->fx_size * 8,
				    target_big_endian);
		    }
		}
	    }
	}

      /* This code was generated using trial and error and so is
	 fragile and not trustworthy.  If you change it, you should
	 rerun the elf-rel, elf-rel2, and empic testcases and ensure
	 they still pass.  */
      if (fixP->fx_pcrel || fixP->fx_subsy != NULL)
	{
	  value += fixP->fx_frag->fr_address + fixP->fx_where;

	  /* BFD's REL handling, for MIPS, is _very_ weird.
	     This gives the right results, but it can't possibly
	     be the way things are supposed to work.  */
	  if (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2
	      || S_GET_SEGMENT (fixP->fx_addsy) != undefined_section)
	    value += fixP->fx_frag->fr_address + fixP->fx_where;
	}
    }
#endif

(ah! the memories!)

It was a constant source of problems and was killed in Dec 2003.

Richard


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