]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/bfd.c
bfd_get_relocated_section_contents allow NULL data buffer
[thirdparty/binutils-gdb.git] / bfd / bfd.c
index 6e5d3397d151c738c95c07e8ade6f5b6c0075d9b..97ce2b104504d3f217afff431c084ef2c4c9c551 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -1,5 +1,5 @@
 /* Generic BFD library interface and support routines.
-   Copyright (C) 1990-2021 Free Software Foundation, Inc.
+   Copyright (C) 1990-2022 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -176,11 +176,16 @@ CODE_FRAGMENT
 .  {* Put pathnames into archives (non-POSIX).  *}
 .#define BFD_ARCHIVE_FULL_PATH  0x100000
 .
+.#define BFD_CLOSED_BY_CACHE    0x200000
+
+.  {* Compress sections in this BFD with SHF_COMPRESSED zstd.  *}
+.#define BFD_COMPRESS_ZSTD      0x400000
+.
 .  {* Flags bits to be saved in bfd_preserve_save.  *}
 .#define BFD_FLAGS_SAVED \
 .  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
 .   | BFD_PLUGIN | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON \
-.   | BFD_USE_ELF_STT_COMMON)
+.   | BFD_USE_ELF_STT_COMMON | BFD_COMPRESS_ZSTD)
 .
 .  {* Flags bits which are for BFD use only.  *}
 .#define BFD_FLAGS_FOR_BFD_USE_MASK \
@@ -276,10 +281,19 @@ CODE_FRAGMENT
 .  {* The number of sections.  *}
 .  unsigned int section_count;
 .
+.  {* The archive plugin file descriptor.  *}
+.  int archive_plugin_fd;
+.
+.  {* The number of opens on the archive plugin file descriptor.  *}
+.  unsigned int archive_plugin_fd_open_count;
+.
 .  {* A field used by _bfd_generic_link_add_archive_symbols.  This will
 .     be used only for archive elements.  *}
 .  int archive_pass;
 .
+.  {* The total size of memory from bfd_alloc.  *}
+.  bfd_size_type alloc_size;
+.
 .  {* Stuff only useful for object files:
 .     The start address.  *}
 .  bfd_vma start_address;
@@ -504,6 +518,14 @@ CODE_FRAGMENT
 .         / bfd_octets_per_byte (abfd, sec));
 .}
 .
+.static inline bfd_size_type
+.bfd_get_section_alloc_size (const bfd *abfd, const asection *sec)
+.{
+.  if (abfd->direction != write_direction && sec->rawsize > sec->size)
+.    return sec->rawsize;
+.  return sec->size;
+.}
+.
 .{* Functions to handle insertion and deletion of a bfd's sections.  These
 .   only handle the list pointers, ie. do not adjust section_count,
 .   target_index etc.  *}
@@ -876,6 +898,10 @@ union _bfd_doprnt_args
   } type;
 };
 
+/* Maximum number of _bfd_error_handler args.  Don't increase this
+   without changing the code handling positional parameters.  */
+#define MAX_ARGS 9
+
 /* This macro and _bfd_doprnt taken from libiberty _doprnt.c, tidied a
    little and extended to handle '%pA', '%pB' and positional parameters.  */
 
@@ -883,11 +909,14 @@ union _bfd_doprnt_args
   do                                                           \
     {                                                          \
       TYPE value = (TYPE) args[arg_no].FIELD;                  \
-      result = fprintf (stream, specifier, value);             \
+      result = print (stream, specifier, value);               \
     } while (0)
 
+typedef int (*print_func) (void *, const char *, ...);
+
 static int
-_bfd_doprnt (FILE *stream, const char *format, union _bfd_doprnt_args *args)
+_bfd_doprnt (print_func print, void *stream, const char *format,
+            union _bfd_doprnt_args *args)
 {
   const char *ptr = format;
   char specifier[128];
@@ -903,9 +932,9 @@ _bfd_doprnt (FILE *stream, const char *format, union _bfd_doprnt_args *args)
          /* While we have regular characters, print them.  */
          char *end = strchr (ptr, '%');
          if (end != NULL)
-           result = fprintf (stream, "%.*s", (int) (end - ptr), ptr);
+           result = print (stream, "%.*s", (int) (end - ptr), ptr);
          else
-           result = fprintf (stream, "%s", ptr);
+           result = print (stream, "%s", ptr);
          ptr += result;
        }
       else if (ptr[1] == '%')
