diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index cb658483ca6..77ff4d63381 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -11495,6 +11495,114 @@ xtensa_callback_required_dependence (bfd
*abfd,
   return ok;
 }
 
+static void
+xtensa_info_set_entry (char *key, int value, xtensa_info_entries
*entries)
+{
+  if (! strcmp (key, "ABI"))
+    {
+      entries->abi = value;
+    }
+  else if (! strcmp (key, "USE_ABSOLUTE_LITERALS"))
+    {
+      entries->use_absolute_literals = value;
+    }
+}
+
+static bool
+xtensa_info_parse (char *data, xtensa_info_entries *entries)
+{
+  char *d, *key;
+
+  d = data;
+  while (*d)
+    {
+      key = d;
+      d = strchr (d, '=');
+      if (! d)
+        goto error;
+
+      /* Overwrite the equal sign.  */
+      *d++ = 0;
+
+      /* Check if this is a quoted string or a number.  */
+      if (*d == '"')
+        {
+          /* No string values are currently checked by LD;
+             just skip over the quotes.  */
+          d++;
+          d = strchr (d, '"');
+          if (! d)
+            goto error;
+          /* Skip the trailing quote.  */
+          d++;
+        }
+      else if( *d >= '0' && *d <= '9' )
+        {
+          int value = strtoul (d, &d, 0);
+          xtensa_info_set_entry (key, value, entries);
+        }
+      else
+        goto error;
+
+      if (*d++ != '\n')
+        goto error;
+    }
+
+  return true;
+
+error:
+  return false;
+}
+
+bool
+read_xtensa_info (bfd *abfd, asection *info_sec, xtensa_info_entries
*entries)
+{
+  bool ret = false;
+  char *data = (char *) bfd_malloc (info_sec->size);
+
+  /* initialize values  */
+  entries->abi = XSHAL_ABI;
+  entries->use_absolute_literals = XSHAL_USE_ABSOLUTE_LITERALS;
+
+  if (! bfd_get_section_contents (abfd, info_sec, data, 0, info_sec-
>size))
+    {
+      fprintf (stderr, _("%pB: cannot read contents of section
%pA\n"),
+               abfd, info_sec);
+      goto exit;
+    }
+
+  if (! (info_sec->size > 24
+         && info_sec->size >= 24 + bfd_get_32 (abfd, data + 4)
+         && bfd_get_32 (abfd, data + 0) == XTINFO_NAMESZ
+         && bfd_get_32 (abfd, data + 8) == XTINFO_TYPE
+         && strcmp (data + 12, XTINFO_NAME) == 0
+         && xtensa_info_parse (data + 12 + XTINFO_NAMESZ, entries)
+        )
+     )
+    {
+      fprintf (stderr,
+               _("%pB: warning: cannot parse .xtensa.info section\n"),
+               abfd);
+      goto exit;
+    }
+
+  ret = true;
+
+exit:
+  free (data);
+  return ret;
+}
+
+void
+fill_xtensa_info (char **data)
+{
+  sprintf (*data,
+           "USE_ABSOLUTE_LITERALS=%d\n"
+           "ABI=%d\n",
+           XSHAL_USE_ABSOLUTE_LITERALS,
+           xtensa_abi_choice ());
+}
+
 /* The default literal sections should always be marked as "code"
(i.e.,
    SHF_EXECINSTR).  This is particularly important for the Linux
kernel
    module loader so that the literals are not placed after the text. 
*/
diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
index 3e3deb5dd36..df6a3cec8a1 100644
--- a/gas/config/tc-xtensa.c
+++ b/gas/config/tc-xtensa.c
@@ -8982,10 +8982,6 @@ is_local_forward_loop (const TInsn *insn, fragS
*fragP)
   return false;
 }
 
-#define XTINFO_NAME "Xtensa_Info"
-#define XTINFO_NAMESZ 12
-#define XTINFO_TYPE 1
-
 static void
 xtensa_add_config_info (void)
 {
@@ -8997,8 +8993,7 @@ xtensa_add_config_info (void)
   bfd_set_section_flags (info_sec, SEC_HAS_CONTENTS | SEC_READONLY);
 
   data = XNEWVEC (char, 100);
-  sprintf (data, "USE_ABSOLUTE_LITERALS=%d\nABI=%d\n",
-	   XSHAL_USE_ABSOLUTE_LITERALS, xtensa_abi_choice ());
+  fill_xtensa_info (&data);
   sz = strlen (data) + 1;
 
   /* Add enough null terminators to pad to a word boundary.  */
diff --git a/include/elf/xtensa.h b/include/elf/xtensa.h
index 542821b0dc9..6d916f8fd64 100644
--- a/include/elf/xtensa.h
+++ b/include/elf/xtensa.h
@@ -138,6 +138,18 @@ typedef struct property_table_entry_t
   flagword flags;
 } property_table_entry;
 
