This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: Strange reloc problem in large MIPS C++ programs
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: Paul Koning <Paul_Koning at dell dot com>
- Cc: binutils at sourceware dot org
- Date: Fri, 27 Jun 2008 23:06:54 +0100
- Subject: Re: Strange reloc problem in large MIPS C++ programs
- References: <18533.18626.152768.552096@gargle.gargle.HOWL>
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