@@ -1089,9 +1118,9 @@ _bfd_doprnt (FILE *stream, const char *format, union _bfd_doprnt_args *args)
                                                                 sec)) != NULL)
                    group = ci->name;
                  if (group != NULL)
-                   result = fprintf (stream, "%s[%s]", sec->name, group);
+                   result = print (stream, "%s[%s]", sec->name, group);
                  else
-                   result = fprintf (stream, "%s", sec->name);
+                   result = print (stream, "%s", sec->name);
                }
              else if (*ptr == 'B')
                {
@@ -1105,11 +1134,11 @@ _bfd_doprnt (FILE *stream, const char *format, union _bfd_doprnt_args *args)
                    abort ();
                  else if (abfd->my_archive
                           && !bfd_is_thin_archive (abfd->my_archive))
-                   result = fprintf (stream, "%s(%s)",
-                                     bfd_get_filename (abfd->my_archive),
-                                     bfd_get_filename (abfd));
+                   result = print (stream, "%s(%s)",
+                                   bfd_get_filename (abfd->my_archive),
+                                   bfd_get_filename (abfd));
                  else
-                   result = fprintf (stream, "%s", bfd_get_filename (abfd));
+                   result = print (stream, "%s", bfd_get_filename (abfd));
                }
              else
                PRINT_TYPE (void *, p);
@@ -1130,11 +1159,14 @@ _bfd_doprnt (FILE *stream, const char *format, union _bfd_doprnt_args *args)
 /* First pass over FORMAT to gather ARGS.  Returns number of args.  */
 
 static unsigned int
-_bfd_doprnt_scan (const char *format, union _bfd_doprnt_args *args)
+_bfd_doprnt_scan (const char *format, va_list ap, union _bfd_doprnt_args *args)
 {
   const char *ptr = format;
   unsigned int arg_count = 0;
 
+  for (unsigned int i = 0; i < MAX_ARGS; i++)
+    args[i].type = Bad;
+
   while (*ptr != '\0')
     {
       if (*ptr != '%')
@@ -1176,7 +1208,7 @@ _bfd_doprnt_scan (const char *format, union _bfd_doprnt_args *args)
                  arg_index = *ptr - '1';
                  ptr += 2;
                }
-             if (arg_index >= 9)
+             if (arg_index >= MAX_ARGS)
                abort ();
              args[arg_index].type = Int;
              arg_count++;
@@ -1201,7 +1233,7 @@ _bfd_doprnt_scan (const char *format, union _bfd_doprnt_args *args)
                      arg_index = *ptr - '1';
                      ptr += 2;
                    }
-                 if (arg_index >= 9)
+                 if (arg_index >= MAX_ARGS)
                    abort ();
                  args[arg_index].type = Int;
                  arg_count++;
@@ -1289,27 +1321,14 @@ _bfd_doprnt_scan (const char *format, union _bfd_doprnt_args *args)
              abort();
            }
 
-         if (arg_no >= 9)
+         if (arg_no >= MAX_ARGS)
            abort ();
          args[arg_no].type = arg_type;
          arg_count++;
        }
     }
 
-  return arg_count;
-}
-
-static void
-error_handler_internal (const char *fmt, va_list ap)
-{
-  unsigned int i, arg_count;
-  union _bfd_doprnt_args args[9];
-
-  for (i = 0; i < sizeof (args) / sizeof (args[0]); i++)
-    args[i].type = Bad;
-
-  arg_count = _bfd_doprnt_scan (fmt, args);
-  for (i = 0; i < arg_count; i++)
+  for (unsigned int i = 0; i < arg_count; i++)
     {
       switch (args[i].type)
        {
@@ -1336,15 +1355,24 @@ error_handler_internal (const char *fmt, va_list ap)
        }
     }
 
+  return arg_count;
+}
+
+/* The standard error handler that prints to stderr.  */
+
+static void
+error_handler_fprintf (const char *fmt, va_list ap)
+{
+  union _bfd_doprnt_args args[MAX_ARGS];
+
+  _bfd_doprnt_scan (fmt, ap, args);
+
   /* PR 4992: Don't interrupt output being sent to stdout.  */
   fflush (stdout);
 
-  if (_bfd_error_program_name != NULL)
-    fprintf (stderr, "%s: ", _bfd_error_program_name);
-  else
-    fprintf (stderr, "BFD: ");
+  fprintf (stderr, "%s: ", _bfd_get_error_program_name ());
 
-  _bfd_doprnt (stderr, fmt, args);
+  _bfd_doprnt ((print_func) fprintf, stderr, fmt, args);
 
   /* On AIX, putc is implemented as a macro that triggers a -Wunused-value
      warning, so use the fputc function to avoid it.  */
@@ -1352,13 +1380,77 @@ error_handler_internal (const char *fmt, va_list ap)
   fflush (stderr);
 }
 
