[binutils-gdb] Sync libiberty sources with gcc master version

Nick Clifton nickc@sourceware.org
Wed Jan 7 11:33:14 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8872d02b0f1216d12bdc34a4b5e71157b4e1aa25

commit 8872d02b0f1216d12bdc34a4b5e71157b4e1aa25
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed Jan 7 11:33:07 2026 +0000

    Sync libiberty sources with gcc master version

Diff:
---
 include/demangle.h                    |   8 +-
 include/libiberty.h                   |  10 +-
 libiberty/ChangeLog                   |  54 ++++
 libiberty/Makefile.in                 |   1 -
 libiberty/acinclude.m4                |   2 +-
 libiberty/aclocal.m4                  |   1 -
 libiberty/configure                   |   5 -
 libiberty/cp-demangle.c               |  65 ++++-
 libiberty/simple-object-coff.c        | 459 ++++++++++++++++++++++++++++------
 libiberty/simple-object-mach-o.c      |  25 +-
 libiberty/testsuite/demangle-expected |   7 +
 11 files changed, 515 insertions(+), 122 deletions(-)

diff --git a/include/demangle.h b/include/demangle.h
index 7e01a116f91..e9165d6b083 100644
--- a/include/demangle.h
+++ b/include/demangle.h
@@ -64,14 +64,14 @@ extern "C" {
 /* Disable a limit on the depth of recursion in mangled strings.
    Note if this limit is disabled then stack exhaustion is possible when
    demangling pathologically complicated strings.  Bug reports about stack
-   exhaustion when the option is enabled will be rejected.  */  
-#define DMGL_NO_RECURSE_LIMIT (1 << 18)	
+   exhaustion when the option is enabled will be rejected.  */
+#define DMGL_NO_RECURSE_LIMIT (1 << 18)
 
 /* If DMGL_NO_RECURSE_LIMIT is not enabled, then this is the value used as
    the maximum depth of recursion allowed.  It should be enough for any
    real-world mangled name.  */
 #define DEMANGLE_RECURSION_LIMIT 2048
-  
+
 /* Enumeration of possible demangling styles.
 
    Lucid and ARM styles are still kept logically distinct, even though
@@ -435,6 +435,8 @@ enum demangle_component_type
   DEMANGLE_COMPONENT_DEFAULT_ARG,
   /* An unnamed type.  */
   DEMANGLE_COMPONENT_UNNAMED_TYPE,
+  /* An unnamed enum.  */
+  DEMANGLE_COMPONENT_UNNAMED_ENUM,
   /* A transactional clone.  This has one subtree, the encoding for
      which it is providing alternative linkage.  */
   DEMANGLE_COMPONENT_TRANSACTION_CLONE,
diff --git a/include/libiberty.h b/include/libiberty.h
index 7960d802b66..1af4fa86101 100644
--- a/include/libiberty.h
+++ b/include/libiberty.h
@@ -1,7 +1,7 @@
 /* Function declarations for libiberty.
 
    Copyright (C) 1997-2026 Free Software Foundation, Inc.
-   
+
    Note - certain prototypes declared in this header file are for
    functions whoes implementation copyright does not belong to the
    FSF.  Those prototypes are present in this file for reference
@@ -23,7 +23,7 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street - Fifth Floor,
    Boston, MA 02110-1301, USA.
-   
+
    Written by Cygnus Support, 1994.
 
    The libiberty library provides a number of functions which are
@@ -108,7 +108,7 @@ extern int countargv (char * const *);
 #if defined (__GNU_LIBRARY__ ) || defined (__linux__) \
  || defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) \
  || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__MINGW32__) \
- || defined (__DragonFly__) || defined (HAVE_DECL_BASENAME) 
+ || defined (__DragonFly__) || defined (HAVE_DECL_BASENAME)
 extern char *basename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
 #else
 /* Do not allow basename to be used if there is no prototype seen.  We
@@ -232,7 +232,7 @@ extern char * getpwd (void);
 #ifdef __MINGW32__
 /* Forward declaration to avoid #include <sys/time.h>.   */
 struct timeval;
-extern int gettimeofday (struct timeval *, void *); 
+extern int gettimeofday (struct timeval *, void *);
 #endif
 
 /* Get the amount of time the process has run, in microseconds.  */
@@ -482,7 +482,7 @@ extern struct pex_obj *pex_init (int flags, const char *pname,
 /* Capture stderr to a pipe.  The output can be read by
    calling pex_read_err and reading from the returned
    FILE object.  This flag may be specified only for
-   the last program in a pipeline.  
+   the last program in a pipeline.
 
    This flag is supported only on Unix and Windows.  */
 #define PEX_STDERR_TO_PIPE	0x40
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index b072d0bed52..37c351d33f5 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,57 @@
+2025-11-30  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* simple-object-mach-o.c
+	(simple_object_mach_o_segment): Handle non-LTO sections.
+
+2025-11-06  Peter Damianov  <peter0x44@disroot.org>
+
+	PR target/122472
+	* simple-object-coff.c (struct external_filehdr_bigobj): New
+	structure for BigObj file header.
+	(bigobj_magic): New constant for BigObj magic bytes.
+	(struct external_syment_bigobj): New structure for BigObj
+	20-byte symbol table entries.
+	(union external_auxent_bigobj): New union for BigObj 20-byte
+	auxiliary symbol entries.
+	(struct simple_object_coff_read): Add is_bigobj flag and make
+	nscns 32-bit to support both formats.
+	(struct simple_object_coff_attributes): Add is_bigobj flag.
+	(simple_object_coff_match): Add BigObj format detection.
+	(simple_object_coff_read_strtab): Use format-specific symbol
+	size when calculating string table offset.
+	(simple_object_coff_attributes_merge): Check is_bigobj flag.
+	(simple_object_coff_write_filehdr_bigobj): New function.
+	(simple_object_coff_write_to_file): Add logic for writing
+	BigObj vs regular COFF format with appropriate symbol
+	and auxiliary entry structures.
+
+2025-11-03  Sam James  <sam@gentoo.org>
+
+	* configure: Regenerate.
+
+2025-10-02  H.J. Lu  <hjl.tools@gmail.com>
+
+	* aclocal.m4: Regenerated.
+	* configure: Likewise.
+	* configure.ac: Synced from binutils-gdb.
+
+2025-08-17  Nathaniel Shead  <nathanieloshead@gmail.com>
+
+	PR c++/120503
+	PR c++/120824
+	* cp-demangle.c (d_unnamed_enum): New function.
+	(d_unqualified_name): Call it.
+	(cplus_demangle_type): Handle unscoped unnamed types
+	(Ue, Ul, etc.)
+	(d_count_templates_scopes): Handle unnamed enums.
+	(d_find_pack): Likewise.
+	(d_print_comp_inner): Print unnamed enums.
+	* testsuite/demangle-expected: Add tests.
+
+2025-08-13  Jakub Jelinek  <jakub@redhat.com>
+
+	* cp-demangle.c (d_encoding): Fix a comment typo, whaever -> whatever.
+
 2025-08-06  Matthieu Longo  <matthieu.longo@arm.com>
 
 	* testsuite/test-doubly-linked-list.c: disable debug logging on
diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in
index 6d8c88ebfe7..00af4acca66 100644
--- a/libiberty/Makefile.in
+++ b/libiberty/Makefile.in
@@ -510,7 +510,6 @@ aclocal_deps = \
 	$(srcdir)/../config/cet.m4 \
 	$(srcdir)/../config/enable.m4 \
 	$(srcdir)/../config/gcc-plugin.m4 \
-	$(srcdir)/../config/mmap.m4 \
 	$(srcdir)/../config/no-executables.m4 \
 	$(srcdir)/../config/override.m4 \
 	$(srcdir)/../config/picflag.m4 \
diff --git a/libiberty/acinclude.m4 b/libiberty/acinclude.m4
index 49f621bf629..a8f2146b0f5 100644
--- a/libiberty/acinclude.m4
+++ b/libiberty/acinclude.m4
@@ -19,7 +19,7 @@ dnl On some versions of SunOS4 at least, strncmp reads a word at a time
 dnl but erroneously reads past the end of strings.  This can cause
 dnl a SEGV in some cases.
 AC_DEFUN([libiberty_AC_FUNC_STRNCMP],
-[AC_REQUIRE([GCC_AC_FUNC_MMAP])
+[AC_REQUIRE([AC_FUNC_MMAP])
 AC_CACHE_CHECK([for working strncmp], ac_cv_func_strncmp_works,
 [AC_TRY_RUN([
 /* Test by Jim Wilson and Kaveh Ghazi.
diff --git a/libiberty/aclocal.m4 b/libiberty/aclocal.m4
index 46cefc36edc..5151f5fee18 100644
--- a/libiberty/aclocal.m4
+++ b/libiberty/aclocal.m4
@@ -18,7 +18,6 @@ m4_include([../config/clang-plugin.m4])
 m4_include([../config/enable.m4])
 m4_include([../config/gcc-plugin.m4])
 m4_include([../config/hwcaps.m4])
-m4_include([../config/mmap.m4])
 m4_include([../config/no-executables.m4])
 m4_include([../config/override.m4])
 m4_include([../config/picflag.m4])
diff --git a/libiberty/configure b/libiberty/configure
index 4c72b5a9283..359f19ac037 100755
--- a/libiberty/configure
+++ b/libiberty/configure
@@ -7997,9 +7997,6 @@ if test x$gcc_no_link = xyes; then
   fi
 fi
 if test "x${ac_cv_func_mmap_fixed_mapped}" != xno; then
-  save_ASAN_OPTIONS="$ASAN_OPTIONS"
-  ASAN_OPTIONS=detect_leaks=0
-  export ASAN_OPTIONS
 
 for ac_func in getpagesize
 do :
@@ -8178,8 +8175,6 @@ $as_echo "#define HAVE_MMAP 1" >>confdefs.h
 fi
 rm -f conftest.mmap conftest.txt
 
-  ASAN_OPTIONS="$save_ASAN_OPTIONS"
-
 fi
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working strncmp" >&5
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index e3c9ca10434..5e6571d419b 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -499,6 +499,8 @@ static struct demangle_component *d_lambda (struct d_info *);
 
 static struct demangle_component *d_unnamed_type (struct d_info *);
 
+static struct demangle_component *d_unnamed_enum (struct d_info *);
+
 static struct demangle_component *
 d_clone_suffix (struct d_info *, struct demangle_component *);
 
@@ -1424,7 +1426,7 @@ d_encoding (struct d_info *di, int top_level)
 
 	      /* If this is a non-top-level local-name, clear the
 		 return type, so it doesn't confuse the user by
-		 being confused with the return type of whaever
+		 being confused with the return type of whatever
 		 this is nested within.  */
 	      if (!top_level && dc->type == DEMANGLE_COMPONENT_LOCAL_NAME
 		  && ftype->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
@@ -1799,6 +1801,9 @@ d_unqualified_name (struct d_info *di, struct demangle_component *scope,
     {
       switch (d_peek_next_char (di))
 	{
+	case 'e':
+	  ret = d_unnamed_enum (di);
+	  break;
 	case 'l':
 	  ret = d_lambda (di);
 	  break;
@@ -2728,13 +2733,20 @@ cplus_demangle_type (struct d_info *di)
       break;
 
     case 'U':
-      d_advance (di, 1);
-      ret = d_source_name (di);
-      if (d_peek_char (di) == 'I')
-	ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
-			   d_template_args (di));
-      ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL,
-			 cplus_demangle_type (di), ret);
+      peek = d_peek_next_char (di);
+      if (IS_DIGIT (peek))
+	{
+	  d_advance (di, 1);
+	  ret = d_source_name (di);
+	  if (d_peek_char (di) == 'I')
+	    ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
+			       d_template_args (di));
+	  ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL,
+			     cplus_demangle_type (di), ret);
+	}
+      else
+	/* Could be a closure type or an unnamed enum.  */
+	ret = d_unqualified_name (di, NULL, NULL);
       break;
 
     case 'D':
@@ -4090,6 +4102,33 @@ d_unnamed_type (struct d_info *di)
   return ret;
 }
 
+/* <unnamed-enum-name> ::= Ue <underlying type> <enumerator source-name> */
+
+static struct demangle_component *
+d_unnamed_enum (struct d_info *di)
+{
+  if (! d_check_char (di, 'U'))
+    return NULL;
+  if (! d_check_char (di, 'e'))
+    return NULL;
+
+  struct demangle_component *underlying = cplus_demangle_type (di);
+  struct demangle_component *name = d_source_name (di);
+
+  struct demangle_component *ret = d_make_empty (di);
+  if (ret)
+    {
+      ret->type = DEMANGLE_COMPONENT_UNNAMED_ENUM;
+      d_left (ret) = underlying;
+      d_right (ret) = name;
+    }
+
+  if (! d_add_substitution (di, ret))
+    return NULL;
+
+  return ret;
+}
+
 /* <clone-suffix> ::= [ . <clone-type-identifier> ] [ . <nonnegative number> ]*
 */
 
@@ -4396,6 +4435,7 @@ d_count_templates_scopes (struct d_print_info *dpi,
     case DEMANGLE_COMPONENT_CHARACTER:
     case DEMANGLE_COMPONENT_NUMBER:
     case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+    case DEMANGLE_COMPONENT_UNNAMED_ENUM:
     case DEMANGLE_COMPONENT_STRUCTURED_BINDING:
     case DEMANGLE_COMPONENT_MODULE_NAME:
     case DEMANGLE_COMPONENT_MODULE_PARTITION:
@@ -4780,6 +4820,7 @@ d_find_pack (struct d_print_info *dpi,
     case DEMANGLE_COMPONENT_CHARACTER:
     case DEMANGLE_COMPONENT_FUNCTION_PARAM:
     case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+    case DEMANGLE_COMPONENT_UNNAMED_ENUM:
     case DEMANGLE_COMPONENT_DEFAULT_ARG:
     case DEMANGLE_COMPONENT_NUMBER:
       return NULL;
@@ -6258,6 +6299,14 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
       d_append_char (dpi, '}');
       return;
 
+    case DEMANGLE_COMPONENT_UNNAMED_ENUM:
+      d_append_string (dpi, "{enum:");
+      d_print_comp (dpi, options, d_left (dc));
+      d_append_string (dpi, "{");
+      d_print_comp (dpi, options, d_right (dc));
+      d_append_string (dpi, "}}");
+      return;
+
     case DEMANGLE_COMPONENT_CLONE:
       d_print_comp (dpi, options, d_left (dc));
       d_append_string (dpi, " [clone ");
diff --git a/libiberty/simple-object-coff.c b/libiberty/simple-object-coff.c
index 2cc94495a13..648036921ac 100644
--- a/libiberty/simple-object-coff.c
+++ b/libiberty/simple-object-coff.c
@@ -57,6 +57,32 @@ struct external_filehdr
   unsigned char f_flags[2];	/* flags			*/
 };
 
+/* BigObj COFF file header.  */
+
+struct external_filehdr_bigobj
+{
+  unsigned char sig1[2];	/* Must be 0x0000 */
+  unsigned char sig2[2];	/* Must be 0xFFFF */
+  unsigned char version[2];	/* Version, currently 2 */
+  unsigned char machine[2];	/* Machine type */
+  unsigned char timdat[4];	/* time & date stamp */
+  unsigned char classid[16];	/* Magic GUID that identifies BigObj format */
+  unsigned char sizeofdata[4];	/* Size of data (unused, set to 0) */
+  unsigned char flags[4];	/* Flags (unused, set to 0) */
+  unsigned char metadatasize[4];	/* Metadata size (unused, set to 0) */
+  unsigned char metadataoffset[4];	/* Metadata offset (unused, set to 0) */
+  unsigned char nscns[4];	/* number of sections (32-bit!) */
+  unsigned char symptr[4];	/* file pointer to symtab */
+  unsigned char nsyms[4];	/* number of symtab entries */
+};
+
+/* The BigObj magic GUID (ClassID).  */
+static const unsigned char bigobj_magic[16] =
+{
+  0xC7, 0xA1, 0xBA, 0xD1, 0xEE, 0xBA, 0xA9, 0x4B,
+  0xAF, 0x20, 0xFA, 0xF6, 0x6A, 0xA4, 0xDC, 0xB8
+};
+
 /* Bits for filehdr f_flags field.  */
 
 #define F_EXEC			(0x0002)
@@ -119,6 +145,28 @@ struct external_syment
   unsigned char e_numaux[1];
 };
 
+/* BigObj COFF symbol table entry (20 bytes instead of 18).  */
+
+struct external_syment_bigobj
+{
+  union
+  {
+    unsigned char e_name[E_SYMNMLEN];
+
+    struct
+    {
+      unsigned char e_zeroes[4];
+      unsigned char e_offset[4];
+    } e;
+  } e;
+
+  unsigned char e_value[4];
+  unsigned char e_scnum[4];	/* 32-bit section number! */
+  unsigned char e_type[2];
+  unsigned char e_sclass[1];
+  unsigned char e_numaux[1];
+};
+
 /* Length allowed for filename in aux sym format 4.  */
 
 #define E_FILNMLEN	18
@@ -149,6 +197,33 @@ union external_auxent
   } x_scn;
 };
 
+/* BigObj auxiliary symbol (20 bytes to match symbol size).  */
+
+union external_auxent_bigobj
+{
+  /* Aux sym format 4: file.  */
+  union
+  {
+    char x_fname[E_FILNMLEN];
+    struct
+    {
+      unsigned char x_zeroes[4];
+      unsigned char x_offset[4];
+    } x_n;
+  } x_file;
+  /* Aux sym format 5: section.  */
+  struct
+  {
+    unsigned char x_scnlen[4];		/* section length		*/
+    unsigned char x_nreloc[2];		/* # relocation entries		*/
+    unsigned char x_nlinno[2];		/* # line numbers		*/
+    unsigned char x_checksum[4];	/* section COMDAT checksum	*/
+    unsigned char x_associated[2];	/* COMDAT assoc section index	*/
+    unsigned char x_comdat[1];		/* COMDAT selection number	*/
+    unsigned char x_pad[3];		/* Padding to 20 bytes		*/
+  } x_scn;
+};
+
 /* Symbol-related constants.  */
 
 #define IMAGE_SYM_DEBUG		(-2)
@@ -168,8 +243,10 @@ struct simple_object_coff_read
   unsigned short magic;
   /* Whether the file is big-endian.  */
   unsigned char is_big_endian;
+  /* Whether this is BigObj format.  */
+  unsigned char is_bigobj;
   /* Number of sections.  */
-  unsigned short nscns;
+  unsigned int nscns;
   /* File offset of symbol table.  */
   off_t symptr;
   /* Number of symbol table entries.  */
@@ -188,6 +265,8 @@ struct simple_object_coff_attributes
   unsigned short magic;
   /* Whether the file is big-endian.  */
   unsigned char is_big_endian;
+  /* Whether this is BigObj format.  */
+  unsigned char is_bigobj;
   /* Flags.  */
   unsigned short flags;
 };
@@ -240,10 +319,12 @@ simple_object_coff_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
   int is_big_endian;
   unsigned short (*fetch_16) (const unsigned char *);
   unsigned int (*fetch_32) (const unsigned char *);
-  unsigned char hdrbuf[sizeof (struct external_filehdr)];
+  unsigned char hdrbuf[sizeof (struct external_filehdr_bigobj)];
   unsigned short flags;
   struct simple_object_coff_read *ocr;
+  unsigned short sig1, sig2;
 
+  /* Try regular COFF first.  */
   c = sizeof (coff_magic) / sizeof (coff_magic[0]);
   magic_big = simple_object_fetch_big_16 (header);
   magic_little = simple_object_fetch_little_16 (header);
@@ -254,12 +335,64 @@ simple_object_coff_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
 	  : coff_magic[i].magic == magic_little)
 	break;
     }
-  if (i >= c)
+
+  /* Check for BigObj if regular COFF didn't match.  */
+  sig1 = simple_object_fetch_little_16 (header);
+  sig2 = simple_object_fetch_little_16 (header + 2);
+
+  if (i >= c && (sig1 != 0 || sig2 != 0xFFFF))
     {
+      /* Not regular COFF and not BigObj.  */
       *errmsg = NULL;
       *err = 0;
       return NULL;
     }
+
+  if (sig1 == 0 && sig2 == 0xFFFF)
+    {
+      /* This looks like BigObj.  Verify the ClassID.  */
+      unsigned char bigobj_hdrbuf[sizeof (struct external_filehdr_bigobj)];
+
+      if (!simple_object_internal_read (descriptor, offset, bigobj_hdrbuf,
+					sizeof bigobj_hdrbuf, errmsg, err))
+	return NULL;
+
+      if (memcmp (bigobj_hdrbuf + offsetof (struct external_filehdr_bigobj,
+					    classid),
+		  bigobj_magic, 16) != 0)
+	{
+	  *errmsg = NULL;
+	  *err = 0;
+	  return NULL;
+	}
+
+      /* BigObj is always little-endian.  */
+      is_big_endian = 0;
+
+      ocr = XNEW (struct simple_object_coff_read);
+      ocr->magic = simple_object_fetch_little_16
+		     (bigobj_hdrbuf
+		      + offsetof (struct external_filehdr_bigobj, machine));
+      ocr->is_big_endian = 0;
+      ocr->is_bigobj = 1;
+      ocr->nscns = simple_object_fetch_little_32
+		     (bigobj_hdrbuf
+		      + offsetof (struct external_filehdr_bigobj, nscns));
+      ocr->symptr = simple_object_fetch_little_32
+		      (bigobj_hdrbuf
+		       + offsetof (struct external_filehdr_bigobj, symptr));
+      ocr->nsyms = simple_object_fetch_little_32
+		     (bigobj_hdrbuf
+		      + offsetof (struct external_filehdr_bigobj, nsyms));
+      ocr->flags = simple_object_fetch_little_32
+		     (bigobj_hdrbuf
+		      + offsetof (struct external_filehdr_bigobj, flags));
+      ocr->scnhdr_offset = sizeof (struct external_filehdr_bigobj);
+
+      return (void *) ocr;
+    }
+
+  /* Regular COFF.  */
   is_big_endian = coff_magic[i].is_big_endian;
 
   magic = is_big_endian ? magic_big : magic_little;
@@ -270,7 +403,7 @@ simple_object_coff_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
 	      ? simple_object_fetch_big_32
 	      : simple_object_fetch_little_32);
 
-  if (!simple_object_internal_read (descriptor, offset, hdrbuf, sizeof hdrbuf,
+  if (!simple_object_internal_read (descriptor, offset, hdrbuf, sizeof (struct external_filehdr),
 				    errmsg, err))
     return NULL;
 
@@ -285,6 +418,7 @@ simple_object_coff_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
   ocr = XNEW (struct simple_object_coff_read);
   ocr->magic = magic;
   ocr->is_big_endian = is_big_endian;
+  ocr->is_bigobj = 0;
   ocr->nscns = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_nscns));
   ocr->symptr = fetch_32 (hdrbuf
 			  + offsetof (struct external_filehdr, f_symptr));
@@ -309,9 +443,13 @@ simple_object_coff_read_strtab (simple_object_read *sobj, size_t *strtab_size,
   unsigned char strsizebuf[4];
   size_t strsize;
   char *strtab;
+  size_t sym_size;
+
+  /* Symbol size depends on format.  */
+  sym_size = ocr->is_bigobj ? sizeof (struct external_syment_bigobj)
+			    : sizeof (struct external_syment);
 
-  strtab_offset = sobj->offset + ocr->symptr
-		  + ocr->nsyms * sizeof (struct external_syment);
+  strtab_offset = sobj->offset + ocr->symptr + ocr->nsyms * sym_size;
   if (!simple_object_internal_read (sobj->descriptor, strtab_offset,
 				    strsizebuf, 4, errmsg, err))
     return NULL;
@@ -444,6 +582,7 @@ simple_object_coff_fetch_attributes (simple_object_read *sobj,
   ret = XNEW (struct simple_object_coff_attributes);
   ret->magic = ocr->magic;
   ret->is_big_endian = ocr->is_big_endian;
+  ret->is_bigobj = ocr->is_bigobj;
   ret->flags = ocr->flags;
   return ret;
 }
@@ -466,7 +605,9 @@ simple_object_coff_attributes_merge (void *todata, void *fromdata, int *err)
   struct simple_object_coff_attributes *from =
     (struct simple_object_coff_attributes *) fromdata;
 
-  if (to->magic != from->magic || to->is_big_endian != from->is_big_endian)
+  if (to->magic != from->magic
+      || to->is_big_endian != from->is_big_endian
+      || to->is_bigobj != from->is_bigobj)
     {
       *err = 0;
       return "COFF object format mismatch";
@@ -500,6 +641,52 @@ simple_object_coff_start_write (void *attributes_data,
   return ret;
 }
 
+/* Write out a BigObj COFF filehdr.  */
+
+static int
+simple_object_coff_write_filehdr_bigobj (simple_object_write *sobj,
+					 int descriptor,
+					 unsigned int nscns,
+					 size_t symtab_offset,
+					 unsigned int nsyms,
+					 const char **errmsg, int *err)
+{
+  struct simple_object_coff_attributes *attrs =
+    (struct simple_object_coff_attributes *) sobj->data;
+  unsigned char hdrbuf[sizeof (struct external_filehdr_bigobj)];
+  unsigned char *hdr;
+  void (*set_16) (unsigned char *, unsigned short);
+  void (*set_32) (unsigned char *, unsigned int);
+
+  hdr = &hdrbuf[0];
+
+  /* BigObj is always little-endian.  */
+  set_16 = simple_object_set_little_16;
+  set_32 = simple_object_set_little_32;
+
+  memset (hdr, 0, sizeof (struct external_filehdr_bigobj));
+
+  /* Set BigObj signatures.  */
+  set_16 (hdr + offsetof (struct external_filehdr_bigobj, sig1), 0);
+  set_16 (hdr + offsetof (struct external_filehdr_bigobj, sig2), 0xFFFF);
+  set_16 (hdr + offsetof (struct external_filehdr_bigobj, version), 2);
+  set_16 (hdr + offsetof (struct external_filehdr_bigobj, machine),
+	  attrs->magic);
+  /* timdat left as zero.  */
+  /* Copy ClassID.  */
+  memcpy (hdr + offsetof (struct external_filehdr_bigobj, classid),
+	  bigobj_magic, 16);
+  /* sizeofdata, flags, metadatasize, metadataoffset left as zero.  */
+  set_32 (hdr + offsetof (struct external_filehdr_bigobj, nscns), nscns);
+  set_32 (hdr + offsetof (struct external_filehdr_bigobj, symptr),
+	  symtab_offset);
+  set_32 (hdr + offsetof (struct external_filehdr_bigobj, nsyms), nsyms);
+
+  return simple_object_internal_write (descriptor, 0, hdrbuf,
+				       sizeof (struct external_filehdr_bigobj),
+				       errmsg, err);
+}
+
 /* Write out a COFF filehdr.  */
 
 static int
@@ -618,14 +805,16 @@ simple_object_coff_write_to_file (simple_object_write *sobj, int descriptor,
      what 'gas' uses when told to assemble from stdin.  */
   const char *source_filename = "fake";
   size_t sflen;
-  union
-  {
-    struct external_syment sym;
-    union external_auxent aux;
-  } syms[2];
+  size_t symsize;
   void (*set_16) (unsigned char *, unsigned short);
   void (*set_32) (unsigned char *, unsigned int);
 
+  /* Determine symbol size based on format.  */
+  if (attrs->is_bigobj)
+    symsize = sizeof (struct external_syment_bigobj);
+  else
+    symsize = sizeof (struct external_syment);
+
   set_16 = (attrs->is_big_endian
 	    ? simple_object_set_big_16
 	    : simple_object_set_little_16);
@@ -637,7 +826,10 @@ simple_object_coff_write_to_file (simple_object_write *sobj, int descriptor,
   for (section = sobj->sections; section != NULL; section = section->next)
     ++nscns;
 
-  scnhdr_offset = sizeof (struct external_filehdr);
+  if (attrs->is_bigobj)
+    scnhdr_offset = sizeof (struct external_filehdr_bigobj);
+  else
+    scnhdr_offset = sizeof (struct external_filehdr);
   offset = scnhdr_offset + nscns * sizeof (struct external_scnhdr);
   name_offset = 4;
   for (section = sobj->sections; section != NULL; section = section->next)
@@ -693,91 +885,198 @@ simple_object_coff_write_to_file (simple_object_write *sobj, int descriptor,
   symtab_offset = offset;
   /* Advance across space reserved for symbol table to locate
      start of string table.  */
-  offset += nsyms * sizeof (struct external_syment);
+  offset += nsyms * symsize;
 
   /* Write out file symbol.  */
-  memset (&syms[0], 0, sizeof (syms));
-  strcpy ((char *)&syms[0].sym.e.e_name[0], ".file");
-  set_16 (&syms[0].sym.e_scnum[0], IMAGE_SYM_DEBUG);
-  set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
-  syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_FILE;
-  syms[0].sym.e_numaux[0] = 1;
-  /* The name need not be nul-terminated if it fits into the x_fname field
-     directly, but must be if it has to be placed into the string table.  */
-  sflen = strlen (source_filename);
-  if (sflen <= E_FILNMLEN)
-    memcpy (&syms[1].aux.x_file.x_fname[0], source_filename, sflen);
-  else
+  if (attrs->is_bigobj)
     {
-      set_32 (&syms[1].aux.x_file.x_n.x_offset[0], name_offset);
-      if (!simple_object_internal_write (descriptor, offset + name_offset,
-					 ((const unsigned char *)
-					  source_filename),
-					 sflen + 1, &errmsg, err))
+      union
+      {
+	struct external_syment_bigobj sym;
+	union external_auxent_bigobj aux;
+      } syms[2];
+
+      memset (&syms[0], 0, sizeof (syms));
+      strcpy ((char *)&syms[0].sym.e.e_name[0], ".file");
+      set_32 (&syms[0].sym.e_scnum[0], IMAGE_SYM_DEBUG);
+      set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
+      syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_FILE;
+      syms[0].sym.e_numaux[0] = 1;
+      /* The name need not be nul-terminated if it fits into the x_fname field
+	 directly, but must be if it has to be placed into the string table.  */
+      sflen = strlen (source_filename);
+      if (sflen <= E_FILNMLEN)
+	memcpy (&syms[1].aux.x_file.x_fname[0], source_filename, sflen);
+      else
+	{
+	  set_32 (&syms[1].aux.x_file.x_n.x_offset[0], name_offset);
+	  if (!simple_object_internal_write (descriptor, offset + name_offset,
+					     ((const unsigned char *)
+					      source_filename),
+					     sflen + 1, &errmsg, err))
+	    return errmsg;
+	  name_offset += strlen (source_filename) + 1;
+	}
+      if (!simple_object_internal_write (descriptor, symtab_offset,
+					 (const unsigned char *) &syms[0],
+					 sizeof (syms), &errmsg, err))
 	return errmsg;
-      name_offset += strlen (source_filename) + 1;
-    }
-  if (!simple_object_internal_write (descriptor, symtab_offset,
-				     (const unsigned char *) &syms[0],
-				     sizeof (syms), &errmsg, err))
-    return errmsg;
-
-  /* Write the string table length, followed by the strings and section
-     symbols in step with each other.  */
-  set_32 (strsizebuf, name_offset);
-  if (!simple_object_internal_write (descriptor, offset, strsizebuf, 4,
-				     &errmsg, err))
-    return errmsg;
 
-  name_offset = 4;
-  secsym_offset = symtab_offset + sizeof (syms);
-  memset (&syms[0], 0, sizeof (syms));
-  set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
-  syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_STATIC;
-  syms[0].sym.e_numaux[0] = 1;
-  secnum = 1;
+      /* Write the string table length, followed by the strings and section
+	 symbols in step with each other.  */
+      set_32 (strsizebuf, name_offset);
+      if (!simple_object_internal_write (descriptor, offset, strsizebuf, 4,
+					 &errmsg, err))
+	return errmsg;
 
-  for (section = sobj->sections; section != NULL; section = section->next)
-    {
-      size_t namelen;
-      size_t scnsize;
-      struct simple_object_write_section_buffer *buffer;
+      name_offset = 4;
+      secsym_offset = symtab_offset + sizeof (syms);
+      memset (&syms[0], 0, sizeof (syms));
+      set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
+      syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_STATIC;
+      syms[0].sym.e_numaux[0] = 1;
+      secnum = 1;
 
-      namelen = strlen (section->name);
-      set_16 (&syms[0].sym.e_scnum[0], secnum++);
-      scnsize = 0;
-      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
-	scnsize += buffer->size;
-      set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize);
-      if (namelen > SCNNMLEN)
+      for (section = sobj->sections; section != NULL; section = section->next)
 	{
-	  set_32 (&syms[0].sym.e.e.e_zeroes[0], 0);
-	  set_32 (&syms[0].sym.e.e.e_offset[0], name_offset);
-	  if (!simple_object_internal_write (descriptor, offset + name_offset,
-					     ((const unsigned char *)
-					      section->name),
-					     namelen + 1, &errmsg, err))
+	  size_t namelen;
+	  size_t scnsize;
+	  struct simple_object_write_section_buffer *buffer;
+
+	  namelen = strlen (section->name);
+	  set_32 (&syms[0].sym.e_scnum[0], secnum++);
+	  scnsize = 0;
+	  for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
+	    scnsize += buffer->size;
+	  set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize);
+	  if (namelen > SCNNMLEN)
+	    {
+	      set_32 (&syms[0].sym.e.e.e_zeroes[0], 0);
+	      set_32 (&syms[0].sym.e.e.e_offset[0], name_offset);
+	      if (!simple_object_internal_write (descriptor, offset + name_offset,
+						 ((const unsigned char *)
+						  section->name),
+						 namelen + 1, &errmsg, err))
+		return errmsg;
+	      name_offset += namelen + 1;
+	    }
+	  else
+	    {
+	      memcpy (&syms[0].sym.e.e_name[0], section->name,
+		      strlen (section->name));
+	      memset (&syms[0].sym.e.e_name[strlen (section->name)], 0,
+		      E_SYMNMLEN - strlen (section->name));
+	    }
+
+	  if (!simple_object_internal_write (descriptor, secsym_offset,
+					     (const unsigned char *) &syms[0],
+					     sizeof (syms), &errmsg, err))
 	    return errmsg;
-	  name_offset += namelen + 1;
+	  secsym_offset += sizeof (syms);
 	}
+    }
+  else
+    {
+      /* Regular COFF.  */
+      union
+      {
+	struct external_syment sym;
+	union external_auxent aux;
+      } syms[2];
+
+      memset (&syms[0], 0, sizeof (syms));
+      strcpy ((char *)&syms[0].sym.e.e_name[0], ".file");
+      set_16 (&syms[0].sym.e_scnum[0], IMAGE_SYM_DEBUG);
+      set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
+      syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_FILE;
+      syms[0].sym.e_numaux[0] = 1;
+      /* The name need not be nul-terminated if it fits into the x_fname field
+	 directly, but must be if it has to be placed into the string table.  */
+      sflen = strlen (source_filename);
+      if (sflen <= E_FILNMLEN)
+	memcpy (&syms[1].aux.x_file.x_fname[0], source_filename, sflen);
       else
 	{
-	  memcpy (&syms[0].sym.e.e_name[0], section->name,
-		  strlen (section->name));
-	  memset (&syms[0].sym.e.e_name[strlen (section->name)], 0,
-		  E_SYMNMLEN - strlen (section->name));
+	  set_32 (&syms[1].aux.x_file.x_n.x_offset[0], name_offset);
+	  if (!simple_object_internal_write (descriptor, offset + name_offset,
+					     ((const unsigned char *)
+					      source_filename),
+					     sflen + 1, &errmsg, err))
+	    return errmsg;
+	  name_offset += strlen (source_filename) + 1;
 	}
-
-      if (!simple_object_internal_write (descriptor, secsym_offset,
+      if (!simple_object_internal_write (descriptor, symtab_offset,
 					 (const unsigned char *) &syms[0],
 					 sizeof (syms), &errmsg, err))
 	return errmsg;
-      secsym_offset += sizeof (syms);
+
+      /* Write the string table length, followed by the strings and section
+	 symbols in step with each other.  */
+      set_32 (strsizebuf, name_offset);
+      if (!simple_object_internal_write (descriptor, offset, strsizebuf, 4,
+					 &errmsg, err))
+	return errmsg;
+
+      name_offset = 4;
+      secsym_offset = symtab_offset + sizeof (syms);
+      memset (&syms[0], 0, sizeof (syms));
+      set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
+      syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_STATIC;
+      syms[0].sym.e_numaux[0] = 1;
+      secnum = 1;
+
+      for (section = sobj->sections; section != NULL; section = section->next)
+	{
+	  size_t namelen;
+	  size_t scnsize;
+	  struct simple_object_write_section_buffer *buffer;
+
+	  namelen = strlen (section->name);
+	  set_16 (&syms[0].sym.e_scnum[0], secnum++);
+	  scnsize = 0;
+	  for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
+	    scnsize += buffer->size;
+	  set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize);
+	  if (namelen > SCNNMLEN)
+	    {
+	      set_32 (&syms[0].sym.e.e.e_zeroes[0], 0);
+	      set_32 (&syms[0].sym.e.e.e_offset[0], name_offset);
+	      if (!simple_object_internal_write (descriptor, offset + name_offset,
+						 ((const unsigned char *)
+						  section->name),
+						 namelen + 1, &errmsg, err))
+		return errmsg;
+	      name_offset += namelen + 1;
+	    }
+	  else
+	    {
+	      memcpy (&syms[0].sym.e.e_name[0], section->name,
+		      strlen (section->name));
+	      memset (&syms[0].sym.e.e_name[strlen (section->name)], 0,
+		      E_SYMNMLEN - strlen (section->name));
+	    }
+
+	  if (!simple_object_internal_write (descriptor, secsym_offset,
+					     (const unsigned char *) &syms[0],
+					     sizeof (syms), &errmsg, err))
+	    return errmsg;
+	  secsym_offset += sizeof (syms);
+	}
     }
 
-  if (!simple_object_coff_write_filehdr (sobj, descriptor, nscns,
-					 symtab_offset, nsyms, &errmsg, err))
-    return errmsg;
+  if (attrs->is_bigobj)
+    {
+      if (!simple_object_coff_write_filehdr_bigobj (sobj, descriptor, nscns,
+						     symtab_offset, nsyms,
+						     &errmsg, err))
+	return errmsg;
+    }
+  else
+    {
+      if (!simple_object_coff_write_filehdr (sobj, descriptor, nscns,
+					     symtab_offset, nsyms, &errmsg, err))
+	return errmsg;
+    }
 
   return NULL;
 }
diff --git a/libiberty/simple-object-mach-o.c b/libiberty/simple-object-mach-o.c
index 3e98c7c7786..3e81d6f908a 100644
--- a/libiberty/simple-object-mach-o.c
+++ b/libiberty/simple-object-mach-o.c
@@ -617,7 +617,6 @@ simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
       char *name;
       off_t secoffset;
       size_t secsize;
-      int l;
 
       sechdr = secdata + i * sechdrsize;
 
@@ -669,12 +668,15 @@ simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
 	    }
 	}
 
+      memset (namebuf, 0, sizeof (namebuf));
+      /* Copy the section name so we can append a null to make it into a
+	 c-string (Mach-o section names are not terminated).  */
+      memcpy (namebuf, sechdr + sectname_offset, MACH_O_NAME_LEN);
+      namebuf[MACH_O_NAME_LEN] = '\0';
+      name = &namebuf[0];
+      /* Maybe override this if we have long section name extension.  */
       if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0)
 	{
-	  memcpy (namebuf, sechdr + sectname_offset, MACH_O_NAME_LEN);
-	  namebuf[MACH_O_NAME_LEN] = '\0';
-
-	  name = &namebuf[0];
 	  if (strtab != NULL && name[0] == '_' && name[1] == '_')
 	    {
 	      unsigned long stringoffset;
@@ -696,19 +698,6 @@ simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
 		}
 	  }
 	}
-      else
-	{
-	   /* Otherwise, make a name like __segment,__section as per the
-	      convention in mach-o asm.  */
-	  name = &namebuf[0];
-	  memcpy (namebuf, (char *) sechdr + segname_offset, MACH_O_NAME_LEN);
-	  namebuf[MACH_O_NAME_LEN] = '\0';
-	  l = strlen (namebuf);
-	  namebuf[l] = ',';
-	  memcpy (namebuf + l + 1, (char *) sechdr + sectname_offset,
-		  MACH_O_NAME_LEN);
-	  namebuf[l + 1 + MACH_O_NAME_LEN] = '\0';
-	}
 
       simple_object_mach_o_section_info (omr->is_big_endian, is_32, sechdr,
 					 &secoffset, &secsize);
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 0f7b97a6d0a..e5cd8ec8a77 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -1709,3 +1709,10 @@ void S::bar<5, int>(this S, int)
 
 _ZNH1S3bazERKS_
 S::baz(this S const&)
+
+_Z3fooUlvE_
+foo({lambda()#1})
+
+# P2115R0 unnamed enums
+_Z3fooUei1ES_
+foo({enum:int{E}}, {enum:int{E}})


More information about the Binutils-cvs mailing list