public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] Import latest fixes to libiberty from GCC
@ 2020-03-02 12:03 H.J.Lu
  0 siblings, 0 replies; 3+ messages in thread
From: H.J.Lu @ 2020-03-02 12:03 UTC (permalink / raw)
  To: bfd-cvs, gdb-cvs

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

commit 4e07c9e2b69064e8b47e3981185b70ebe78aac68
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Mar 2 03:56:36 2020 -0800

    Import latest fixes to libiberty from GCC
    
    lto: Also copy .note.gnu.property section
    
    When generating the separate file with LTO debug sections, we should
    also copy .note.gnu.property section.
    
    	PR lto/93966
    	* simple-object.c (handle_lto_debug_sections): Also copy
    	.note.gnu.property section.

Diff:
---
 libiberty/ChangeLog       | 6 ++++++
 libiberty/simple-object.c | 3 +++
 2 files changed, 9 insertions(+)

diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 8e3408e..fd31323 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,9 @@
+2020-03-02  H.J. Lu  <hongjiu.lu@intel.com>
+
+	PR lto/93966
+	* simple-object.c (handle_lto_debug_sections): Also copy
+	.note.gnu.property section.
+
 2020-02-25  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* rust-demangle.h: Removed.
diff --git a/libiberty/simple-object.c b/libiberty/simple-object.c
index d9c648a..e6c466a 100644
--- a/libiberty/simple-object.c
+++ b/libiberty/simple-object.c
@@ -293,6 +293,9 @@ handle_lto_debug_sections (const char *name, int rename)
   /* Copy over .note.GNU-stack section under the same name if present.  */
   else if (strcmp (name, ".note.GNU-stack") == 0)
     return strcpy (newname, name);
+  /* Copy over .note.gnu.property section under the same name if present.  */
+  else if (strcmp (name, ".note.gnu.property") == 0)
+    return strcpy (newname, name);
   /* Copy over .comment section under the same name if present.  Solaris
      ld uses them to relax its checking of ELF gABI access rules for
      COMDAT sections in objects produced by GCC.  */


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [binutils-gdb] Import latest fixes to libiberty from GCC
@ 2017-09-01 13:15 H.J.Lu
  0 siblings, 0 replies; 3+ messages in thread
From: H.J.Lu @ 2017-09-01 13:15 UTC (permalink / raw)
  To: bfd-cvs, gdb-cvs

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

commit 376dc015f275575e0aa7be9c46476db5506ff836
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Sep 1 06:14:39 2017 -0700

    Import latest fixes to libiberty from GCC
    
    Fix warning for simple-object-elf.c.
    
    2017-09-01  Martin Liska  <mliska@suse.cz>
    
    	* simple-object-elf.c (simple_object_elf_copy_lto_debug_sections):
    	Remove duplicite declaration.

Diff:
---
 libiberty/ChangeLog           | 5 +++++
 libiberty/simple-object-elf.c | 6 ------
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 191a311..8c46971 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,8 @@
+2017-09-01  Martin Liska  <mliska@suse.cz>
+
+	* simple-object-elf.c (simple_object_elf_copy_lto_debug_sections):
+	Remove duplicite declaration.
+
 2017-08-31  Richard Biener  <rguenther@suse.de>
 
 	PR lto/81968
diff --git a/libiberty/simple-object-elf.c b/libiberty/simple-object-elf.c
index 9799e72..6774eb2 100644
--- a/libiberty/simple-object-elf.c
+++ b/libiberty/simple-object-elf.c
@@ -587,11 +587,6 @@ simple_object_elf_find_sections (simple_object_read *sobj,
 
   /* Read the section names.  */
 
-  if (eor->shstrndx == 0)
-    {
-      XDELETEVEC (shdrs);
-      return "ELF section header string table missing";
-    }
   shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
   name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
 			       shstrhdr, sh_size, Elf_Addr);
@@ -1237,7 +1232,6 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
       off_t offset;
       off_t length;
       int ret;
-      const char *errmsg;
       simple_object_write_section *dest;
       off_t flags;
       unsigned char *buf;


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [binutils-gdb] Import latest fixes to libiberty from GCC.
@ 2017-09-01  9:54 Nick Clifton
  0 siblings, 0 replies; 3+ messages in thread
From: Nick Clifton @ 2017-09-01  9:54 UTC (permalink / raw)
  To: bfd-cvs, gdb-cvs

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

commit f8ad2513754f5a53fecb407cf64fcb586836b60c
Author: Nick Clifton <nickc@redhat.com>
Date:   Fri Sep 1 10:52:53 2017 +0100

    Import latest fixes to libiberty from GCC.
    
    	PR lto/81968
    	* simple-object-elf.c (simple_object_elf_copy_lto_debug_section):
    	Keep names of removed global symbols.
    
    	* simple-object-xcoff.c (simple_object_xcoff_find_sections):
    	Improve .go_export csect handling.  Don't make assumptions
    	on containing section or number of auxiliary entries.
    
    	PR lto/81968
    	* simple-object-elf.c (simple_object_elf_copy_lto_debug_section):
    	Adjust field with for sh_type write, set SHF_EXCLUDE only for
    	removed sections.
    
    	PR lto/81925
    	* simple-object-elf.c (simple_object_elf_write_shdr): Adjust
    	type of sh_addralign and sh_entsize and properly write
    	sh_entsize as Elf_Addr.
    	(simple_object_elf_write_to_file): Read sh_entsize as Elf_Addr.
    
    	* simple-object-common.h (struct simple_object_functions): Add
    	copy_lto_debug_sections hook.
    	* simple-object.c: Include fcntl.h.
    	(handle_lto_debug_sections): New helper function.
    	(simple_object_copy_lto_debug_sections): New function copying
    	early LTO debug sections to regular debug sections in a new file.
    	(simple_object_start_write): Handle NULL segment_name.
    	* simple-object-coff.c (simple_object_coff_functions): Adjust
    	for not implemented copy_lto_debug_sections hook.
    	* simple-object-mach-o.c (simple_object_mach_o_functions): Likewise.
    	* simple-object-xcoff.c (simple_object_xcoff_functions): Likewise.
    	* simple-object-elf.c (SHT_NULL, SHT_SYMTAB, SHT_RELA, SHT_REL,
    	SHT_GROUP): Add various sectopn header types.
    	(SHF_EXCLUDE): Add flag.
    	(Elf32_External_Sym, Elf64_External_Sym): Add symbol struct.
    	(ELF_ST_BIND, ELF_ST_TYPE, ELF_ST_INFO): Add accessors.
    	(STT_OBJECT, STT_FUNC, STT_TLS, STT_GNU_IFUNC): Add Symbol types.
    	(STV_DEFAULT): Add symbol visibility.
    	(SHN_COMMON): Add special section index name.
    	(struct simple_object_elf_write): New.
    	(simple_object_elf_start_write): Adjust for new private data.
    	(simple_object_elf_write_shdr): Pass in values for all fields
    	we write.
    	(simple_object_elf_write_to_file): Adjust.  Copy from recorded
    	section headers if requested.
    	(simple_object_elf_release_write): Release private data.
    	(simple_object_elf_copy_lto_debug_sections): Copy and rename sections
    	as denoted by PFN and all their dependences, symbols and relocations
    	to the empty destination file.
    	(simple_object_elf_functions): Adjust for copy_lto_debug_sections hook.
    
    	* simple-object-xcoff.c (simple_object_xcoff_find_sections):
    	Search symbol table for .go_export symbol and apply pfn if found.

