daily update
[deliverable/binutils-gdb.git] / bfd / mach-o.c
index 84d5a72960f0a009d1504590df596821e1e604a8..e44cf6d4c58486dc8bcf0421655c10dd269b3672 100644 (file)
@@ -1018,7 +1018,7 @@ bfd_mach_o_canonicalize_one_reloc (bfd *abfd,
   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,22 +1056,35 @@ bfd_mach_o_canonicalize_one_reloc (bfd *abfd,
   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))
+       {
+         /* 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,26 +1093,23 @@ bfd_mach_o_canonicalize_one_reloc (bfd *abfd,
              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;
-        }
+      /* 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.  */
+
+  /* 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;
@@ -3656,6 +3666,48 @@ bfd_mach_o_read_encryption_info (bfd *abfd, bfd_mach_o_load_command *command)
   return TRUE;
 }
 
+static bfd_boolean
+bfd_mach_o_read_main (bfd *abfd, bfd_mach_o_load_command *command)
+{
+  bfd_mach_o_main_command *cmd = &command->command.main;
+  struct mach_o_entry_point_command_external raw;
+
+  if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0
+      || bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
+    return FALSE;
+
+  cmd->entryoff = bfd_get_64 (abfd, raw.entryoff);
+  cmd->stacksize = bfd_get_64 (abfd, raw.stacksize);
+  return TRUE;
+}
+
+static bfd_boolean
+bfd_mach_o_read_source_version (bfd *abfd, bfd_mach_o_load_command *command)
+{
+  bfd_mach_o_source_version_command *cmd = &command->command.source_version;
+  struct mach_o_source_version_command_external raw;
+  bfd_uint64_t ver;
+
+  if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0
+      || bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
+    return FALSE;
+
+  ver = bfd_get_64 (abfd, raw.version);
+  /* Note: we use a serie of shift to avoid shift > 32 (for which gcc
+     generates warnings) in case of the host doesn't support 64 bit
+     integers.  */
+  cmd->e = ver & 0x3ff;
+  ver >>= 10;
+  cmd->d = ver & 0x3ff;
+  ver >>= 10;
+  cmd->c = ver & 0x3ff;
+  ver >>= 10;
+  cmd->b = ver & 0x3ff;
+  ver >>= 10;
+  cmd->a = ver & 0xffffff;
+  return TRUE;
+}
+
 static int
 bfd_mach_o_read_segment (bfd *abfd,
                          bfd_mach_o_load_command *command,
@@ -3832,6 +3884,8 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command)
     case BFD_MACH_O_LC_CODE_SIGNATURE:
     case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
     case BFD_MACH_O_LC_FUNCTION_STARTS:
+    case BFD_MACH_O_LC_DATA_IN_CODE:
+    case BFD_MACH_O_LC_DYLIB_CODE_SIGN_DRS:
       if (bfd_mach_o_read_linkedit (abfd, command) != 0)
        return -1;
       break;
@@ -3848,6 +3902,14 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command)
       if (!bfd_mach_o_read_version_min (abfd, command))
        return -1;
       break;
+    case BFD_MACH_O_LC_MAIN:
+      if (!bfd_mach_o_read_main (abfd, command))
+       return -1;
+      break;
+    case BFD_MACH_O_LC_SOURCE_VERSION:
+      if (!bfd_mach_o_read_source_version (abfd, command))
+       return -1;
+      break;
     default:
       (*_bfd_error_handler)(_("%B: unknown load command 0x%lx"),
          abfd, (unsigned long) command->type);
@@ -4294,7 +4356,7 @@ bfd_mach_o_fat_member_init (bfd *abfd,
       abfd->filename = name;
     }
 
-  areltdata = bfd_zalloc (abfd, sizeof (struct areltdata));
+  areltdata = bfd_zmalloc (sizeof (struct areltdata));
   areltdata->parsed_size = entry->size;
   abfd->arelt_data = areltdata;
   abfd->iostream = NULL;
@@ -4864,6 +4926,9 @@ bfd_mach_o_close_and_cleanup (bfd *abfd)
         }
     }
 
+  if (bfd_get_format (abfd) == bfd_archive
+      && abfd->xvec == &mach_o_fat_vec)
+    return TRUE;
   return _bfd_generic_close_and_cleanup (abfd);
 }
 
This page took 0.025791 seconds and 4 git commands to generate.