+/* Control printing to a string buffer.  */
+struct buf_stream
+{
+  char *ptr;
+  int left;
+};
+
+/* An fprintf like function that instead prints to a string buffer.  */
+
+static int
+err_sprintf (void *stream, const char *fmt, ...)
+{
+  struct buf_stream *s = stream;
+  va_list ap;
+
+  va_start (ap, fmt);
+  int total = vsnprintf (s->ptr, s->left, fmt, ap);
+  va_end (ap);
+  if (total < 0)
+    ;
+  else if (total > s->left)
+    {
+      s->ptr += s->left;
+      s->left = 0;
+    }
+  else
+    {
+      s->ptr += total;
+      s->left -= total;
+    }
+  return total;
+}
+
+/* Communicate the bfd processed by bfd_check_format_matches to the
+   error handling function error_handler_sprintf.  */
+
+static bfd *error_handler_bfd;
+
+/* An error handler that prints to a string, then dups that string to
+   a per-xvec cache.  */
+
+static void
+error_handler_sprintf (const char *fmt, va_list ap)
+{
+  union _bfd_doprnt_args args[MAX_ARGS];
+  char error_buf[1024];
+  struct buf_stream error_stream;
+
+  _bfd_doprnt_scan (fmt, ap, args);
+
+  error_stream.ptr = error_buf;
+  error_stream.left = sizeof (error_buf);
+  _bfd_doprnt (err_sprintf, &error_stream, fmt, args);
+
+  size_t len = error_stream.ptr - error_buf;
+  struct per_xvec_message **warn
+    = _bfd_per_xvec_warn (error_handler_bfd->xvec, len + 1);
+  if (*warn)
+    {
+      memcpy ((*warn)->message, error_buf, len);
+      (*warn)->message[len] = 0;
+    }
+}
+
 /* This is a function pointer to the routine which should handle BFD
    error messages.  It is called when a BFD routine encounters an
    error for which it wants to print a message.  Going through a
    function pointer permits a program linked against BFD to intercept
    the messages and deal with them itself.  */
 
