]> 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 84e74a36b838599d5b9e911d449e9892cd34972a..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-2020 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 \
@@ -245,6 +250,10 @@ CODE_FRAGMENT
 .  {* Set if this is a slim LTO object not loaded with a compiler plugin.  *}
 .  unsigned int lto_slim_object : 1;
 .
+.  {* Do not attempt to modify this file.  Set when detecting errors
+.     that BFD is not prepared to handle for objcopy/strip.  *}
+.  unsigned int read_only : 1;
+.
 .  {* Set to dummy BFD created when claimed by a compiler plug-in
 .     library.  *}
 .  bfd *plugin_dummy_bfd;
@@ -272,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;
@@ -368,7 +386,7 @@ CODE_FRAGMENT
 .  return abfd->filename;
 .}
 .
-.static inline bfd_boolean
+.static inline bool
 .bfd_get_cacheable (const bfd *abfd)
 .{
 .  return abfd->cacheable;
@@ -416,13 +434,13 @@ CODE_FRAGMENT
 .  return abfd->section_count;
 .}
 .
-.static inline bfd_boolean
+.static inline bool
 .bfd_has_map (const bfd *abfd)
 .{
 .  return abfd->has_armap;
 .}
 .
-.static inline bfd_boolean
+.static inline bool
 .bfd_is_thin_archive (const bfd *abfd)
 .{
 .  return abfd->is_thin_archive;
@@ -435,15 +453,15 @@ CODE_FRAGMENT
 .}
 .
 .{* See note beside bfd_set_section_userdata.  *}
-.static inline bfd_boolean
-.bfd_set_cacheable (bfd * abfd, bfd_boolean val)
+.static inline bool
+.bfd_set_cacheable (bfd * abfd, bool val)
 .{
 .  abfd->cacheable = val;
-.  return TRUE;
+.  return true;
 .}
 .
 .static inline void
-.bfd_set_thin_archive (bfd *abfd, bfd_boolean val)
+.bfd_set_thin_archive (bfd *abfd, bool val)
 .{
 .  abfd->is_thin_archive = val;
 .}
@@ -500,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.  *}
@@ -578,7 +604,7 @@ CODE_FRAGMENT
 .    abfd->sections = s;
 .}
 .
-.static inline bfd_boolean
+.static inline bool
 .bfd_section_removed_from_list (const bfd *abfd, const asection *s)
 .{
 .  return s->next ? s->next->prev != s : abfd->section_last != s;
@@ -872,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.  */
 
@@ -879,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];
@@ -899,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] == '%')
@@ -1038,12 +1071,7 @@ _bfd_doprnt (FILE *stream, const char *format, union _bfd_doprnt_args *args)
                        *sptr++ = ptr[-1];
                        *sptr = '\0';
 #endif
-#if defined (__GNUC__) || defined (HAVE_LONG_LONG)
                        PRINT_TYPE (long long, ll);
-#else
-                       /* Fake it and hope for the best.  */
-                       PRINT_TYPE (long, l);
-#endif
                        break;
                      }
                  }
@@ -1058,14 +1086,7 @@ _bfd_doprnt (FILE *stream, const char *format, union _bfd_doprnt_args *args)
                if (wide_width == 0)
                  PRINT_TYPE (double, d);
                else
-                 {
-#if defined (__GNUC__) || defined (HAVE_LONG_DOUBLE)
-                   PRINT_TYPE (long double, ld);
-#else
-                   /* Fake it and hope for the best.  */
-                   PRINT_TYPE (double, d);
-#endif
-                 }
+                 PRINT_TYPE (long double, ld);
              }
              break;
            case 's':
@@ -1097,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')
                {
@@ -1113,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);
@@ -1138,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 != '%')
@@ -1184,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++;
@@ -1209,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++;
@@ -1267,11 +1291,7 @@ _bfd_doprnt_scan (const char *format, union _bfd_doprnt_args *args)
                        break;
                      case 2:
                      default:
-#if defined (__GNUC__) || defined (HAVE_LONG_LONG)
                        arg_type = LongLong;
-#else
-                       arg_type = Long;
-#endif
                        break;
                      }
                  }
