This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Mach-O]: Fix crash while reading non-scattered pair relocations


Hi,

the symnum field of a non-scattered PAIR is 0xffffff, while it should be a section number for other non-scattered relocations.  To avoid an assertion failure (or a crash), we need to specifically handle this special value in the generic code.  Target specific swap routines have to adjust, if necessary.

Committed on trunk.

Tristan.

bfd/
2012-11-14  Tristan Gingold  <gingold@adacore.com>

	* mach-o.c (bfd_mach_o_canonicalize_one_reloc): Add a special
	handling for non-scattered pairs.  Update comments.

Index: mach-o.c
===================================================================
RCS file: /cvs/src/src/bfd/mach-o.c,v
retrieving revision 1.105
diff -c -r1.105 mach-o.c
*** mach-o.c	6 Nov 2012 06:44:01 -0000	1.105
--- mach-o.c	14 Nov 2012 10:28:37 -0000
***************
*** 1018,1024 ****
    addr = bfd_get_32 (abfd, raw->r_address);
    res->sym_ptr_ptr = NULL;
    res->addend = 0;
!   
    if (addr & BFD_MACH_O_SR_SCATTERED)
      {
        unsigned int j;
--- 1018,1024 ----
    addr = bfd_get_32 (abfd, raw->r_address);
    res->sym_ptr_ptr = NULL;
    res->addend = 0;
! 
    if (addr & BFD_MACH_O_SR_SCATTERED)
      {
        unsigned int j;
***************
*** 1056,1077 ****
    else
      {
        unsigned int num;
!       
        /* Non-scattered relocation.  */
        reloc.r_scattered = 0;
!       
        /* The value and info fields have to be extracted dependent on target
           endian-ness.  */
        bfd_mach_o_swap_in_non_scattered_reloc (abfd, &reloc, raw->r_symbolnum);
        num = reloc.r_value;
  
        if (reloc.r_extern)
!           sym = syms + num;
!       else if (reloc.r_scattered
! 	       || (reloc.r_type != BFD_MACH_O_GENERIC_RELOC_PAIR))
          {
            BFD_ASSERT (num != 0);
            BFD_ASSERT (num <= mdata->nsects);
            sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr;
            /* For a symbol defined in section S, the addend (stored in the
               binary) contains the address of the section.  To comply with
--- 1056,1090 ----
    else
      {
        unsigned int num;
! 
        /* Non-scattered relocation.  */
        reloc.r_scattered = 0;
! 
        /* The value and info fields have to be extracted dependent on target
           endian-ness.  */
        bfd_mach_o_swap_in_non_scattered_reloc (abfd, &reloc, raw->r_symbolnum);
        num = reloc.r_value;
  
        if (reloc.r_extern)
! 	{
! 	  /* An external symbol number.  */
! 	  sym = syms + num;
! 	}
!       else if (num == 0x00ffffff)
! 	{
! 	  /* The 'symnum' in a non-scattered PAIR is 0x00ffffff.  But as this
! 	     is generic code, we don't know wether this is really a PAIR.
! 	     This value is almost certainly not a valid section number, hence
! 	     this specific case to avoid an assertion failure.
! 	     Target specific swap_reloc_in routine should adjust that.  */
! 	  sym = bfd_abs_section_ptr->symbol_ptr_ptr;
! 	}
!       else
          {
+ 	  /* A section number.  */
            BFD_ASSERT (num != 0);
            BFD_ASSERT (num <= mdata->nsects);
+ 
            sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr;
            /* For a symbol defined in section S, the addend (stored in the
               binary) contains the address of the section.  To comply with
***************
*** 1080,1105 ****
               the vma of the section.  */
            res->addend = -mdata->sections[num - 1]->addr;
          }
!       else /* ... The 'symnum' in a non-scattered PAIR will be 0x00ffffff.  */
!         {
!           /* Pairs for PPC LO/HI/HA are not scattered, but contain the offset
!              in the lower 16bits of the address value.  So we have to find the
!              'symbol' from the preceding reloc.  We do this even thoough the
!              section symbol is probably not needed here, because NULL symbol
!              values cause an assert in generic BFD code.  */
!           sym = (res - 1)->sym_ptr_ptr;
!         }
        res->sym_ptr_ptr = sym;
!       
        /* The 'address' is just r_address.
           ??? maybe this should be masked with  0xffffff for safety.  */
        res->address = addr;
        reloc.r_address = addr;
      }
!   
!   /* We have set up a reloc with all the information present, so the swapper can
!      modify address, value and addend fields, if necessary, to convey information
!      in the generic BFD reloc that is mach-o specific.  */
  
    if (!(*bed->_bfd_mach_o_swap_reloc_in)(res, &reloc))
      return -1;
--- 1093,1115 ----
               the vma of the section.  */
            res->addend = -mdata->sections[num - 1]->addr;
          }
!       /* Note: Pairs for PPC LO/HI/HA are not scattered, but contain the offset
! 	 in the lower 16bits of the address value.  So we have to find the
! 	 'symbol' from the preceding reloc.  We do this even though the
! 	 section symbol is probably not needed here, because NULL symbol
! 	 values cause an assert in generic BFD code.  This must be done in
! 	 the PPC swap_reloc_in routine.  */
        res->sym_ptr_ptr = sym;
! 
        /* The 'address' is just r_address.
           ??? maybe this should be masked with  0xffffff for safety.  */
        res->address = addr;
        reloc.r_address = addr;
      }
! 
!   /* We have set up a reloc with all the information present, so the swapper
!      can modify address, value and addend fields, if necessary, to convey
!      information in the generic BFD reloc that is mach-o specific.  */
  
    if (!(*bed->_bfd_mach_o_swap_reloc_in)(res, &reloc))
      return -1;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]