-static bfd_error_handler_type _bfd_error_internal = error_handler_internal;
+static bfd_error_handler_type _bfd_error_internal = error_handler_fprintf;
 
 /*
 FUNCTION
@@ -1412,6 +1504,25 @@ bfd_set_error_handler (bfd_error_handler_type pnew)
   return pold;
 }
 
+/*
+INTERNAL_FUNCTION
+       _bfd_set_error_handler_caching
+
+SYNOPSIS
+       bfd_error_handler_type _bfd_set_error_handler_caching (bfd *);
+
+DESCRIPTION
+       Set the BFD error handler function to one that stores messages
+       to the per_xvec_warn array.  Returns the previous function.
+*/
+
+bfd_error_handler_type
+_bfd_set_error_handler_caching (bfd *abfd)
+{
+  error_handler_bfd = abfd;
+  return bfd_set_error_handler (error_handler_sprintf);
+}
+
 /*
 FUNCTION
        bfd_set_error_program_name
@@ -1432,6 +1543,25 @@ bfd_set_error_program_name (const char *name)
   _bfd_error_program_name = name;
 }
 
+/*
+INTERNAL_FUNCTION
+       _bfd_get_error_program_name
+
+SYNOPSIS
+       const char *_bfd_get_error_program_name (void);
+
+DESCRIPTION
+       Get the program name used when printing a BFD error.
+*/
+
+const char *
+_bfd_get_error_program_name (void)
+{
+  if (_bfd_error_program_name != NULL)
+    return _bfd_error_program_name;
+  return "BFD";
+}
+
 /*
 SUBSECTION
        BFD assert handler
@@ -1729,8 +1859,11 @@ bfd_get_sign_extend_vma (bfd *abfd)
       || strcmp (name, "pei-i386") == 0
       || strcmp (name, "pe-x86-64") == 0
       || strcmp (name, "pei-x86-64") == 0
+      || strcmp (name, "pe-aarch64-little") == 0
+      || strcmp (name, "pei-aarch64-little") == 0
       || strcmp (name, "pe-arm-wince-little") == 0
       || strcmp (name, "pei-arm-wince-little") == 0
+      || strcmp (name, "pei-loongarch64") == 0
       || strcmp (name, "aixcoff-rs6000") == 0
       || strcmp (name, "aix5coff64-rs6000") == 0)
     return 1;
@@ -1851,6 +1984,24 @@ _bfd_set_gp_value (bfd *abfd, bfd_vma v)
     elf_gp (abfd) = v;
 }
 
+/*
+FUNCTION
+       bfd_set_gp_value
+
+SYNOPSIS
+       void bfd_set_gp_value (bfd *abfd, bfd_vma v);
+
+DESCRIPTION
+       Allow external access to the fucntion to set the GP value.
+       This is specifically added for gdb-compile support.
+*/
+
+void
+bfd_set_gp_value (bfd *abfd, bfd_vma v)
+{
+  _bfd_set_gp_value (abfd, v);
+}
+
 /*
 FUNCTION
        bfd_scan_vma
@@ -2019,6 +2170,11 @@ DESCRIPTION
 .      BFD_SEND (abfd, _bfd_find_nearest_line, \
 .                (abfd, syms, sec, off, file, func, line, NULL))
 .
+.#define bfd_find_nearest_line_with_alt(abfd, alt_filename, sec, syms, off, \
+.                                      file, func, line, disc) \
+.      BFD_SEND (abfd, _bfd_find_nearest_line_with_alt, \
+.                (abfd, alt_filename, syms, sec, off, file, func, line, disc))
+.
 .#define bfd_find_nearest_line_discriminator(abfd, sec, syms, off, file, func, \
 .                                          line, disc) \
 .      BFD_SEND (abfd, _bfd_find_nearest_line, \
@@ -2208,26 +2364,26 @@ void
 bfd_sprintf_vma (bfd *abfd ATTRIBUTE_UNUSED, char *buf, bfd_vma value)
 {
 #ifdef BFD64
-  if (is32bit (abfd))
+  if (!is32bit (abfd))
     {
-      sprintf (buf, "%08lx", (unsigned long) value & 0xffffffff);
+      sprintf (buf, "%016" PRIx64, (uint64_t) value);
       return;
     }
 #endif
-  sprintf_vma (buf, value);
+  sprintf (buf, "%08lx", (unsigned long) value & 0xffffffff);
 }
 
 void
 bfd_fprintf_vma (bfd *abfd ATTRIBUTE_UNUSED, void *stream, bfd_vma value)
 {
 #ifdef BFD64
-  if (is32bit (abfd))
+  if (!is32bit (abfd))
     {
-      fprintf ((FILE *) stream, "%08lx", (unsigned long) value & 0xffffffff);
+      fprintf ((FILE *) stream, "%016" PRIx64, (uint64_t) value);
       return;
     }
 #endif
-  fprintf_vma ((FILE *) stream, value);
+  fprintf ((FILE *) stream, "%08lx", (unsigned long) value & 0xffffffff);
 }
 
 /*
@@ -2316,7 +2472,7 @@ FUNCTION
        bfd_emul_get_commonpagesize
 
 SYNOPSIS
-       bfd_vma bfd_emul_get_commonpagesize (const char *, bool);
+       bfd_vma bfd_emul_get_commonpagesize (const char *);
 
 DESCRIPTION
        Returns the common page size, in bytes, as determined by
@@ -2327,7 +2483,7 @@ RETURNS
 */
 
 bfd_vma
-bfd_emul_get_commonpagesize (const char *emul, bool relro)
+bfd_emul_get_commonpagesize (const char *emul)
 {
   const bfd_target *target;
 
@@ -2338,10 +2494,7 @@ bfd_emul_get_commonpagesize (const char *emul, bool relro)
       const struct elf_backend_data *bed;
 
       bed = xvec_get_elf_backend_data (target);
-      if (relro)
-       return bed->relropagesize;
-      else
-       return bed->commonpagesize;
+      return bed->commonpagesize;
     }
   return 0;
 }