Diff:
---
 libiberty/ChangeLog              |  77 +++++-
 libiberty/simple-object-coff.c   |   3 +-
 libiberty/simple-object-common.h |   6 +
 libiberty/simple-object-elf.c    | 489 +++++++++++++++++++++++++++++++++++++--
 libiberty/simple-object-mach-o.c |   3 +-
 libiberty/simple-object-xcoff.c  | 177 +++++++++++++-
 libiberty/simple-object.c        |  83 ++++++-
 7 files changed, 802 insertions(+), 36 deletions(-)

diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 925b152..191a311 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,18 +1,80 @@
+2017-08-31  Richard Biener  <rguenther@suse.de>
+
+	PR lto/81968
+	* simple-object-elf.c (simple_object_elf_copy_lto_debug_section):
+	Keep names of removed global symbols.
+
+2017-08-29  Tony Reix  <tony.reix@atos.net>
+
+	* simple-object-xcoff.c (simple_object_xcoff_find_sections):
+	Improve .go_export csect handling.  Don't make assumptions
+	on containing section or number of auxiliary entries.
+
+2017-08-28  Richard Biener  <rguenther@suse.de>
+
+	PR lto/81968
+	* simple-object-elf.c (simple_object_elf_copy_lto_debug_section):
+	Adjust field with for sh_type write, set SHF_EXCLUDE only for
+	removed sections.
+
+2017-08-22  Richard Biener  <rguenther@suse.de>
+
+	PR lto/81925
+	* simple-object-elf.c (simple_object_elf_write_shdr): Adjust
+	type of sh_addralign and sh_entsize and properly write
+	sh_entsize as Elf_Addr.
+	(simple_object_elf_write_to_file): Read sh_entsize as Elf_Addr.
+
+2017-08-21  Richard Biener  <rguenther@suse.de>
+
+	* simple-object-common.h (struct simple_object_functions): Add
+	copy_lto_debug_sections hook.
+	* simple-object.c: Include fcntl.h.
+	(handle_lto_debug_sections): New helper function.
+	(simple_object_copy_lto_debug_sections): New function copying
+	early LTO debug sections to regular debug sections in a new file.
+	(simple_object_start_write): Handle NULL segment_name.
+	* simple-object-coff.c (simple_object_coff_functions): Adjust
+	for not implemented copy_lto_debug_sections hook.
+	* simple-object-mach-o.c (simple_object_mach_o_functions): Likewise.
+	* simple-object-xcoff.c (simple_object_xcoff_functions): Likewise.
+	* simple-object-elf.c (SHT_NULL, SHT_SYMTAB, SHT_RELA, SHT_REL,
+	SHT_GROUP): Add various sectopn header types.
+	(SHF_EXCLUDE): Add flag.
+	(Elf32_External_Sym, Elf64_External_Sym): Add symbol struct.
+	(ELF_ST_BIND, ELF_ST_TYPE, ELF_ST_INFO): Add accessors.
+	(STT_OBJECT, STT_FUNC, STT_TLS, STT_GNU_IFUNC): Add Symbol types.
+	(STV_DEFAULT): Add symbol visibility.
+	(SHN_COMMON): Add special section index name.
+	(struct simple_object_elf_write): New.
+	(simple_object_elf_start_write): Adjust for new private data.
+	(simple_object_elf_write_shdr): Pass in values for all fields
+	we write.
+	(simple_object_elf_write_to_file): Adjust.  Copy from recorded
+	section headers if requested.
+	(simple_object_elf_release_write): Release private data.
+	(simple_object_elf_copy_lto_debug_sections): Copy and rename sections
+	as denoted by PFN and all their dependences, symbols and relocations
+	to the empty destination file.
+	(simple_object_elf_functions): Adjust for copy_lto_debug_sections hook.
+
 2017-07-02  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
 	* dwarfnames.c (DW_FIRST_IDX, DW_END_IDX, DW_IDX, DW_IDX_DUP): New.
 
+2017-06-07  Tony Reix  <tony.reix@atos.net>
+	    Matthieu Sarter  <matthieu.sarter.external@atos.net>
+	    David Edelsohn  <dje.gcc@gmail.com>
+
+	* simple-object-xcoff.c (simple_object_xcoff_find_sections):
+	Search symbol table for .go_export symbol and apply pfn if found.
+
 2017-05-31  DJ Delorie  <dj@redhat.com>
 
 	* configure.ac (strnlen): Add to AC_CHECK_DECLS.
 	* configure: Likewise.
 	* config.in: Add HACE_DECL_STRNLEN.
 
-2017-05-31  Eli Zaretskii  <eliz@gnu.org>
-
-	* waitpid.c (wait) [__MINGW32__]: Define as a macro
-	that calls _cwait, so that this function works on MinGW.
-
 2017-05-27  Iain Buclaw  <ibuclaw@gdcproject.org>
 
 	* d-demangle.c (dlang_identifier): Prefix mangled init symbols
