This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH, bfin] Clear relocs for removed entries in .eh_frame section
- From: "Jie Zhang" <jzhang918 at gmail dot com>
- To: binutils at sourceware dot org
- Cc: "Alexandre Oliva" <aoliva at redhat dot com>, "Bernd Schmidt" <bernds_cb1 at t-online dot de>, "Alan Modra" <amodra at bigpond dot net dot au>
- Date: Wed, 26 Apr 2006 11:45:19 +0800
- Subject: [PATCH, bfin] Clear relocs for removed entries in .eh_frame section
When debugging a C++ exception unwinding issue for Blackfin FDPIC
format, I found a bug of Blackfin BFD FDPIC support. When linking,
duplicate CIE will be removed from output .eh_frame section. But the
relocations for them are not. When dynamic linker does these
relocations, some contents in .eh_frame will be wrongly modified. This
causes the exception unwinding failure. I attached a patch for it. But
there are several points I'm not sure:
1. I saw this in elflink.c:elf_link_input_bfd ()
/* This is a reloc for a deleted entry or somesuch.
Turn it into an R_*_NONE reloc, at the same
offset as the last reloc. elf_eh_frame.c and
elf_bfd_discard_info rely on reloc offsets
being ordered. */
In my patch I just set the offset to zero. It seems works. I don't
know if we need do the same.
Alan: The comment was from you. Can you help me understand it?
2. In bfinfdpic_relocate_section () there are several calls to
_bfd_elf_section_offset () before calling _bfinfdpic_add_dyn_reloc ().
Only in one place the return value of _bfd_elf_section_offset () is
checked in my patch. It seems works. But I'm not sure if we need add
such check for all these calls.
3. Is it possible to not emit the reloc instead of set its type to R_*_NONE?
Alex: I think FRV has the same issue. In the lasted release of
redhat's frv toolchain from redhat's ftp, the bug is hidden since all
dupilicated CIEs are not optimized away because there is CIE format
incompatibility between gcc (3.4) and binutils (2.14).
Thanks,
Jie
Index: elf32-bfin.c
===================================================================
RCS file: /cvsroot/gcc3/binutils/binutils-2.15/bfd/elf32-bfin.c,v
retrieving revision 1.35
diff -u -p -r1.35 elf32-bfin.c
--- elf32-bfin.c 6 Apr 2006 05:48:02 -0000 1.35
+++ elf32-bfin.c 24 Apr 2006 10:46:44 -0000
@@ -2476,6 +2481,8 @@ bfinfdpic_relocate_section (bfd * output
input_section->output_section)
& (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
{
+ bfd_vma offset;
+
if (_bfinfdpic_osec_readonly_p (output_bfd,
input_section
->output_section))
@@ -2486,15 +2493,23 @@ bfinfdpic_relocate_section (bfd * output
name, input_bfd, input_section, rel->r_offset);
return FALSE;
}
- _bfinfdpic_add_dyn_reloc (output_bfd,
- bfinfdpic_gotrel_section (info),
- _bfd_elf_section_offset
- (output_bfd, info,
- input_section, rel->r_offset)
- + input_section
- ->output_section->vma
- + input_section->output_offset,
- r_type, dynindx, addend, picrel);
+ offset = _bfd_elf_section_offset (output_bfd, info,
+ input_section, rel->r_offset);
+ /* Only output a reloc for a not deleted entry. */
+ if (offset >= (bfd_vma) -2)
+ _bfinfdpic_add_dyn_reloc (output_bfd,
+ bfinfdpic_gotrel_section (info),
+ 0,
+ R_unused0,
+ dynindx, addend, picrel);
+ else
+ _bfinfdpic_add_dyn_reloc (output_bfd,
+ bfinfdpic_gotrel_section (info),
+ offset + input_section
+ ->output_section->vma
+ + input_section->output_offset,
+ r_type,
+ dynindx, addend, picrel);
}
else
addend += bfinfdpic_got_section (info)->output_section->vma;