@@ -2440,351 +2593,6 @@ bfd_demangle (bfd *abfd, const char *name, int options)
   return res;
 }
 
-/*
-FUNCTION
-       bfd_update_compression_header
-
-SYNOPSIS
-       void bfd_update_compression_header
-         (bfd *abfd, bfd_byte *contents, asection *sec);
-
-DESCRIPTION
-       Set the compression header at CONTENTS of SEC in ABFD and update
-       elf_section_flags for compression.
-*/
-
-void
-bfd_update_compression_header (bfd *abfd, bfd_byte *contents,
-                              asection *sec)
-{
-  if ((abfd->flags & BFD_COMPRESS) == 0)
-    abort ();
-
-  switch (bfd_get_flavour (abfd))
-    {
-    case bfd_target_elf_flavour:
-      if ((abfd->flags & BFD_COMPRESS_GABI) != 0)
-       {
-         const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-         struct bfd_elf_section_data * esd = elf_section_data (sec);
-
-         /* Set the SHF_COMPRESSED bit.  */
-         elf_section_flags (sec) |= SHF_COMPRESSED;
-
-         if (bed->s->elfclass == ELFCLASS32)
-           {
-             Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents;
-             bfd_put_32 (abfd, ELFCOMPRESS_ZLIB, &echdr->ch_type);
-             bfd_put_32 (abfd, sec->size, &echdr->ch_size);
-             bfd_put_32 (abfd, 1 << sec->alignment_power,
-                         &echdr->ch_addralign);
-             /* bfd_log2 (alignof (Elf32_Chdr)) */
-             bfd_set_section_alignment (sec, 2);
-             esd->this_hdr.sh_addralign = 4;
-           }
-         else
-           {
-             Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents;
-             bfd_put_32 (abfd, ELFCOMPRESS_ZLIB, &echdr->ch_type);
-             bfd_put_32 (abfd, 0, &echdr->ch_reserved);
-             bfd_put_64 (abfd, sec->size, &echdr->ch_size);
-             bfd_put_64 (abfd, 1 << sec->alignment_power,
-                         &echdr->ch_addralign);
-             /* bfd_log2 (alignof (Elf64_Chdr)) */
-             bfd_set_section_alignment (sec, 3);
-             esd->this_hdr.sh_addralign = 8;
-           }
-         break;
-       }
-
-      /* Clear the SHF_COMPRESSED bit.  */
-      elf_section_flags (sec) &= ~SHF_COMPRESSED;
-      /* Fall through.  */
-
-    default:
-      /* Write the zlib header.  It should be "ZLIB" followed by
-        the uncompressed section size, 8 bytes in big-endian
-        order.  */
-      memcpy (contents, "ZLIB", 4);
-      bfd_putb64 (sec->size, contents + 4);
-      /* No way to keep the original alignment, just use 1 always. */
-      bfd_set_section_alignment (sec, 0);
-      break;
-    }
-}
-
-/*
-   FUNCTION
-   bfd_check_compression_header
-
-   SYNOPSIS
-       bool bfd_check_compression_header
-         (bfd *abfd, bfd_byte *contents, asection *sec,
-         bfd_size_type *uncompressed_size,
-         unsigned int *uncompressed_alignment_power);
-
-DESCRIPTION
-       Check the compression header at CONTENTS of SEC in ABFD and
-       store the uncompressed size in UNCOMPRESSED_SIZE and the
-       uncompressed data alignment in UNCOMPRESSED_ALIGNMENT_POWER
-       if the compression header is valid.
-
-RETURNS
-       Return TRUE if the compression header is valid.
-*/
-
-bool
-bfd_check_compression_header (bfd *abfd, bfd_byte *contents,
-                             asection *sec,
-                             bfd_size_type *uncompressed_size,
-                             unsigned int *uncompressed_alignment_power)
-{
-  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
-      && (elf_section_flags (sec) & SHF_COMPRESSED) != 0)
-    {
-      Elf_Internal_Chdr chdr;
-      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-      if (bed->s->elfclass == ELFCLASS32)
-       {
-         Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents;
-         chdr.ch_type = bfd_get_32 (abfd, &echdr->ch_type);
-         chdr.ch_size = bfd_get_32 (abfd, &echdr->ch_size);
-         chdr.ch_addralign = bfd_get_32 (abfd, &echdr->ch_addralign);
-       }
-      else
-       {
-         Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents;
-         chdr.ch_type = bfd_get_32 (abfd, &echdr->ch_type);
-         chdr.ch_size = bfd_get_64 (abfd, &echdr->ch_size);
-         chdr.ch_addralign = bfd_get_64 (abfd, &echdr->ch_addralign);
-       }
-      if (chdr.ch_type == ELFCOMPRESS_ZLIB
-         && chdr.ch_addralign == (chdr.ch_addralign & -chdr.ch_addralign))
-       {
-         *uncompressed_size = chdr.ch_size;
-         *uncompressed_alignment_power = bfd_log2 (chdr.ch_addralign);
-         return true;
-       }
-    }
-
-  return false;
-}
-
-/*
-FUNCTION
-       bfd_get_compression_header_size
-
-SYNOPSIS
-       int bfd_get_compression_header_size (bfd *abfd, asection *sec);
-
-DESCRIPTION
-       Return the size of the compression header of SEC in ABFD.
-
-RETURNS
-       Return the size of the compression header in bytes.
-*/
-
-int
-bfd_get_compression_header_size (bfd *abfd, asection *sec)
-{
-  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
-    {
-      if (sec == NULL)
-       {
-         if (!(abfd->flags & BFD_COMPRESS_GABI))
-           return 0;
-       }
-      else if (!(elf_section_flags (sec) & SHF_COMPRESSED))
-       return 0;
-
-      if (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS32)
-       return sizeof (Elf32_External_Chdr);
-      else
-       return sizeof (Elf64_External_Chdr);
-    }
-
-  return 0;
-}
-
-/*
-FUNCTION
-       bfd_convert_section_size
-
-SYNOPSIS
-       bfd_size_type bfd_convert_section_size
-         (bfd *ibfd, asection *isec, bfd *obfd, bfd_size_type size);
-
-DESCRIPTION
-       Convert the size @var{size} of the section @var{isec} in input
-       BFD @var{ibfd} to the section size in output BFD @var{obfd}.
-*/
-
-bfd_size_type
-bfd_convert_section_size (bfd *ibfd, sec_ptr isec, bfd *obfd,
-                         bfd_size_type size)
-{
-  bfd_size_type hdr_size;
-
-  /* Do nothing if either input or output aren't ELF.  */
-  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
-      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return size;
-
-  /* Do nothing if ELF classes of input and output are the same. */
-  if (get_elf_backend_data (ibfd)->s->elfclass
-      == get_elf_backend_data (obfd)->s->elfclass)
-    return size;
-
-  /* Convert GNU property size.  */
-  if (startswith (isec->name, NOTE_GNU_PROPERTY_SECTION_NAME))
-    return _bfd_elf_convert_gnu_property_size (ibfd, obfd);
-
-  /* Do nothing if input file will be decompressed.  */
-  if ((ibfd->flags & BFD_DECOMPRESS))
-    return size;
-
-  /* Do nothing if the input section isn't a SHF_COMPRESSED section. */
-  hdr_size = bfd_get_compression_header_size (ibfd, isec);
-  if (hdr_size == 0)
-    return size;
-
-  /* Adjust the size of the output SHF_COMPRESSED section.  */
-  if (hdr_size == sizeof (Elf32_External_Chdr))
-    return (size - sizeof (Elf32_External_Chdr)
-           + sizeof (Elf64_External_Chdr));
-  else
-    return (size - sizeof (Elf64_External_Chdr)
-           + sizeof (Elf32_External_Chdr));
-}
-
-/*
-FUNCTION
-       bfd_convert_section_contents
-
-SYNOPSIS
-       bool bfd_convert_section_contents
-         (bfd *ibfd, asection *isec, bfd *obfd,
-          bfd_byte **ptr, bfd_size_type *ptr_size);
-
-DESCRIPTION
-       Convert the contents, stored in @var{*ptr}, of the section
-       @var{isec} in input BFD @var{ibfd} to output BFD @var{obfd}
-       if needed.  The original buffer pointed to by @var{*ptr} may
-       be freed and @var{*ptr} is returned with memory malloc'd by this
-       function, and the new size written to @var{ptr_size}.
-*/
-
-bool
-bfd_convert_section_contents (bfd *ibfd, sec_ptr isec, bfd *obfd,
-                             bfd_byte **ptr, bfd_size_type *ptr_size)
-{
-  bfd_byte *contents;
-  bfd_size_type ihdr_size, ohdr_size, size;
-  Elf_Internal_Chdr chdr;
-  bool use_memmove;
-
-  /* Do nothing if either input or output aren't ELF.  */
-  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
-      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
-
-  /* Do nothing if ELF classes of input and output are the same.  */
-  if (get_elf_backend_data (ibfd)->s->elfclass
-      == get_elf_backend_data (obfd)->s->elfclass)
-    return true;
-
-  /* Convert GNU properties.  */
-  if (startswith (isec->name, NOTE_GNU_PROPERTY_SECTION_NAME))
-    return _bfd_elf_convert_gnu_properties (ibfd, isec, obfd, ptr,
-                                           ptr_size);
-
-  /* Do nothing if input file will be decompressed.  */
-  if ((ibfd->flags & BFD_DECOMPRESS))
-    return true;
-
-  /* Do nothing if the input section isn't a SHF_COMPRESSED section.  */
-  ihdr_size = bfd_get_compression_header_size (ibfd, isec);
-  if (ihdr_size == 0)
-    return true;
-
-  /* PR 25221.  Check for corrupt input sections.  */
-  if (ihdr_size > bfd_get_section_limit (ibfd, isec))
-    /* FIXME: Issue a warning about a corrupt
-       compression header size field ?  */
-    return false;
-
-  contents = *ptr;
-
-  /* Convert the contents of the input SHF_COMPRESSED section to
-     output.  Get the input compression header and the size of the
-     output compression header.  */
-  if (ihdr_size == sizeof (Elf32_External_Chdr))
-    {
-      Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents;
-      chdr.ch_type = bfd_get_32 (ibfd, &echdr->ch_type);
-      chdr.ch_size = bfd_get_32 (ibfd, &echdr->ch_size);
-      chdr.ch_addralign = bfd_get_32 (ibfd, &echdr->ch_addralign);
-
-      ohdr_size = sizeof (Elf64_External_Chdr);
-
-      use_memmove = false;
-    }
-  else if (ihdr_size != sizeof (Elf64_External_Chdr))
-    {
-      /* FIXME: Issue a warning about a corrupt
-        compression header size field ?  */
-      return false;
-    }
-  else
-    {
-      Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents;
-      chdr.ch_type = bfd_get_32 (ibfd, &echdr->ch_type);
-      chdr.ch_size = bfd_get_64 (ibfd, &echdr->ch_size);
-      chdr.ch_addralign = bfd_get_64 (ibfd, &echdr->ch_addralign);
-
-      ohdr_size = sizeof (Elf32_External_Chdr);
-      use_memmove = true;
-    }
-
-  size = bfd_section_size (isec) - ihdr_size + ohdr_size;
-  if (!use_memmove)
-    {
-      contents = (bfd_byte *) bfd_malloc (size);
-      if (contents == NULL)
-       return false;
-    }
-
-  /* Write out the output compression header.  */
-  if (ohdr_size == sizeof (Elf32_External_Chdr))
-    {
-      Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents;
-      bfd_put_32 (obfd, ELFCOMPRESS_ZLIB, &echdr->ch_type);
-      bfd_put_32 (obfd, chdr.ch_size, &echdr->ch_size);
-      bfd_put_32 (obfd, chdr.ch_addralign, &echdr->ch_addralign);
-    }
-  else
-    {
-      Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents;
-      bfd_put_32 (obfd, ELFCOMPRESS_ZLIB, &echdr->ch_type);
-      bfd_put_32 (obfd, 0, &echdr->ch_reserved);
-      bfd_put_64 (obfd, chdr.ch_size, &echdr->ch_size);
-      bfd_put_64 (obfd, chdr.ch_addralign, &echdr->ch_addralign);
-    }
-
-  /* Copy the compressed contents.  */
-  if (use_memmove)
-    memmove (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size);
-  else
-    {
-      memcpy (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size);
-      free (*ptr);
-      *ptr = contents;
-    }
-
-  *ptr_size = size;
-  return true;
-}
-
 /* Get the linker information.  */
 
 struct bfd_link_info *