@@ -32,6 +94,11 @@
 	the demangled hexadecimal directly to string.
 	* testsuite/d-demangle-expected: Add tests.
 
+2017-05-24  Eli Zaretskii  <eliz@gnu.org>
+
+	* waitpid.c (wait) [__MINGW32__]: Define as a macro
+	that calls _cwait, so that this function works on MinGW.
+
 2017-05-02  Iain Buclaw  <ibuclaw@gdcproject.org>
 
 	* d-demangle.c (dlang_hexdigit): New function.
diff --git a/libiberty/simple-object-coff.c b/libiberty/simple-object-coff.c
index 0283b15..54d430d 100644
--- a/libiberty/simple-object-coff.c
+++ b/libiberty/simple-object-coff.c
@@ -800,5 +800,6 @@ const struct simple_object_functions simple_object_coff_functions =
   simple_object_coff_release_attributes,
   simple_object_coff_start_write,
   simple_object_coff_write_to_file,
-  simple_object_coff_release_write
+  simple_object_coff_release_write,
+  NULL
 };
diff --git a/libiberty/simple-object-common.h b/libiberty/simple-object-common.h
index cda4038..733bdd0 100644
--- a/libiberty/simple-object-common.h
+++ b/libiberty/simple-object-common.h
@@ -141,6 +141,12 @@ struct simple_object_functions
 
   /* Release the private data for an simple_object_write.  */
   void (*release_write) (void *);
+
+  /* Copy LTO debug sections.  */
+  const char *(*copy_lto_debug_sections) (simple_object_read *sobj,
+					  simple_object_write *dobj,
+					  int (*pfn) (const char **),
+					  int *err);
 };
 
 /* The known object file formats.  */
diff --git a/libiberty/simple-object-elf.c b/libiberty/simple-object-elf.c
index a733e4b..9799e72 100644
--- a/libiberty/simple-object-elf.c
+++ b/libiberty/simple-object-elf.c
@@ -122,9 +122,12 @@ typedef struct {
 
 /* Special section index values.  */
 
+#define SHN_UNDEF	0		/* Undefined section */
 #define SHN_LORESERVE	0xFF00		/* Begin range of reserved indices */
+#define SHN_COMMON	0xFFF2	/* Associated symbol is in common */
 #define SHN_XINDEX	0xFFFF		/* Section index is held elsewhere */
 
+
 /* 32-bit ELF program header.  */
 
 typedef struct {
@@ -183,8 +186,57 @@ typedef struct {
 
 /* Values for sh_type field.  */
 
+#define SHT_NULL	0		/* Section header table entry unused */
 #define SHT_PROGBITS	1		/* Program data */
+#define SHT_SYMTAB	2		/* Link editing symbol table */
 #define SHT_STRTAB	3		/* A string table */
+#define SHT_RELA	4		/* Relocation entries with addends */
+#define SHT_REL		9		/* Relocation entries, no addends */
+#define SHT_GROUP	17		/* Section contains a section group */
+
+/* Values for sh_flags field.  */
+
+#define SHF_EXCLUDE	0x80000000	/* Link editor is to exclude this
+					   section from executable and
+					   shared library that it builds
+					   when those objects are not to be
+					   further relocated.  */
+/* Symbol table entry.  */
+
+typedef struct
+{
+  unsigned char st_name[4];                /* Symbol name (string tbl index) */
+  unsigned char st_value[4];               /* Symbol value */
+  unsigned char st_size[4];                /* Symbol size */
+  unsigned char st_info;                /* Symbol type and binding */
+  unsigned char st_other;               /* Symbol visibility */
+  unsigned char st_shndx[2];               /* Section index */
+} Elf32_External_Sym;
+
+typedef struct
+{
+  unsigned char st_name[4];                /* Symbol name (string tbl index) */
+  unsigned char st_info;                /* Symbol type and binding */
+  unsigned char st_other;               /* Symbol visibility */
+  unsigned char st_shndx[2];               /* Section index */
+  unsigned char st_value[8];               /* Symbol value */
+  unsigned char st_size[8];                /* Symbol size */
+} Elf64_External_Sym;
+
+#define ELF_ST_BIND(val)              (((unsigned char) (val)) >> 4)
+#define ELF_ST_TYPE(val)              ((val) & 0xf)
+#define ELF_ST_INFO(bind, type)       (((bind) << 4) + ((type) & 0xf))
+
+#define STT_NOTYPE	0	/* Symbol type is unspecified */
+#define STT_OBJECT	1	/* Symbol is a data object */
+#define STT_FUNC	2	/* Symbol is a code object */
+#define STT_TLS		6	/* Thread local data object */
+#define STT_GNU_IFUNC	10	/* Symbol is an indirect code object */
+
+#define STB_LOCAL	0	/* Local symbol */
+#define STB_GLOBAL	1	/* Global symbol */
+
+#define STV_DEFAULT	0	/* Visibility is specified by binding type */
 
 /* Functions to fetch and store different ELF types, depending on the
    endianness and size.  */
@@ -348,6 +400,14 @@ struct simple_object_elf_attributes
   unsigned int flags;
 };
 
+/* Private data for an simple_object_write.  */
+
+struct simple_object_elf_write
+{
+  struct simple_object_elf_attributes attrs;
+  unsigned char *shdrs;
+};
+
 /* See if we have an ELF file.  */
 
 static void *
@@ -527,6 +587,11 @@ simple_object_elf_find_sections (simple_object_read *sobj,
 
   /* Read the section names.  */
 
+  if (eor->shstrndx == 0)
+    {
+      XDELETEVEC (shdrs);
+      return "ELF section header string table missing";
+    }
   shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
   name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
 			       shstrhdr, sh_size, Elf_Addr);
@@ -675,12 +740,13 @@ simple_object_elf_start_write (void *attributes_data,
 {
   struct simple_object_elf_attributes *attrs =
     (struct simple_object_elf_attributes *) attributes_data;
-  struct simple_object_elf_attributes *ret;
+  struct simple_object_elf_write *ret;
 
   /* We're just going to record the attributes, but we need to make a
      copy because the user may delete them.  */
-  ret = XNEW (struct simple_object_elf_attributes);
-  *ret = *attrs;
+  ret = XNEW (struct simple_object_elf_write);
+  ret->attrs = *attrs;
+  ret->shdrs = NULL;
   return ret;
 }
 
@@ -766,8 +832,11 @@ static int
 simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
 			      off_t offset, unsigned int sh_name,
 			      unsigned int sh_type, unsigned int sh_flags,
+			      off_t sh_addr,
 			      unsigned int sh_offset, unsigned int sh_size,
-			      unsigned int sh_link, unsigned int sh_addralign,
+			      unsigned int sh_link, unsigned int sh_info,
+			      size_t sh_addralign,
+			      size_t sh_entsize,
 			      const char **errmsg, int *err)
 {
   struct simple_object_elf_attributes *attrs =
@@ -788,12 +857,13 @@ simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addr, Elf_Addr, sh_addr);
   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_link, Elf_Word, sh_link);
-  /* sh_info left as zero.  */
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_info, Elf_Word, sh_info);
   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