+/* .xtensa.info section related definitions  */
+
+#define XTINFO_NAME "Xtensa_Info"
+#define XTINFO_NAMESZ sizeof(XTINFO_NAME)
+#define XTINFO_TYPE 1
+
+typedef struct xtensa_info_entries_t
+{
+  int abi;
+  int use_absolute_literals;
+} xtensa_info_entries;
+
 /* Flags in the property tables to specify whether blocks of memory
are
    literals, instructions, data, or unreachable.  For instructions,
    blocks that begin loop targets and branch targets are designated.
@@ -228,6 +240,12 @@ xtensa_compute_fill_extra_space
(property_table_entry *entry);
 extern int
 xtensa_abi_choice (void);
 
+extern void
+fill_xtensa_info (char **data);
+
+extern bool
+read_xtensa_info (bfd *abfd, asection *info_sec, xtensa_info_entries
*entries);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/ld/emultempl/xtensaelf.em b/ld/emultempl/xtensaelf.em
index 9d527daea95..ed2945b850d 100644
--- a/ld/emultempl/xtensaelf.em
+++ b/ld/emultempl/xtensaelf.em
@@ -312,108 +312,25 @@ elf_xtensa_after_open (void)
 }
 
 
-static bool
-xt_config_info_unpack_and_check (char *data,
-				 bool *pmismatch,
-				 char **pmsg)
+static void
+check_xtensa_info (bfd *abfd, xtensa_info_entries *entries)
 {
-  char *d, *key;
-  int num;
-
-  *pmismatch = false;
-
-  d = data;
-  while (*d)
+  /* Check ABI */
+  if (elf32xtensa_abi == XTHAL_ABI_UNDEFINED)
     {
-      key = d;
-      d = strchr (d, '=');
-      if (! d)
-	goto error;
-
-      /* Overwrite the equal sign.  */
-      *d++ = 0;
-
-      /* Check if this is a quoted string or a number.  */
-      if (*d == '"')
-	{
-	  /* No string values are currently checked by LD;
-	     just skip over the quotes.  */
-	  d++;
-	  d = strchr (d, '"');
-	  if (! d)
-	    goto error;
-	  /* Overwrite the trailing quote.  */
-	  *d++ = 0;
-	}
-      else
-	{
-	  if (*d == 0)
-	    goto error;
-	  num = strtoul (d, &d, 0);
-
-	  if (! strcmp (key, "ABI"))
-	    {
-	      if (elf32xtensa_abi == XTHAL_ABI_UNDEFINED)
-		{
-		  elf32xtensa_abi = num;
-		}
-	      else if (num != elf32xtensa_abi)
-		{
-		  *pmismatch = true;
-		  *pmsg = "ABI does not match";
-		}
-	    }
-	  else if (! strcmp (key, "USE_ABSOLUTE_LITERALS"))
-	    {
-	      if (num != XSHAL_USE_ABSOLUTE_LITERALS)
-		{
-		  *pmismatch = true;
-		  *pmsg = "incompatible use of the Extended L32R
option";
-		}
-	    }
-	}
-
-      if (*d++ != '\n')
-	goto error;
+      elf32xtensa_abi = entries->abi;
     }
-
-  return true;
-
- error:
-  return false;
-}
-
-
-#define XTINFO_NAME "Xtensa_Info"
-#define XTINFO_NAMESZ 12
-#define XTINFO_TYPE 1
-
-static void
-check_xtensa_info (bfd *abfd, asection *info_sec)
-{
-  char *data, *errmsg = "";
-  bool mismatch;
-
-  data = xmalloc (info_sec->size);
-  if (! bfd_get_section_contents (abfd, info_sec, data, 0, info_sec-
>size))
-    einfo (_("%F%P: %pB: cannot read contents of section %pA\n"),
abfd, info_sec);
-
-  if (info_sec->size > 24
-      && info_sec->size >= 24 + bfd_get_32 (abfd, data + 4)
-      && bfd_get_32 (abfd, data + 0) == XTINFO_NAMESZ
-      && bfd_get_32 (abfd, data + 8) == XTINFO_TYPE
-      && strcmp (data + 12, XTINFO_NAME) == 0
-      && xt_config_info_unpack_and_check (data + 12 + XTINFO_NAMESZ,
-					  &mismatch, &errmsg))
+  else if (entries->abi != elf32xtensa_abi)
     {
-      if (mismatch)
-	einfo (_("%P: %pB: warning: incompatible Xtensa configuration
(%s)\n"),
-	       abfd, errmsg);
+      einfo (_("%P: %pB: warning: Xtensa ABI does not match\n"),
abfd);
     }
-  else
-    einfo (_("%P: %pB: warning: cannot parse .xtensa.info section\n"),
abfd);
 
-  free (data);
+  /* Check USE_ABSOLUTE_LITERALS */
+  if (entries->use_absolute_literals != XSHAL_USE_ABSOLUTE_LITERALS)
+    {
