Bug 12339

Summary: Invalid .rel.plt section data is generated when a linked symbol is warning symbol (ELF32, ARM only)
Product: binutils Reporter: J. Park <grassman>
Component: ldAssignee: Alan Modra <amodra>
Status: RESOLVED FIXED    
Severity: normal CC: amodra
Priority: P2    
Version: unspecified   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:

Description J. Park 2010-12-22 13:24:47 UTC
A couple of days ago I found a program (dropbear - SSH server) generating segfault. I examined that program and found .rel.plt section was broken.
After two days of bug tracking, I found the following bug and report it now.

When an elf32_arm_link_hash_entry is defined as bfd_link_hash_warning,
the first thing to do before accessing it is finding the hidden 'real'
entry. But 'allocate_dynrelocs' function does not. The variable 'eh'
is not referencing the 'real' entry. This results in an invalid 'eh->plt_got_offset' value (under my cross-compile environment).
After fixing this code, everything seems fine.

bfd/elf32-arm.c file
---------------------------------------------------------------------------

static bfd_boolean
allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
{
  struct bfd_link_info *info;
  struct elf32_arm_link_hash_table *htab;
  struct elf32_arm_link_hash_entry *eh;
  struct elf_dyn_relocs *p;
  bfd_signed_vma thumb_refs;

  eh = (struct elf32_arm_link_hash_entry *) h;   /* <- THIS IS THE PROBLEM */

  if (h->root.type == bfd_link_hash_indirect)
    return TRUE;

  if (h->root.type == bfd_link_hash_warning)
    /* When warning symbols are created, they **replace** the "real"
       entry in the hash table, thus we never get to see the real
       symbol in a hash traversal.  So look at it now.  */
    h = (struct elf_link_hash_entry *) h->root.u.i.link;

  // <- PLEASE MOVE THE ABOVE LINE HERE

---------------------------------------------------------------------------

In addition to above problem, ld doesn't list warning symbols in the map file.
Is it intended? If not, please add the following two lines to the beginning of 'sort_def_symbol' function (ld/ldlang.c file).

  if (hash_entry->type == bfd_link_hash_warning)
    hash_entry = (struct bfd_link_hash_entry *) hash_entry->u.i.link;
Comment 1 Alan Modra 2011-01-12 13:47:27 UTC
Both of your proposed changes are good.
Comment 2 Sourceware Commits 2011-01-14 02:18:02 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	amodra@sourceware.org	2011-01-14 02:17:58

Modified files:
	bfd            : ChangeLog elf32-arm.c 

Log message:
	PR ld/12339
	* elf32-arm.c (allocate_dynrelocs): Don't set up eh before
	following bfd_link_hash_warning symbol link.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/ChangeLog.diff?cvsroot=src&r1=1.5227&r2=1.5228
http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elf32-arm.c.diff?cvsroot=src&r1=1.253&r2=1.254
Comment 3 Sourceware Commits 2011-01-14 02:18:25 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	amodra@sourceware.org	2011-01-14 02:18:22

Modified files:
	ld             : ChangeLog ldlang.c 

Log message:
	PR ld/12339
	* ldlang.c (sort_def_symbol): Handle bfd_link_hash_warning symbols.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/ChangeLog.diff?cvsroot=src&r1=1.2271&r2=1.2272
http://sourceware.org/cgi-bin/cvsweb.cgi/src/ld/ldlang.c.diff?cvsroot=src&r1=1.359&r2=1.360
Comment 4 Alan Modra 2011-01-14 03:01:25 UTC
patched
Comment 5 J. Park 2011-01-18 11:30:27 UTC
Thank you :)