-  /* sh_entsize left as zero.  */
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_entsize, Elf_Addr, sh_entsize);
 
   return simple_object_internal_write (descriptor, offset, buf, shdr_size,
 				       errmsg, err);
@@ -811,8 +881,9 @@ static const char *
 simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
 				 int *err)
 {
-  struct simple_object_elf_attributes *attrs =
-    (struct simple_object_elf_attributes *) sobj->data;
+  struct simple_object_elf_write *eow =
+    (struct simple_object_elf_write *) sobj->data;
+  struct simple_object_elf_attributes *attrs = &eow->attrs;
   unsigned char cl;
   size_t ehdr_size;
   size_t shdr_size;
@@ -825,6 +896,7 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
   unsigned int first_sh_link;
   size_t sh_name;
   unsigned char zero;
+  unsigned secnum;
 
   if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
     return errmsg;
@@ -862,21 +934,54 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
   else
     first_sh_link = shnum - 1;
   if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
-				     0, 0, 0, 0, first_sh_size, first_sh_link,
-				     0, &errmsg, err))
+				     0, 0, 0, 0, 0, first_sh_size, first_sh_link,
+				     0, 0, 0, &errmsg, err))
     return errmsg;
 
   shdr_offset += shdr_size;
 
   sh_name = 1;
+  secnum = 0;
   for (section = sobj->sections; section != NULL; section = section->next)
     {
       size_t mask;
       size_t new_sh_offset;
       size_t sh_size;
       struct simple_object_write_section_buffer *buffer;
+      unsigned int sh_type = SHT_PROGBITS;
+      unsigned int sh_flags = 0;
+      off_t sh_addr = 0;
+      unsigned int sh_link = 0;
+      unsigned int sh_info = 0;
+      size_t sh_addralign = 1U << section->align;
+      size_t sh_entsize = 0;
+      if (eow->shdrs)
+	{
+	  sh_type = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
+				     eow->shdrs + secnum * shdr_size,
+				     sh_type, Elf_Word);
+	  sh_flags = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
+				      eow->shdrs + secnum * shdr_size,
+				      sh_flags, Elf_Addr);
+	  sh_addr = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
+				     eow->shdrs + secnum * shdr_size,
+				     sh_addr, Elf_Addr);
+	  sh_link = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
+				     eow->shdrs + secnum * shdr_size,
+				     sh_link, Elf_Word);
+	  sh_info = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
+				     eow->shdrs + secnum * shdr_size,
+				     sh_info, Elf_Word);
+	  sh_addralign = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
+					  eow->shdrs + secnum * shdr_size,
+					  sh_addralign, Elf_Addr);
+	  sh_entsize = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
+					eow->shdrs + secnum * shdr_size,
+					sh_entsize, Elf_Addr);
+	  secnum++;
+	}
 
-      mask = (1U << section->align) - 1;
+      mask = sh_addralign - 1;
       new_sh_offset = sh_offset + mask;
       new_sh_offset &= ~ mask;
       while (new_sh_offset > sh_offset)
@@ -906,8 +1011,10 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
 	}
 
       if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
-					 sh_name, SHT_PROGBITS, 0, sh_offset,
-					 sh_size, 0, 1U << section->align,
+					 sh_name, sh_type, sh_flags,
+					 sh_addr, sh_offset,
+					 sh_size, sh_link, sh_info,
+					 sh_addralign, sh_entsize,
 					 &errmsg, err))
 	return errmsg;
 
@@ -917,9 +1024,9 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
     }
 
   if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
-				     sh_name, SHT_STRTAB, 0, sh_offset,
-				     sh_name + strlen (".shstrtab") + 1, 0,
-				     1, &errmsg, err))
+				     sh_name, SHT_STRTAB, 0, 0, sh_offset,
+				     sh_name + strlen (".shstrtab") + 1, 0, 0,
+				     1, 0, &errmsg, err))
     return errmsg;
 
   /* .shstrtab has a leading zero byte.  */
@@ -954,9 +1061,356 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
 static void
 simple_object_elf_release_write (void *data)
 {
+  struct simple_object_elf_write *eow = (struct simple_object_elf_write *) data;
+  if (eow->shdrs)
+    XDELETE (eow->shdrs);
   XDELETE (data);
 }
 
