From a65b844aed9153789356e098984452df2f5d9058 Mon Sep 17 00:00:00 2001
From: Claudiu Zissulescu <claziss@synopsys.com>
Date: Tue, 4 Aug 2015 12:53:11 +0200
Subject: [PATCH] Check to see if the input BFD actually contains any sections.

---
 bfd/elf32-arc.c   | 70 +++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 47 insertions(+), 23 deletions(-)

diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c
index 38f72b4..76bac6c 100644
--- a/bfd/elf32-arc.c
+++ b/bfd/elf32-arc.c
@@ -881,44 +881,68 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 {
   unsigned short mach_ibfd;
   static unsigned short mach_obfd = EM_NONE;
-  flagword old_flags;
-  flagword new_flags;
+  flagword out_flags;
+  flagword in_flags;
+  asection *sec;
+
+   /* Check if we have the same endianess.  */
+  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
+    {
+      _bfd_error_handler (
+			  _("ERROR: Endian Match failed . Attempting to link %B with binary %s \
+of opposite endian-ness"),
+			  ibfd, bfd_get_filename (obfd));
+      return FALSE;
+    }
 
   /* Collect ELF flags. */
-  new_flags = elf_elfheader (ibfd)->e_flags & EF_ARC_MACH_MSK;
-  old_flags = elf_elfheader (obfd)->e_flags & EF_ARC_MACH_MSK;
+  in_flags = elf_elfheader (ibfd)->e_flags & EF_ARC_MACH_MSK;
+  out_flags = elf_elfheader (obfd)->e_flags & EF_ARC_MACH_MSK;
 
 #if DEBUG
-  (*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
-			 old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
+  (*_bfd_error_handler) ("out_flags = 0x%.8lx, in_flags = 0x%.8lx, init = %s, filename = %s",
+			 out_flags, in_flags, elf_flags_init (obfd) ? "yes" : "no",
 			 bfd_get_filename (ibfd));
 #endif
 
   if (!elf_flags_init (obfd))			/* First call, no flags set.  */
     {
       elf_flags_init (obfd) = TRUE;
-      old_flags = new_flags;
+      out_flags = in_flags;
     }
 
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return TRUE;
 
-  if (bfd_count_sections (ibfd) == 0)
-    return TRUE ; /* For the case of empty archive files */
+  /* Check to see if the input BFD actually contains any sections.  If
+     not, its flags may not have been initialised either, but it
+     cannot actually cause any incompatiblity.  Do not short-circuit
+     dynamic objects; their section list may be emptied by
+     elf_link_add_object_symbols.  */
+  if (!(ibfd->flags & DYNAMIC))
+    {
+      bfd_boolean null_input_bfd = TRUE;
+      bfd_boolean only_data_sections = TRUE;
 
-  mach_ibfd = elf_elfheader (ibfd)->e_machine;
+      for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+	{
+	  if ((bfd_get_section_flags (ibfd, sec)
+	       & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
+	      == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
+	    only_data_sections = FALSE;
 
-   /* Check if we have the same endianess.  */
-  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
-    {
-      _bfd_error_handler (_("\
-ERROR: Endian Match failed . Attempting to link %B with binary %s \
-of opposite endian-ness"),
-			  ibfd, bfd_get_filename (obfd));
-      return FALSE;
+	  null_input_bfd = FALSE;
+	  break;
+	}
+
+      if (null_input_bfd || only_data_sections)
+	return TRUE;
     }
 
+
+  /* Complain about various flag/architecture mismatches.  */
+  mach_ibfd = elf_elfheader (ibfd)->e_machine;
   if (mach_obfd == EM_NONE)
     {
       mach_obfd = mach_ibfd;
@@ -932,23 +956,23 @@ with a binary %s of different architecture"),
 			      ibfd, bfd_get_filename (obfd));
 	  return FALSE;
 	}
-      else if (new_flags != old_flags)
+      else if (in_flags != out_flags)
 	{
 	  /* Warn if different flags. */
 	  (*_bfd_error_handler)
 	    (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
-	     bfd_get_filename (ibfd), (long)new_flags, (long)old_flags);
-	  if (new_flags && old_flags)
+	     bfd_get_filename (ibfd), (long)in_flags, (long)out_flags);
+	  if (in_flags && out_flags)
 	    return FALSE;
 	  /* MWDT doesnt set the eflags hence make sure we choose the
 	     eflags set by gcc.  */
-	  new_flags = new_flags > old_flags ? new_flags : old_flags;
+	  in_flags = in_flags > out_flags ? in_flags : out_flags;
 	}
 
     }
 
   /* Update the flags. */
-  elf_elfheader (obfd)->e_flags = new_flags;
+  elf_elfheader (obfd)->e_flags = in_flags;
 
   if (bfd_get_mach (obfd) < bfd_get_mach (ibfd))
     {
-- 
2.4.3

