This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: Finding BFD bug
- From: pladow at pullman dot com
- To: binutils at sources dot redhat dot com
- Date: Fri, 11 Jun 2004 20:03:25 GMT
- Subject: Re: Finding BFD bug
> "Ian Lance Taylor" <ian@wasabisystems.com> writes:
> pladow@pullman.com writes:
>
> > Well, my above statement has been proven wrong. The changes to src_msk
and
> > partial_inplace fixed the external symbol problem. Now a problem appears
in
> > the opposite case: local symbols (which worked before). Now all local
> > symbols have their offsets zerod. Again, this only happens in the data
> > section. Any references to symbols, local or external, are fine in the
text
> > section.
>
> At a guess, the assembler is not putting the required addend in the
> relocations against .data. Why it is not doing that I do not know.
> Those relocs are going through adjust_reloc_syms() in gas. But they
> should already have fx_addnumber set at that point, I think, and it
> should also be set before tc_gen_reloc() is called. It's really a
> black art, unfortunately.
Following on what you wrote, I did some suring. Especially useful was the
mention of fx_addnumber. In the gas internals texi it mentions that this is
used only between md_apply_fix and tc_gen_reloc. I looked in md_apply_fix3()
in tc-microblaze and found something that I think may be the source of the
problem.
char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
<intermediate stuff snipped>
switch (fixP->fx_r_type)
{
<bunch of other cases snipped>
case BFD_RELOC_32:
case BFD_RELOC_RVA:
case BFD_RELOC_32_PCREL:
case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
/* Don't do anything if the symbol is not defined */
if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy)) {
if (target_big_endian)
{
buf[0] |= ((val >> 24) & 0xff);
buf[1] |= ((val >> 16) & 0xff);
buf[2] |= ((val >> 8) & 0xff);
buf[3] |= (val & 0xff);
}
else
{
buf[3] |= ((val >> 24) & 0xff);
buf[2] |= ((val >> 16) & 0xff);
buf[1] |= ((val >> 8) & 0xff);
buf[0] |= (val & 0xff);
}
} else if (!fixP->fx_pcrel) {
fixP->fx_addnumber = val;
}
break;
<more cases snipped>
default:
break;
}
It seems to be embeddeding the offsets here, but only if the symbol is
undefined. Hence the external differences from the local.
My solution as to apply the changes to the HOWTO mentioned earlier (i.e.
src_mask of 0 and partial_inplace to false) and to change the above case
statement to:
char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
switch (fixP->fx_r_type)
{
<bunch of other cases snipped>
case BFD_RELOC_32:
case BFD_RELOC_RVA:
case BFD_RELOC_32_PCREL:
case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
if (target_big_endian)
{
buf[0] |= ((val >> 24) & 0xff);
buf[1] |= ((val >> 16) & 0xff);
buf[2] |= ((val >> 8) & 0xff);
buf[3] |= (val & 0xff);
}
else
{
buf[3] |= ((val >> 24) & 0xff);
buf[2] |= ((val >> 16) & 0xff);
buf[1] |= ((val >> 8) & 0xff);
buf[0] |= (val & 0xff);
}
if (!fixP->fx_pcrel) {
fixP->fx_addnumber = val;
}
break
<more cases snipped>
default:
break;
}
After applying these changes, I see the relocs in 'objdump -r', and also the
embedded offsets in 'objdump -s'. Changing the src_mask to 0 nukes the
embedded offsets and uses the relocs instead. What I'd like to do is have the
embedded offsets to zero and then I can leave the HOWTO alone.
But I mucked around enough and have something working. I just thought perhaps
some comments on the above code could shed some light on the "right way" to
fix the problem.
Thanks,
Pete
---------------------------------------------
This message was sent by First Step Internet.
http://www.fsr.net/