+/* Copy all sections in an ELF file.  */
+
+static const char *
+simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
+					   simple_object_write *dobj,
+					   int (*pfn) (const char **),
+					   int *err)
+{
+  struct simple_object_elf_read *eor =
+    (struct simple_object_elf_read *) sobj->data;
+  const struct elf_type_functions *type_functions = eor->type_functions;
+  struct simple_object_elf_write *eow =
+    (struct simple_object_elf_write *) dobj->data;
+  unsigned char ei_class = eor->ei_class;
+  size_t shdr_size;
+  unsigned int shnum;
+  unsigned char *shdrs;
+  const char *errmsg;
+  unsigned char *shstrhdr;
+  size_t name_size;
+  off_t shstroff;
+  unsigned char *names;
+  unsigned int i;
+  int *pfnret;
+  const char **pfnname;
+
+  shdr_size = (ei_class == ELFCLASS32
+	       ? sizeof (Elf32_External_Shdr)
+	       : sizeof (Elf64_External_Shdr));
+
+  /* Read the section headers.  We skip section 0, which is not a
+     useful section.  */
+
+  shnum = eor->shnum;
+  shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
+
+  if (!simple_object_internal_read (sobj->descriptor,
+				    sobj->offset + eor->shoff + shdr_size,
+				    shdrs,
+				    shdr_size * (shnum - 1),
+				    &errmsg, err))
+    {
+      XDELETEVEC (shdrs);
+      return errmsg;
+    }
+
+  /* Read the section names.  */
+
+  shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
+  name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+			       shstrhdr, sh_size, Elf_Addr);
+  shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+			      shstrhdr, sh_offset, Elf_Addr);
+  names = XNEWVEC (unsigned char, name_size);
+  if (!simple_object_internal_read (sobj->descriptor,
+				    sobj->offset + shstroff,
+				    names, name_size, &errmsg, err))
+    {
+      XDELETEVEC (names);
+      XDELETEVEC (shdrs);
+      return errmsg;
+    }
+
+  eow->shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
+  pfnret = XNEWVEC (int, shnum);
+  pfnname = XNEWVEC (const char *, shnum);
+
+  /* First perform the callbacks to know which sections to preserve and
+     what name to use for those.  */
+  for (i = 1; i < shnum; ++i)
+    {
+      unsigned char *shdr;
+      unsigned int sh_name;
+      const char *name;
+      int ret;
+
+      shdr = shdrs + (i - 1) * shdr_size;
+      sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				 shdr, sh_name, Elf_Word);
+      if (sh_name >= name_size)
+	{
+	  *err = 0;
+	  XDELETEVEC (names);
+	  XDELETEVEC (shdrs);
+	  return "ELF section name out of range";
+	}
+
+      name = (const char *) names + sh_name;
+
+      ret = (*pfn) (&name);
+      pfnret[i - 1] = ret == 1 ? 0 : -1;
+      pfnname[i - 1] = name;
+    }
+
+  /* Mark sections as preserved that are required by to be preserved
+     sections.  */
+  for (i = 1; i < shnum; ++i)
+    {
+      unsigned char *shdr;
+      unsigned int sh_type, sh_info, sh_link;
+      off_t offset;
+      off_t length;
+
+      shdr = shdrs + (i - 1) * shdr_size;
+      sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				 shdr, sh_type, Elf_Word);
+      sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				 shdr, sh_info, Elf_Word);
+      sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				 shdr, sh_link, Elf_Word);
+      if (sh_type == SHT_GROUP)
+	{
+	  /* Mark groups containing copied sections.  */
+	  unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+					      shdr, sh_entsize, Elf_Addr);
+	  unsigned char *ent, *buf;
+	  int keep = 0;
+	  offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				    shdr, sh_offset, Elf_Addr);
+	  length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				    shdr, sh_size, Elf_Addr);
+	  buf = XNEWVEC (unsigned char, length);
+	  if (!simple_object_internal_read (sobj->descriptor,
+					    sobj->offset + offset, buf,
+					    (size_t) length, &errmsg, err))
+	    {
+	      XDELETEVEC (buf);
+	      XDELETEVEC (names);
+	      XDELETEVEC (shdrs);
+	      return errmsg;
+	    }
+	  for (ent = buf + entsize; ent < buf + length; ent += entsize)
+	    {
+	      unsigned sec = type_functions->fetch_Elf_Word (ent);
+	      if (pfnret[sec - 1] == 0)
+		keep = 1;
+	    }
+	  if (keep)
+	    {
+	      pfnret[sh_link - 1] = 0;
+	      pfnret[i - 1] = 0;
+	    }
+	}
+      if (sh_type == SHT_RELA
+	  || sh_type == SHT_REL)
+	{
+	  /* Mark relocation sections and symtab of copied sections.  */
+	  if (pfnret[sh_info - 1] == 0)
+	    {
+	      pfnret[sh_link - 1] = 0;
+	      pfnret[i - 1] = 0;
+	    }
+	}
+      if (sh_type == SHT_SYMTAB)
+	{
+	  /* Mark strings sections of copied symtabs.  */
+	  if (pfnret[i - 1] == 0)
+	    pfnret[sh_link - 1] = 0;
+	}
+    }
+
+  /* Then perform the actual copying.  */
+  for (i = 1; i < shnum; ++i)
+    {
+      unsigned char *shdr;
+      unsigned int sh_name, sh_type;
+      const char *name;
+      off_t offset;
+      off_t length;
+      int ret;
+      const char *errmsg;
+      simple_object_write_section *dest;
+      off_t flags;
+      unsigned char *buf;
+
+      shdr = shdrs + (i - 1) * shdr_size;
+      sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				 shdr, sh_name, Elf_Word);
+      if (sh_name >= name_size)
+	{
+	  *err = 0;
+	  XDELETEVEC (names);
+	  XDELETEVEC (shdrs);
+	  return "ELF section name out of range";
+	}
+
+      name = (const char *) names + sh_name;
+      offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				shdr, sh_offset, Elf_Addr);
+      length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				shdr, sh_size, Elf_Addr);
+      sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				 shdr, sh_type, Elf_Word);
+
+      ret = pfnret[i - 1];
+      name = ret == 0 ? pfnname[i - 1] : "";
+
+      dest = simple_object_write_create_section (dobj, name, 0, &errmsg, err);
+      if (dest == NULL)
+	{
+	  XDELETEVEC (names);
+	  XDELETEVEC (shdrs);
+	  return errmsg;
+	}
+
+      /* Record the SHDR of the source.  */
+      memcpy (eow->shdrs + (i - 1) * shdr_size, shdr, shdr_size);
+      shdr = eow->shdrs + (i - 1) * shdr_size;
+
+      /* Copy the data.
+	 ???  This is quite wasteful and ideally would be delayed until
+	 write_to_file ().  Thus it questions the interfacing
+	 which eventually should contain destination creation plus
+	 writing.  */
+      /* Keep empty sections for sections we should discard.  This avoids
+         the need to rewrite section indices in symtab and relocation
+	 sections.  */
+      if (ret == 0)
+	{
+	  buf = XNEWVEC (unsigned char, length);
+	  if (!simple_object_internal_read (sobj->descriptor,
+					    sobj->offset + offset, buf,
+					    (size_t) length, &errmsg, err))
+	    {
+	      XDELETEVEC (buf);
+	      XDELETEVEC (names);
+	      XDELETEVEC (shdrs);
+	      return errmsg;
+	    }
+
+	  /* If we are processing .symtab purge __gnu_lto_v1 and
+	     __gnu_lto_slim symbols from it.  */
+	  if (sh_type == SHT_SYMTAB)
+	    {
+	      unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+						  shdr, sh_entsize, Elf_Addr);
+	      unsigned strtab = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+						 shdr, sh_link, Elf_Word);
+	      unsigned char *strshdr = shdrs + (strtab - 1) * shdr_size;
+	      off_t stroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+					      strshdr, sh_offset, Elf_Addr);
+	      size_t strsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+					      strshdr, sh_size, Elf_Addr);
+	      char *strings = XNEWVEC (char, strsz);
+	      unsigned char *ent;
+	      simple_object_internal_read (sobj->descriptor,
+					   sobj->offset + stroff,
+					   (unsigned char *)strings,
+					   strsz, &errmsg, err);
+	      for (ent = buf; ent < buf + length; ent += entsize)
+		{
+		  unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
+						       Sym, ent,
+						       st_shndx, Elf_Half);
+		  unsigned char *st_info;
+		  unsigned char *st_other;
+		  int discard = 0;
+		  if (ei_class == ELFCLASS32)
+		    {
+		      st_info = &((Elf32_External_Sym *)ent)->st_info;
+		      st_other = &((Elf32_External_Sym *)ent)->st_other;
+		    }
+		  else
+		    {
+		      st_info = &((Elf64_External_Sym *)ent)->st_info;
+		      st_other = &((Elf64_External_Sym *)ent)->st_other;
+		    }
+		  /* Eliminate all COMMONs - this includes __gnu_lto_v1
+		     and __gnu_lto_slim which otherwise cause endless
+		     LTO plugin invocation.  */
+		  if (st_shndx == SHN_COMMON)
+		    /* Setting st_name to "" seems to work to purge
+		       COMMON symbols (in addition to setting their
+		       size to zero).  */
+		    discard = 1;
+		  /* We also need to remove symbols refering to sections
+		     we'll eventually remove as with fat LTO objects
+		     we otherwise get duplicate symbols at final link
+		     (with GNU ld, gold is fine and ignores symbols in
+		     sections marked as EXCLUDE).  ld/20513  */
+		  else if (st_shndx != SHN_UNDEF
+			   && st_shndx < shnum
+			   && pfnret[st_shndx - 1] == -1)
+		    discard = 1;
+
+		  if (discard)
+		    {
+		      /* Make discarded symbols undefined and unnamed
+		         in case it is local.  */
+		      if (ELF_ST_BIND (*st_info) == STB_LOCAL)
+			ELF_SET_FIELD (type_functions, ei_class, Sym,
+				       ent, st_name, Elf_Word, 0);
+		      ELF_SET_FIELD (type_functions, ei_class, Sym,
+				     ent, st_value, Elf_Addr, 0);
+		      ELF_SET_FIELD (type_functions, ei_class, Sym,
+				     ent, st_size, Elf_Word, 0);
+		      ELF_SET_FIELD (type_functions, ei_class, Sym,
+				     ent, st_shndx, Elf_Half, SHN_UNDEF);
+		      *st_info = ELF_ST_INFO (ELF_ST_BIND (*st_info),
+					      STT_NOTYPE);
+		      *st_other = STV_DEFAULT;
+		    }
+		}
+	      XDELETEVEC (strings);
+	    }
+
+	  errmsg = simple_object_write_add_data (dobj, dest,
+						 buf, length, 1, err);
+	  XDELETEVEC (buf);
+	  if (errmsg)
+	    {
+	      XDELETEVEC (names);
+	      XDELETEVEC (shdrs);
+	      return errmsg;
+	    }
+	}
+      else
+	{
+	  /* For deleted sections mark the section header table entry as
+	     unused.  That allows the link editor to remove it in a partial
+	     link.  */
+	  ELF_SET_FIELD (type_functions, ei_class, Shdr,
+			 shdr, sh_type, Elf_Word, SHT_NULL);
+	}
+
+      flags = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+			       shdr, sh_flags, Elf_Addr);
+      if (ret == 0)
+	flags &= ~SHF_EXCLUDE;
+      else if (ret == -1)
+	flags = SHF_EXCLUDE;
+      ELF_SET_FIELD (type_functions, ei_class, Shdr,
+		     shdr, sh_flags, Elf_Addr, flags);
+    }
+
+  XDELETEVEC (names);
+  XDELETEVEC (shdrs);
+  XDELETEVEC (pfnret);
+  XDELETEVEC (pfnname);
+
+  return NULL;
+}
+
+
 /* The ELF functions.  */
 
 const struct simple_object_functions simple_object_elf_functions =
