summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDJ Delorie <dj@delorie.com>2011-05-23 19:50:38 +0000
committerDJ Delorie <dj@delorie.com>2011-05-23 19:50:38 +0000
commit24d38b419e61ac55f18e8801a272e527316d7a5d (patch)
treefd6d6ce65060bb598b19799fc37c7bb63714291c
parenta1a99f5bbfb4fd8d6e43ed434c7fd555eec9255c (diff)
downloadbinutils-redhat-24d38b419e61ac55f18e8801a272e527316d7a5d.tar.gz
* elf32-rx.c (rx_elf_object_p): When reading an RX object in, undo
the vma/lma swapping done in elf32_rx_modify_program_headers.
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/elf32-rx.c50
2 files changed, 55 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 910d8bc04b..64bdff6c93 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,8 @@
+2011-05-23 DJ Delorie <dj@redhat.com>
+
+ * elf32-rx.c (rx_elf_object_p): When reading an RX object in, undo
+ the vma/lma swapping done in elf32_rx_modify_program_headers.
+
2011-05-15 Richard Sandiford <rdsandiford@googlemail.com>
* elfxx-mips.c (_bfd_mips_elf_check_relocs): Record both local and
diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c
index d7e15a0e52..65f13b3caf 100644
--- a/bfd/elf32-rx.c
+++ b/bfd/elf32-rx.c
@@ -2947,8 +2947,58 @@ elf32_rx_machine (bfd * abfd)
static bfd_boolean
rx_elf_object_p (bfd * abfd)
{
+ int i;
+ unsigned int u;
+ Elf_Internal_Phdr *phdr = elf_tdata (abfd)->phdr;
+ int nphdrs = elf_elfheader (abfd)->e_phnum;
+ sec_ptr bsec;
+
bfd_default_set_arch_mach (abfd, bfd_arch_rx,
elf32_rx_machine (abfd));
+
+ /* For each PHDR in the object, we must find some section that
+ corresponds (based on matching file offsets) and use its VMA
+ information to reconstruct the p_vaddr field we clobbered when we
+ wrote it out. */
+ for (i=0; i<nphdrs; i++)
+ {
+ for (u=0; u<elf_tdata(abfd)->num_elf_sections; u++)
+ {
+ Elf_Internal_Shdr *sec = elf_tdata(abfd)->elf_sect_ptr[u];
+
+ if (phdr[i].p_offset <= (bfd_vma) sec->sh_offset
+ && (bfd_vma)sec->sh_offset <= phdr[i].p_offset + (phdr[i].p_filesz - 1))
+ {
+ /* Found one! The difference between the two addresses,
+ plus the difference between the two file offsets, is
+ enough information to reconstruct the lma. */
+
+ /* Example where they aren't:
+ PHDR[1] = lma fffc0100 offset 00002010 size 00000100
+ SEC[6] = vma 00000050 offset 00002050 size 00000040
+
+ The correct LMA for the section is fffc0140 + (2050-2010).
+ */
+
+ phdr[i].p_vaddr = sec->sh_addr + (sec->sh_offset - phdr[i].p_offset);
+ break;
+ }
+ }
+
+ /* We must update the bfd sections as well, so we don't stop
+ with one match. */
+ bsec = abfd->sections;
+ while (bsec)
+ {
+ if (phdr[i].p_vaddr <= bsec->lma
+ && bsec->vma <= phdr[i].p_vaddr + (phdr[i].p_filesz - 1))
+ {
+ bsec->lma = phdr[i].p_paddr + (bsec->vma - phdr[i].p_vaddr);
+ }
+ bsec = bsec->next;
+ }
+ }
+
return TRUE;
}