[PATCH] Fix objdump output of R_SPARC_OLO10
H.J. Lu
hjl.tools@gmail.com
Wed Jan 19 04:57:00 GMT 2011
On Tue, Jan 18, 2011 at 8:51 PM, David Miller <davem@davemloft.net> wrote:
>
> This bug in relocation reporting on sparc has bitten me at least
> twice, and just recently has sent several folks on a wild goose chase
> again.
>
> R_SPARC_OLO10 relocations exist only on 64-bit sparc, and use the
> extra bits in the R_INFO field of the relocation to store a second,
> constant, 24-bit signed addend.
>
> BFD internally does not have enough space to store two addends in
> it's 'arelent' structure.
>
> Therefore, the 64-bit ELF Sparc backend transforms every R_SPARC_OLO10
> relocation into a sequence of two BFD internal relocs:
>
> R_SPARC_LO10
> R_SPARC_13
>
> both pointing at the same address.
>
> The primary addend of the R_SPARC_OLO10 relocation is stored in the
> R_SPARC_LO10 reloc, and the second addend is stored in the R_SPARC_13
> reloc.
>
> This internal transformed form is therefore what 'objdump' ends up
> reporting. Being a full mis-representation of what's actually in the
> binary, it will confuse and has confused developers trying to use
> objdump to analyze binaries.
>
> 'readelf' handles it properly, by way of not using BFD along with some
> sparc specific tests.
>
> On the one hand the fix I'm proposing here is a bit of a hack, but on
> the other hand it's the best thing I've been able to come up with and
> this bug has wasted developer time unnecessarily.
>
> Any better ideas?
>
> binutils/
>
> 2011-01-18 David S. Miller <davem@sunset.davemloft.net>
>
> * objdump.c (dump_reloc_set): Output R_SPARC_OLO10 relocations
> accurately, rather than how they are represented internally.
>
> diff --git a/binutils/objdump.c b/binutils/objdump.c
> index 0be662f..99d1279 100644
> --- a/binutils/objdump.c
> +++ b/binutils/objdump.c
> @@ -2829,6 +2829,7 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount)
> unsigned int linenumber;
> const char *sym_name;
> const char *section_name;
> + bfd_vma addend2 = 0;
>
> if (start_address != (bfd_vma) -1
> && q->address < start_address)
> @@ -2884,7 +2885,34 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount)
> if (q->howto == NULL)
> printf (" *unknown* ");
> else if (q->howto->name)
> - printf (" %-16s ", q->howto->name);
> + {
> + const char *name = q->howto->name;
> +
> + /* R_SPARC_OLO10 relocations contain two addends.
> + But because 'arelent' lacks enough storage to
> + store them both, the 64-bit ELF Sparc backend
> + records this as two relocations. One R_SPARC_LO10
> + and one R_SPARC_13, both pointing to the same
> + address. This is merely so that we have some
> + place to store both addend fields.
> +
> + Undo this transformation, otherwise the output
> + will be confusing. */
> + if (relcount
> + && !strcmp (q->howto->name, "R_SPARC_LO10"))
> + {
> + arelent *q2 = *(p + 1);
> + if (q2->howto
> + && q->address == q2->address
> + && !strcmp (q2->howto->name, "R_SPARC_13"))
> + {
> + name = "R_SPARC_OLO10";
> + addend2 = q2->addend;
> + p++;
> + }
> + }
> + printf (" %-16s ", name);
> + }
> else
> printf (" %-16d ", q->howto->type);
>
> @@ -2904,6 +2932,11 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount)
> printf ("+0x");
> bfd_printf_vma (abfd, q->addend);
> }
> + if (addend2)
> + {
> + printf ("+0x");
> + bfd_printf_vma (abfd, addend2);
> + }
>
> printf ("\n");
> }
>
Are you checking R_SPARC_LO10 even on x86 input?
--
H.J.
More information about the Binutils
mailing list