@@ -969,5 +1423,6 @@ const struct simple_object_functions simple_object_elf_functions =
   simple_object_elf_release_attributes,
   simple_object_elf_start_write,
   simple_object_elf_write_to_file,
-  simple_object_elf_release_write
+  simple_object_elf_release_write,
+  simple_object_elf_copy_lto_debug_sections
 };
diff --git a/libiberty/simple-object-mach-o.c b/libiberty/simple-object-mach-o.c
index bbadf5d..b90fca8 100644
--- a/libiberty/simple-object-mach-o.c
+++ b/libiberty/simple-object-mach-o.c
@@ -1374,5 +1374,6 @@ const struct simple_object_functions simple_object_mach_o_functions =
   simple_object_mach_o_release_attributes,
   simple_object_mach_o_start_write,
   simple_object_mach_o_write_to_file,
-  simple_object_mach_o_release_write
+  simple_object_mach_o_release_write,
+  NULL
 };
diff --git a/libiberty/simple-object-xcoff.c b/libiberty/simple-object-xcoff.c
index 8a15939..9a8f581 100644
--- a/libiberty/simple-object-xcoff.c
+++ b/libiberty/simple-object-xcoff.c
@@ -138,15 +138,15 @@ struct external_syment
   union {
     struct {
       union {
-        /* The name of the symbol.  There is an implicit null character
-           after the end of the array.  */
-        char n_name[N_SYMNMLEN];
-        struct {
-          /* If n_zeroes is zero, n_offset is the offset the name from
-             the start of the string table.  */
-          unsigned char n_zeroes[4];
-          unsigned char n_offset[4];
-        } n;
+/* The name of the symbol.  There is an implicit null character
+   after the end of the array.  */
+	char n_name[N_SYMNMLEN];
+	struct {
+	  /* If n_zeroes is zero, n_offset is the offset the name from
+	     the start of the string table.  */
+	  unsigned char n_zeroes[4];
+	  unsigned char n_offset[4];
+	} n;
       } n;
 
       /* The symbol's value.  */
@@ -255,8 +255,14 @@ union external_auxent
 #define IMAGE_SYM_TYPE \
   ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL)
 
+#define C_EXT		(2)
 #define C_STAT		(3)
 #define C_FILE		(103)
+#define C_HIDEXT	(107)
+
+#define XTY_SD		(1)	/* section definition */
+
+#define XMC_XO		(7)	/* extended operation */
 
 /* Private data for an simple_object_read.  */
 
@@ -398,11 +404,13 @@ simple_object_xcoff_find_sections (simple_object_read *sobj,
   size_t scnhdr_size;
   unsigned char *scnbuf;
   const char *errmsg;
+  unsigned short (*fetch_16) (const unsigned char *);
   unsigned int (*fetch_32) (const unsigned char *);
   ulong_type (*fetch_64) (const unsigned char *);
   unsigned int nscns;
   char *strtab;
   size_t strtab_size;
+  struct external_syment *symtab = NULL;
   unsigned int i;
 
   scnhdr_size = u64 ? SCNHSZ64 : SCNHSZ32;
@@ -416,6 +424,7 @@ simple_object_xcoff_find_sections (simple_object_read *sobj,
       return errmsg;
     }
 
+  fetch_16 = simple_object_fetch_big_16;
   fetch_32 = simple_object_fetch_big_32;
   fetch_64 = simple_object_fetch_big_64;
 
@@ -429,7 +438,7 @@ simple_object_xcoff_find_sections (simple_object_read *sobj,
       char namebuf[SCNNMLEN + 1];
       char *name;
       off_t scnptr;
-      unsigned int size;
+      off_t size;
 
       scnhdr = scnbuf + i * scnhdr_size;
       scnname = scnhdr + offsetof (struct external_scnhdr, s_name);
@@ -489,6 +498,151 @@ simple_object_xcoff_find_sections (simple_object_read *sobj,
 	break;
     }
 
+  /* Special handling for .go_export csect.  */
+  if (ocr->nsyms > 0)
+    {
+      unsigned char *sym;
+      const char *n_name;
+      off_t size, n_value;
+      unsigned int n_numaux, n_offset, n_zeroes;
+      short n_scnum;
+
+      /* Read symbol table.  */
+      symtab = XNEWVEC (struct external_syment, ocr->nsyms * SYMESZ);
+      if (!simple_object_internal_read (sobj->descriptor,
+					sobj->offset + ocr->symptr,
+					(unsigned char *) symtab,
+					ocr->nsyms * SYMESZ,
+					&errmsg, err))
+	{
+	  XDELETEVEC (symtab);
+	  XDELETEVEC (scnbuf);
+	  return NULL;
+	}
+
+      /* Search in symbol table if we have a ".go_export" symbol.  */
+      for (i = 0; i < ocr->nsyms; i += n_numaux + 1)
+	{
+	  sym = (unsigned char *) &symtab[i];
+	  n_numaux = symtab[i].n_numaux[0];
+
+	  if (symtab[i].n_sclass[0] != C_EXT
+	      && symtab[i].n_sclass[0] != C_HIDEXT)
+	    continue;
+
+	  /* Must have at least one csect auxiliary entry.  */
+	  if (n_numaux < 1 || i + n_numaux >= ocr->nsyms)
+	    continue;
+
+	  n_scnum = fetch_16 (sym + offsetof (struct external_syment,
+					      n_scnum));
+	  if (n_scnum < 1 || (unsigned int) n_scnum > nscns)
+	    continue;
+
+	  if (u64)
+	    {
+	      n_value = fetch_64 (sym + offsetof (struct external_syment,
+						  u.xcoff64.n_value));
+	      n_offset = fetch_32 (sym + offsetof (struct external_syment,
+						   u.xcoff64.n_offset));
+	    }
+	  else
+	    {
+	      /* ".go_export" is longer than N_SYMNMLEN.  */
+	      n_zeroes = fetch_32 (sym + offsetof (struct external_syment,
+						   u.xcoff32.n.n.n_zeroes));
+	      if (n_zeroes != 0)
+		continue;
+
+	      n_value = fetch_32 (sym + offsetof (struct external_syment,
+						  u.xcoff32.n_value));
+	      n_offset = fetch_32 (sym + offsetof (struct external_syment,
+						   u.xcoff32.n.n.n_offset));
+	    }
+
+	  /* The real symbol name is found in the string table.  */
+	  if (strtab == NULL)
+	    {
+	      strtab = simple_object_xcoff_read_strtab (sobj,
+	  						&strtab_size,
+							&errmsg, err);
+	      if (strtab == NULL)
+		{
+		  XDELETEVEC (symtab);
+		  XDELETEVEC (scnbuf);
+		  return errmsg;
+		}
+	    }
+
+	  if (n_offset >= strtab_size)
+	    {
+	      XDELETEVEC (strtab);
+	      XDELETEVEC (symtab);
+	      XDELETEVEC (scnbuf);
+	      *err = 0;
+	      return "symbol string index out of range";
+	    }
+	  n_name = strtab + n_offset;
+
+	  if (!strcmp (n_name, ".go_export"))
+	    {
+	      union external_auxent *auxent;
+	      unsigned char *aux, *scnhdr;
+	      off_t scnptr, x_scnlen;
+
+	      /* Found .go_export symbol, read its csect auxiliary entry.
+		 By convention, it is the last auxiliary entry.  */
+	      auxent = (union external_auxent *) &symtab[i + n_numaux];
+	      aux = (unsigned char *) auxent;
+	      if (u64)
+		{
+		  if ((auxent->u.xcoff64.x_csect.x_smtyp & 0x7) != XTY_SD
+		      || auxent->u.xcoff64.x_csect.x_smclas != XMC_XO)
+		    continue;
+
+		  x_scnlen = fetch_32 (aux + offsetof (union external_auxent,
+						       u.xcoff64.x_csect.x_scnlen_hi));
+		  x_scnlen = x_scnlen << 32
+			   | fetch_32 (aux + offsetof (union external_auxent,
+						       u.xcoff64.x_csect.x_scnlen_lo));
+		}
+	      else
+		{
+		  if ((auxent->u.xcoff32.x_csect.x_smtyp & 0x7) != XTY_SD
+		      || auxent->u.xcoff32.x_csect.x_smclas != XMC_XO)
+		    continue;
+
+		  x_scnlen = fetch_32 (aux + offsetof (union external_auxent,
+						       u.xcoff32.x_csect.x_scnlen));
+		}
+
+	      /* Get header of containing section.  */
+	      scnhdr = scnbuf + (n_scnum - 1) * scnhdr_size;
+	      if (u64)
+		{
+		  scnptr = fetch_64 (scnhdr + offsetof (struct external_scnhdr,
+							u.xcoff64.s_scnptr));
+		  size = fetch_64 (scnhdr + offsetof (struct external_scnhdr,
+						      u.xcoff64.s_size));
+		}
+	      else
+		{
+		  scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr,
+							u.xcoff32.s_scnptr));
+		  size = fetch_32 (scnhdr + offsetof (struct external_scnhdr,
+						      u.xcoff32.s_size));
+		}
+	      if (n_value + x_scnlen > size)
+		break;
+
+	      (*pfn) (data, ".go_export", scnptr + n_value, x_scnlen);
+	      break;
+	    }
+	}
+    }
+
+  if (symtab != NULL)
+    XDELETEVEC (symtab);
   if (strtab != NULL)
     XDELETEVEC (strtab);
   XDELETEVEC (scnbuf);
@@ -894,5 +1048,6 @@ const struct simple_object_functions simple_object_xcoff_functions =
   simple_object_xcoff_release_attributes,
   simple_object_xcoff_start_write,
   simple_object_xcoff_write_to_file,
-  simple_object_xcoff_release_write
+  simple_object_xcoff_release_write,
+  NULL
 };