@@ -1286,13 +1306,7 @@ _bfd_doprnt_scan (const char *format, union _bfd_doprnt_args *args)
                if (wide_width == 0)
                  arg_type = Double;
                else
-                 {
-#if defined (__GNUC__) || defined (HAVE_LONG_DOUBLE)
-                   arg_type = LongDouble;
-#else
-                   arg_type = Double;
-#endif
-                 }
+                 arg_type = LongDouble;
              }
              break;
            case 's':
@@ -1307,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)
        {
@@ -1354,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.  */
@@ -1370,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
@@ -1430,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
@@ -1450,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
@@ -1611,7 +1723,7 @@ FUNCTION
        bfd_set_file_flags
 
 SYNOPSIS
-       bfd_boolean bfd_set_file_flags (bfd *abfd, flagword flags);
+       bool bfd_set_file_flags (bfd *abfd, flagword flags);
 
 DESCRIPTION
        Set the flag word in the BFD @var{abfd} to the value @var{flags}.
@@ -1626,29 +1738,29 @@ DESCRIPTION
 
 */
 
-bfd_boolean
+bool
 bfd_set_file_flags (bfd *abfd, flagword flags)
 {
   if (abfd->format != bfd_object)
     {
       bfd_set_error (bfd_error_wrong_format);
-      return FALSE;
+      return false;
     }
 
   if (bfd_read_p (abfd))
     {
       bfd_set_error (bfd_error_invalid_operation);
-      return FALSE;
+      return false;
     }
 
   abfd->flags = flags;
   if ((flags & bfd_applicable_file_flags (abfd)) != flags)
     {
       bfd_set_error (bfd_error_invalid_operation);
-      return FALSE;
+      return false;
     }
 
-  return TRUE;
+  return true;
 }
 
 void
@@ -1742,18 +1854,21 @@ bfd_get_sign_extend_vma (bfd *abfd)
      no place to store this information in the COFF back end.
      Should enough other COFF targets add support for DWARF2,
      a place will have to be found.  Until then, this hack will do.  */
-  if (CONST_STRNEQ (name, "coff-go32")
+  if (startswith (name, "coff-go32")
       || strcmp (name, "pe-i386") == 0
       || 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;
 
-  if (CONST_STRNEQ (name, "mach-o"))
+  if (startswith (name, "mach-o"))
     return 0;
 
   bfd_set_error (bfd_error_wrong_format);
@@ -1765,7 +1880,7 @@ FUNCTION
        bfd_set_start_address
 
 SYNOPSIS
-       bfd_boolean bfd_set_start_address (bfd *abfd, bfd_vma vma);
+       bool bfd_set_start_address (bfd *abfd, bfd_vma vma);
 
 DESCRIPTION
        Make @var{vma} the entry point of output BFD @var{abfd}.
@@ -1774,11 +1889,11 @@ RETURNS
        Returns <<TRUE>> on success, <<FALSE>> otherwise.
 */
 
-bfd_boolean
+bool
 bfd_set_start_address (bfd *abfd, bfd_vma vma)
 {
   abfd->start_address = vma;
-  return TRUE;
+  return true;
 }
 
 /*
@@ -1869,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
@@ -1902,10 +2035,8 @@ bfd_scan_vma (const char *string, const char **end, int base)
   if (sizeof (bfd_vma) <= sizeof (unsigned long))
     return strtoul (string, (char **) end, base);
 
-#if defined (HAVE_STRTOULL) && defined (HAVE_LONG_LONG)
   if (sizeof (bfd_vma) <= sizeof (unsigned long long))
     return strtoull (string, (char **) end, base);
-#endif
 
   if (base == 0)
     {
@@ -1966,7 +2097,7 @@ FUNCTION
        bfd_copy_private_header_data
 
 SYNOPSIS
-       bfd_boolean bfd_copy_private_header_data (bfd *ibfd, bfd *obfd);
+       bool bfd_copy_private_header_data (bfd *ibfd, bfd *obfd);
 
 DESCRIPTION
        Copy private BFD header information from the BFD @var{ibfd} to the
@@ -1989,7 +2120,7 @@ FUNCTION
        bfd_copy_private_bfd_data
 
 SYNOPSIS
-       bfd_boolean bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd);
+       bool bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd);
 
 DESCRIPTION
        Copy private BFD information from the BFD @var{ibfd} to the
@@ -2010,7 +2141,7 @@ FUNCTION
        bfd_set_private_flags
 
 SYNOPSIS
-       bfd_boolean bfd_set_private_flags (bfd *abfd, flagword flags);
+       bool bfd_set_private_flags (bfd *abfd, flagword flags);
 
 DESCRIPTION
        Set private BFD flag information in the BFD @var{abfd}.
@@ -2039,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, \
@@ -2128,7 +2264,7 @@ DESCRIPTION
 .
 .extern bfd_byte *bfd_get_relocated_section_contents
 .  (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *,
-.   bfd_boolean, asymbol **);
+.   bool, asymbol **);
 .
 
 */
@@ -2138,12 +2274,12 @@ bfd_get_relocated_section_contents (bfd *abfd,
                                    struct bfd_link_info *link_info,
                                    struct bfd_link_order *link_order,
                                    bfd_byte *data,
-                                   bfd_boolean relocatable,
+                                   bool relocatable,
                                    asymbol **symbols)
 {
   bfd *abfd2;
   bfd_byte *(*fn) (bfd *, struct bfd_link_info *, struct bfd_link_order *,
-                  bfd_byte *, bfd_boolean, asymbol **);
+                  bfd_byte *, bool, asymbol **);
 
   if (link_order->type == bfd_indirect_link_order)
     {
@@ -2161,15 +2297,15 @@ bfd_get_relocated_section_contents (bfd *abfd,
 
 /* Record information about an ELF program header.  */
 
-bfd_boolean
+bool
 bfd_record_phdr (bfd *abfd,
                 unsigned long type,
-                bfd_boolean flags_valid,
+                bool flags_valid,
                 flagword flags,
-                bfd_boolean at_valid,
+                bool at_valid,
                 bfd_vma at,  /* Bytes.  */
-                bfd_boolean includes_filehdr,
-                bfd_boolean includes_phdrs,
+                bool includes_filehdr,
+                bool includes_phdrs,
                 unsigned int count,
                 asection **secs)
 {
@@ -2178,13 +2314,13 @@ bfd_record_phdr (bfd *abfd,
   unsigned int opb = bfd_octets_per_byte (abfd, NULL);
 
   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
-    return TRUE;
+    return true;
 
   amt = sizeof (struct elf_segment_map);
   amt += ((bfd_size_type) count - 1) * sizeof (asection *);
   m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
   if (m == NULL)
-    return FALSE;
+    return false;
 
   m->p_type = type;
   m->p_flags = flags;
@@ -2201,13 +2337,13 @@ bfd_record_phdr (bfd *abfd,
     ;
   *pm = m;
 
-  return TRUE;
+  return true;
 }
 
 #ifdef BFD64
 /* Return true iff this target is 32-bit.  */
 
-static bfd_boolean
+static bool
 is32bit (bfd *abfd)
 {
   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
@@ -2228,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);
 }
 
 /*
@@ -2255,7 +2391,7 @@ FUNCTION
        bfd_alt_mach_code
 
 SYNOPSIS
-       bfd_boolean bfd_alt_mach_code (bfd *abfd, int alternative);
+       bool bfd_alt_mach_code (bfd *abfd, int alternative);
 
 DESCRIPTION
 
@@ -2266,7 +2402,7 @@ DESCRIPTION
        machine codes.
 */
 
-bfd_boolean
+bool
 bfd_alt_mach_code (bfd *abfd, int alternative)
 {
   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
@@ -2282,25 +2418,25 @@ bfd_alt_mach_code (bfd *abfd, int alternative)
        case 1:
          code = get_elf_backend_data (abfd)->elf_machine_alt1;
          if (code == 0)
-           return FALSE;
+           return false;
          break;
 
        case 2:
          code = get_elf_backend_data (abfd)->elf_machine_alt2;
          if (code == 0)
-           return FALSE;
+           return false;
          break;
 
        default:
-         return FALSE;
+         return false;
        }
 
       elf_elfheader (abfd)->e_machine = code;
 
-      return TRUE;
+      return true;
     }
 
-  return FALSE;
+  return false;
 }
 
 /*
@@ -2331,55 +2467,12 @@ bfd_emul_get_maxpagesize (const char *emul)
   return 0;
 }
 
-static void
-bfd_elf_set_pagesize (const bfd_target *target, bfd_vma size,
-                     int offset, const bfd_target *orig_target)
-{
-  if (target->flavour == bfd_target_elf_flavour)
-    {
-      const struct elf_backend_data *bed;
-
-      bed = xvec_get_elf_backend_data (target);
-      *((bfd_vma *) ((char *) bed + offset)) = size;
-    }
-
-  if (target->alternative_target
-      && target->alternative_target != orig_target)
-    bfd_elf_set_pagesize (target->alternative_target, size, offset,
-                         orig_target);
-}
-
-/*
-FUNCTION
-       bfd_emul_set_maxpagesize
-
-SYNOPSIS
-       void bfd_emul_set_maxpagesize (const char *, bfd_vma);
-
-DESCRIPTION
-       For ELF, set the maximum page size for the emulation.  It is
-       a no-op for other formats.
-
-*/
-
-void
-bfd_emul_set_maxpagesize (const char *emul, bfd_vma size)
-{
-  const bfd_target *target;
-
-  target = bfd_find_target (emul, NULL);
-  if (target)
-    bfd_elf_set_pagesize (target, size,
-                         offsetof (struct elf_backend_data,
-                                   maxpagesize), target);
-}
-
 /*
 FUNCTION
        bfd_emul_get_commonpagesize
 
 SYNOPSIS
-       bfd_vma bfd_emul_get_commonpagesize (const char *, bfd_boolean);
+       bfd_vma bfd_emul_get_commonpagesize (const char *);
 
 DESCRIPTION
        Returns the common page size, in bytes, as determined by
@@ -2390,7 +2483,7 @@ RETURNS
 */
 
 bfd_vma
-bfd_emul_get_commonpagesize (const char *emul, bfd_boolean relro)
+bfd_emul_get_commonpagesize (const char *emul)
 {
   const bfd_target *target;
 
@@ -2401,39 +2494,11 @@ bfd_emul_get_commonpagesize (const char *emul, bfd_boolean 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;
 }
 
-/*
-FUNCTION
-       bfd_emul_set_commonpagesize
-
-SYNOPSIS
-       void bfd_emul_set_commonpagesize (const char *, bfd_vma);
-
-DESCRIPTION
-       For ELF, set the common page size for the emulation.  It is
-       a no-op for other formats.
-
-*/
-
-void
-bfd_emul_set_commonpagesize (const char *emul, bfd_vma size)
-{
-  const bfd_target *target;
-
-  target = bfd_find_target (emul, NULL);
-  if (target)
-    bfd_elf_set_pagesize (target, size,
-                         offsetof (struct elf_backend_data,
-                                   commonpagesize), target);
-}
-
 /*
 FUNCTION
        bfd_demangle
@@ -2455,7 +2520,7 @@ bfd_demangle (bfd *abfd, const char *name, int options)
   char *res, *alloc;
   const char *pre, *suf;
   size_t pre_len;
-  bfd_boolean skip_lead;
+  bool skip_lead;
 
   skip_lead = (abfd != NULL
               && *name != '\0'
@@ -2487,8 +2552,7 @@ bfd_demangle (bfd *abfd, const char *name, int options)
 
   res = cplus_demangle (name, options);
 
-  if (alloc != NULL)
-    free (alloc);
+  free (alloc);
 
   if (res == NULL)
     {
@@ -2529,344 +2593,13 @@ 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);
-
-         /* 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);
-           }
-         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);
-           }
-         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
-       bfd_boolean 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.
-*/
-
-bfd_boolean
-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
+/* Get the linker information.  */
 
-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)
+struct bfd_link_info *
+_bfd_get_link_info (bfd *abfd)
 {
-  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 (CONST_STRNEQ (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
-       bfd_boolean 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}.
-*/
-
-bfd_boolean
-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;
-  bfd_boolean 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 (CONST_STRNEQ (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;
-    }
+  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+    return NULL;
 
-  *ptr_size = size;
-  return TRUE;
+  return elf_link_info (abfd);
 }