This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] Fix objdump output of R_SPARC_OLO10
- From: David Miller <davem at davemloft dot net>
- To: binutils at sourceware dot org
- Cc: richm at oldelvet dot org dot uk
- Date: Tue, 18 Jan 2011 20:51:05 -0800 (PST)
- Subject: [PATCH] Fix objdump output of R_SPARC_OLO10
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");
}