diff --git a/libiberty/simple-object.c b/libiberty/simple-object.c
index 8ea9cf1..553e90f 100644
--- a/libiberty/simple-object.c
+++ b/libiberty/simple-object.c
@@ -22,6 +22,7 @@ Boston, MA 02110-1301, USA.  */
 #include "simple-object.h"
 
 #include <errno.h>
+#include <fcntl.h>
 
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
@@ -249,6 +250,86 @@ simple_object_find_section (simple_object_read *sobj, const char *name,
   return 1;
 }
 
+/* Callback to identify and rename LTO debug sections by name.
+   Returns 1 if NAME is a LTO debug section, 0 if not.  */
+
+static int
+handle_lto_debug_sections (const char **name)
+{
+  /* ???  So we can't use .gnu.lto_ prefixed sections as the assembler
+     complains about bogus section flags.  Which means we need to arrange
+     for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make
+     fat lto object tooling work for the fat part).  */
+  /* ???  For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
+     sections.  */
+  /* Copy LTO debug sections and rename them to their non-LTO name.  */
+  if (strncmp (*name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
+    {
+      *name = *name + sizeof (".gnu.debuglto_") - 1;
+      return 1;
+    }
+  else if (strncmp (*name, ".gnu.lto_.debug_", sizeof (".gnu.lto_.debug_") -1) == 0)
+    {
+      *name = *name + sizeof (".gnu.lto_") - 1;
+      return 1;
+    }
+  return 0;
+}
+
+/* Copy LTO debug sections.  */
+
+const char *
+simple_object_copy_lto_debug_sections (simple_object_read *sobj,
+				       const char *dest, int *err)
+{
+  const char *errmsg;
+  simple_object_write *dest_sobj;
+  simple_object_attributes *attrs;
+  int outfd;
+
+  if (! sobj->functions->copy_lto_debug_sections)
+    {
+      *err = EINVAL;
+      return "simple_object_copy_lto_debug_sections not implemented";
+    }
+
+  attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
+  if (! attrs)
+    return errmsg;
+  dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
+  simple_object_release_attributes (attrs);
+  if (! dest_sobj)
+    return errmsg;
+
+  errmsg = sobj->functions->copy_lto_debug_sections (sobj, dest_sobj,
+						     handle_lto_debug_sections,
+						     err);
+  if (errmsg)
+    {
+      simple_object_release_write (dest_sobj);
+      return errmsg;
+    }
+
+  outfd = creat (dest, 00777);
+  if (outfd == -1)
+    {
+      *err = errno;
+      simple_object_release_write (dest_sobj);
+      return "open failed";
+    }
+
+  errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
+  close (outfd);
+  if (errmsg)
+    {
+      simple_object_release_write (dest_sobj);
+      return errmsg;
+    }
+
+  simple_object_release_write (dest_sobj);
+  return NULL;
+}
+
 /* Fetch attributes.  */
 
 simple_object_attributes *
@@ -315,7 +396,7 @@ simple_object_start_write (simple_object_attributes *attrs,
     return NULL;
   ret = XNEW (simple_object_write);
   ret->functions = attrs->functions;
-  ret->segment_name = xstrdup (segment_name);
+  ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
   ret->sections = NULL;
   ret->last_section = NULL;
   ret->data = data;


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-03-02 12:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-02 12:03 [binutils-gdb] Import latest fixes to libiberty from GCC H.J.Lu
  -- strict thread matches above, loose matches on Subject: below --
2017-09-01 13:15 H.J.Lu
2017-09-01  9:54 Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).