More fixes for bfd_get_section_contents change
[deliverable/binutils-gdb.git] / bfd / bfd.c
index e60f3581a3a89b6935c5a5e9f6646017b1adbb8e..c6fce45abf1b7c530dcb99a7a764d42359c17bbb 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -1,5 +1,5 @@
 /* Generic BFD library interface and support routines.
 /* Generic BFD library interface and support routines.
-   Copyright (C) 1990-2015 Free Software Foundation, Inc.
+   Copyright (C) 1990-2017 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -46,14 +46,14 @@ CODE_FRAGMENT
 .
 .enum bfd_plugin_format
 .  {
 .
 .enum bfd_plugin_format
 .  {
-.    bfd_plugin_uknown = 0,
+.    bfd_plugin_unknown = 0,
 .    bfd_plugin_yes = 1,
 .    bfd_plugin_no = 2
 .  };
 .
 .struct bfd_build_id
 .  {
 .    bfd_plugin_yes = 1,
 .    bfd_plugin_no = 2
 .  };
 .
 .struct bfd_build_id
 .  {
-.    size_t size;
+.    bfd_size_type size;
 .    bfd_byte data[1];
 .  };
 .
 .    bfd_byte data[1];
 .  };
 .
@@ -91,7 +91,7 @@ CODE_FRAGMENT
 .  ENUM_BITFIELD (bfd_direction) direction : 2;
 .
 .  {* Format_specific flags.  *}
 .  ENUM_BITFIELD (bfd_direction) direction : 2;
 .
 .  {* Format_specific flags.  *}
-.  flagword flags : 18;
+.  flagword flags : 20;
 .
 .  {* Values that may appear in the flags field of a BFD.  These also
 .     appear in the object_flags field of the bfd_target structure, where
 .
 .  {* Values that may appear in the flags field of a BFD.  These also
 .     appear in the object_flags field of the bfd_target structure, where
@@ -171,16 +171,24 @@ CODE_FRAGMENT
 .  {* Compress sections in this BFD with SHF_COMPRESSED from gABI.  *}
 .#define BFD_COMPRESS_GABI 0x20000
 .
 .  {* Compress sections in this BFD with SHF_COMPRESSED from gABI.  *}
 .#define BFD_COMPRESS_GABI 0x20000
 .
+.  {* Convert ELF common symbol type to STT_COMMON or STT_OBJECT in this
+.     BFD.  *}
+.#define BFD_CONVERT_ELF_COMMON 0x40000
+.
+.  {* Use the ELF STT_COMMON type in this BFD.  *}
+.#define BFD_USE_ELF_STT_COMMON 0x80000
+.
 .  {* Flags bits to be saved in bfd_preserve_save.  *}
 .#define BFD_FLAGS_SAVED \
 .  {* Flags bits to be saved in bfd_preserve_save.  *}
 .#define BFD_FLAGS_SAVED \
-.  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN \
-.   | BFD_COMPRESS_GABI)
+.  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
+.   | BFD_PLUGIN | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON \
+.   | BFD_USE_ELF_STT_COMMON)
 .
 .  {* Flags bits which are for BFD use only.  *}
 .#define BFD_FLAGS_FOR_BFD_USE_MASK \
 .  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
 .   | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT \
 .
 .  {* Flags bits which are for BFD use only.  *}
 .#define BFD_FLAGS_FOR_BFD_USE_MASK \
 .  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
 .   | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT \
-.   | BFD_COMPRESS_GABI)
+.   | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON)
 .
 .  {* Is the file descriptor being cached?  That is, can it be closed as
 .     needed, and re-opened when accessed later?  *}
 .
 .  {* Is the file descriptor being cached?  That is, can it be closed as
 .     needed, and re-opened when accessed later?  *}
@@ -591,11 +599,11 @@ SUBSECTION
        problem.  They call a BFD error handler function.  This
        function may be overridden by the program.
 
        problem.  They call a BFD error handler function.  This
        function may be overridden by the program.
 
-       The BFD error handler acts like printf.
+       The BFD error handler acts like vprintf.
 
 CODE_FRAGMENT
 .
 
 CODE_FRAGMENT
 .
-.typedef void (*bfd_error_handler_type) (const char *, ...);
+.typedef void (*bfd_error_handler_type) (const char *, va_list);
 .
 */
 
 .
 */
 
@@ -603,178 +611,240 @@ CODE_FRAGMENT
 
 static const char *_bfd_error_program_name;
 
 
 static const char *_bfd_error_program_name;
 
-/* This is the default routine to handle BFD error messages.
-   Like fprintf (stderr, ...), but also handles some extra format specifiers.
+/* This macro and _doprnt taken from libiberty _doprnt.c, tidied a
+   little and extended to handle '%A' and '%B'.  */
 
 
-   %A section name from section.  For group components, print group name too.
-   %B file name from bfd.  For archive components, prints archive too.
+#define PRINT_TYPE(TYPE) \
+  do                                                           \
+    {                                                          \
+      TYPE value = va_arg (ap, TYPE);                          \
+      result = fprintf (stream, specifier, value);             \
+    } while (0)
 
 
-   Note - because these two extra format specifiers require special handling
-   they are scanned for and processed in this function, before calling
-   vfprintf.  This means that the *arguments* for these format specifiers
-   must be the first ones in the variable argument list, regardless of where
-   the specifiers appear in the format string.  Thus for example calling
-   this function with a format string of:
-
-      "blah %s blah %A blah %d blah %B"
-
-   would involve passing the arguments as:
-
-      "blah %s blah %A blah %d blah %B",
-        asection_for_the_%A,
-       bfd_for_the_%B,
-       string_for_the_%s,
-       integer_for_the_%d);
- */
-
-void
-_bfd_default_error_handler (const char *fmt, ...)
+static int
+_doprnt (FILE *stream, const char *format, va_list ap)
 {
 {
-  va_list ap;
-  char *bufp;
-  const char *new_fmt, *p;
-  size_t avail = 1000;
-  char buf[1000];
-
-  /* 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: ");
-
-  va_start (ap, fmt);
-  new_fmt = fmt;
-  bufp = buf;
+  const char *ptr = format;
+  char specifier[128];
+  int total_printed = 0;
 
 
-  /* Reserve enough space for the existing format string.  */
-  avail -= strlen (fmt) + 1;
-  if (avail > 1000)
-    _exit (EXIT_FAILURE);
-
-  p = fmt;
-  while (1)
+  while (*ptr != '\0')
     {
     {
-      char *q;
-      size_t len, extra, trim;
+      int result;
 
 
-      p = strchr (p, '%');
-      if (p == NULL || p[1] == '\0')
+      if (*ptr != '%')
        {
        {
-         if (new_fmt == buf)
-           {
-             len = strlen (fmt);
-             memcpy (bufp, fmt, len + 1);
-           }
-         break;
+         /* While we have regular characters, print them.  */
+         char *end = strchr (ptr, '%');
+         if (end != NULL)
+           result = fprintf (stream, "%.*s", (int) (end - ptr), ptr);
+         else
+           result = fprintf (stream, "%s", ptr);
+         ptr += result;
        }
        }
-
-      if (p[1] == 'A' || p[1] == 'B')
+      else
        {
        {
-         len = p - fmt;
-         memcpy (bufp, fmt, len);
-         bufp += len;
-         fmt = p + 2;
-         new_fmt = buf;
-
-         /* If we run out of space, tough, you lose your ridiculously
-            long file or section name.  It's not safe to try to alloc
-            memory here;  We might be printing an out of memory message.  */
-         if (avail == 0)
+         /* We have a format specifier!  */
+         char *sptr = specifier;
+         int wide_width = 0, short_width = 0;
+
+         /* Copy the % and move forward.  */
+         *sptr++ = *ptr++;
+
+         /* Move past flags.  */
+         while (strchr ("-+ #0", *ptr))
+           *sptr++ = *ptr++;
+
+         if (*ptr == '*')
            {
            {
-             *bufp++ = '*';
-             *bufp++ = '*';
-             *bufp = '\0';
+             int value = abs (va_arg (ap, int));
+             sptr += sprintf (sptr, "%d", value);
+             ptr++;
            }
          else
            }
          else
+           /* Handle explicit numeric value.  */
+           while (ISDIGIT (*ptr))
+             *sptr++ = *ptr++;
+
+         if (*ptr == '.')
            {
            {
-             if (p[1] == 'B')
+             /* Copy and go past the period.  */
+             *sptr++ = *ptr++;
+             if (*ptr == '*')
                {
                {
-                 bfd *abfd = va_arg (ap, bfd *);
-
-                 if (abfd == NULL)
-                   /* Invoking %B with a null bfd pointer is an internal error.  */
-                   abort ();
-                 else if (abfd->my_archive)
-                   snprintf (bufp, avail, "%s(%s)",
-                             abfd->my_archive->filename, abfd->filename);
-                 else
-                   snprintf (bufp, avail, "%s", abfd->filename);
+                 int value = abs (va_arg (ap, int));
+                 sptr += sprintf (sptr, "%d", value);
+                 ptr++;
                }
              else
                }
              else
+               /* Handle explicit numeric value.  */
+               while (ISDIGIT (*ptr))
+                 *sptr++ = *ptr++;
+           }
+         while (strchr ("hlL", *ptr))
+           {
+             switch (*ptr)
                {
                {
-                 asection *sec = va_arg (ap, asection *);
-                 bfd *abfd;
-                 const char *group = NULL;
-                 struct coff_comdat_info *ci;
-
-                 if (sec == NULL)
-                   /* Invoking %A with a null section pointer is an internal error.  */
-                   abort ();
-                 abfd = sec->owner;
-                 if (abfd != NULL
-                     && bfd_get_flavour (abfd) == bfd_target_elf_flavour
-                     && elf_next_in_group (sec) != NULL
-                     && (sec->flags & SEC_GROUP) == 0)
-                   group = elf_group_name (sec);
-                 else if (abfd != NULL
-                          && bfd_get_flavour (abfd) == bfd_target_coff_flavour
-                          && (ci = bfd_coff_get_comdat_section (sec->owner,
-                                                                sec)) != NULL)
-                   group = ci->name;
-                 if (group != NULL)
-                   snprintf (bufp, avail, "%s[%s]", sec->name, group);
-                 else
-                   snprintf (bufp, avail, "%s", sec->name);
-               }
-             len = strlen (bufp);
-             avail = avail - len + 2;
-
-             /* We need to replace any '%' we printed by "%%".
-                First count how many.  */
-             q = bufp;
-             bufp += len;
-             extra = 0;
-             while ((q = strchr (q, '%')) != NULL)
-               {
-                 ++q;
-                 ++extra;
+               case 'h':
+                 short_width = 1;
+                 break;
+               case 'l':
+                 wide_width++;
+                 break;
+               case 'L':
+                 wide_width = 2;
+                 break;
+               default:
+                 abort();
                }
                }
+             *sptr++ = *ptr++;
+           }
 
 
-             /* If there isn't room, trim off the end of the string.  */
-             q = bufp;
-             bufp += extra;
-             if (extra > avail)
-               {
-                 trim = extra - avail;
-                 bufp -= trim;
-                 do
-                   {
-                     if (*--q == '%')
-                       --extra;
-                   }
-                 while (--trim != 0);
-                 *q = '\0';
-                 avail = extra;
-               }
-             avail -= extra;
+         /* Copy the type specifier, and NULL terminate.  */
+         *sptr++ = *ptr++;
+         *sptr = '\0';
 
 
-             /* Now double all '%' chars, shuffling the string as we go.  */
-             while (extra != 0)
-               {
-                 while ((q[extra] = *q) != '%')
-                   --q;
-                 q[--extra] = '%';
-                 --q;
-               }
+         switch (ptr[-1])
+           {
+           case 'd':
+           case 'i':
+           case 'o':
+           case 'u':
+           case 'x':
+           case 'X':
+           case 'c':
+             {
+               /* Short values are promoted to int, so just copy it
+                  as an int and trust the C library printf to cast it
+                  to the right width.  */
+               if (short_width)
+                 PRINT_TYPE (int);
+               else
+                 {
+                   switch (wide_width)
+                     {
+                     case 0:
+                       PRINT_TYPE (int);
+                       break;
+                     case 1:
+                       PRINT_TYPE (long);
+                       break;
+                     case 2:
+                     default:
+#if defined(__GNUC__) || defined(HAVE_LONG_LONG)
+                       PRINT_TYPE (long long);
+#else
+                       /* Fake it and hope for the best.  */
+                       PRINT_TYPE (long);
+#endif
+                       break;
+                     }
+                 }
+             }
+             break;
+           case 'f':
+           case 'e':
+           case 'E':
+           case 'g':
+           case 'G':
+             {
+               if (wide_width == 0)
+                 PRINT_TYPE (double);
+               else
+                 {
+#if defined(__GNUC__) || defined(HAVE_LONG_DOUBLE)
+                   PRINT_TYPE (long double);
+#else
+                   /* Fake it and hope for the best.  */
+                   PRINT_TYPE (double);
+#endif
+                 }
+             }
+             break;
+           case 's':
+             PRINT_TYPE (char *);
+             break;
+           case 'p':
+             PRINT_TYPE (void *);
+             break;
+           case '%':
+             fputc ('%', stream);
+             result = 1;
+             break;
+           case 'A':
+             {
+               asection *sec = va_arg (ap, asection *);
+               bfd *abfd;
+               const char *group = NULL;
+               struct coff_comdat_info *ci;
+
+               if (sec == NULL)
+                 /* Invoking %A with a null section pointer is an
+                    internal error.  */
+                 abort ();
+               abfd = sec->owner;
+               if (abfd != NULL
+                   && bfd_get_flavour (abfd) == bfd_target_elf_flavour
+                   && elf_next_in_group (sec) != NULL
+                   && (sec->flags & SEC_GROUP) == 0)
+                 group = elf_group_name (sec);
+               else if (abfd != NULL
+                        && bfd_get_flavour (abfd) == bfd_target_coff_flavour
+                        && (ci = bfd_coff_get_comdat_section (sec->owner,
+                                                              sec)) != NULL)
+                 group = ci->name;
+               if (group != NULL)
+                 result = fprintf (stream, "%s[%s]", sec->name, group);
+               else
+                 result = fprintf (stream, "%s", sec->name);
+             }
+             break;
+           case 'B':
+             {
+               bfd *abfd = va_arg (ap, bfd *);
+
+               if (abfd == NULL)
+                 /* Invoking %B with a null bfd pointer is an
+                    internal error.  */
+                 abort ();
+               else if (abfd->my_archive
+                        && !bfd_is_thin_archive (abfd->my_archive))
+                 result = fprintf (stream, "%s(%s)",
+                                   abfd->my_archive->filename, abfd->filename);
+               else
+                 result = fprintf (stream, "%s", abfd->filename);
+             }
+             break;
+           default:
+             abort();
            }
        }
            }
        }
-      p = p + 2;
+      if (result == -1)
+       return -1;
+      total_printed += result;
     }
 
     }
 
-  vfprintf (stderr, new_fmt, ap);
-  va_end (ap);
+  return total_printed;
+}
+
+/* This is the default routine to handle BFD error messages.
+   Like fprintf (stderr, ...), but also handles some extra format specifiers.
+
+   %A section name from section.  For group components, print group name too.
+   %B file name from bfd.  For archive components, prints archive too.  */
+
+static void
+error_handler_internal (const char *fmt, va_list ap)
+{
+  /* 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: ");
+
+  _doprnt (stderr, fmt, ap);
 
   /* On AIX, putc is implemented as a macro that triggers a -Wunused-value
      warning, so use the fputc function to avoid it.  */
 
   /* On AIX, putc is implemented as a macro that triggers a -Wunused-value
      warning, so use the fputc function to avoid it.  */
@@ -788,7 +858,17 @@ _bfd_default_error_handler (const char *fmt, ...)
    function pointer permits a program linked against BFD to intercept
    the messages and deal with them itself.  */
 
    function pointer permits a program linked against BFD to intercept
    the messages and deal with them itself.  */
 
-bfd_error_handler_type _bfd_error_handler = _bfd_default_error_handler;
+static bfd_error_handler_type _bfd_error_internal = error_handler_internal;
+
+void
+_bfd_error_handler (const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start (ap, fmt);
+  _bfd_error_internal (fmt, ap);
+  va_end (ap);
+}
 
 /*
 FUNCTION
 
 /*
 FUNCTION
@@ -807,8 +887,8 @@ bfd_set_error_handler (bfd_error_handler_type pnew)
 {
   bfd_error_handler_type pold;
 
 {
   bfd_error_handler_type pold;
 
-  pold = _bfd_error_handler;
-  _bfd_error_handler = pnew;
+  pold = _bfd_error_internal;
+  _bfd_error_internal = pnew;
   return pold;
 }
 
   return pold;
 }
 
@@ -832,23 +912,6 @@ bfd_set_error_program_name (const char *name)
   _bfd_error_program_name = name;
 }
 
   _bfd_error_program_name = name;
 }
 
-/*
-FUNCTION
-       bfd_get_error_handler
-
-SYNOPSIS
-       bfd_error_handler_type bfd_get_error_handler (void);
-
-DESCRIPTION
-       Return the BFD error handler function.
-*/
-
-bfd_error_handler_type
-bfd_get_error_handler (void)
-{
-  return _bfd_error_handler;
-}
-
 /*
 SUBSECTION
        BFD assert handler
 /*
 SUBSECTION
        BFD assert handler
@@ -883,14 +946,14 @@ _bfd_default_assert_handler (const char *bfd_formatmsg,
                             int bfd_line)
 
 {
                             int bfd_line)
 
 {
-  (*_bfd_error_handler) (bfd_formatmsg, bfd_version, bfd_file, bfd_line);
+  _bfd_error_handler (bfd_formatmsg, bfd_version, bfd_file, bfd_line);
 }
 
 /* Similar to _bfd_error_handler, a program can decide to exit on an
    internal BFD error.  We use a non-variadic type to simplify passing
    on parameters to other functions, e.g. _bfd_error_handler.  */
 
 }
 
 /* Similar to _bfd_error_handler, a program can decide to exit on an
    internal BFD error.  We use a non-variadic type to simplify passing
    on parameters to other functions, e.g. _bfd_error_handler.  */
 
-bfd_assert_handler_type _bfd_assert_handler = _bfd_default_assert_handler;
+static bfd_assert_handler_type _bfd_assert_handler = _bfd_default_assert_handler;
 
 /*
 FUNCTION
 
 /*
 FUNCTION
@@ -913,23 +976,6 @@ bfd_set_assert_handler (bfd_assert_handler_type pnew)
   _bfd_assert_handler = pnew;
   return pold;
 }
   _bfd_assert_handler = pnew;
   return pold;
 }
-
-/*
-FUNCTION
-       bfd_get_assert_handler
-
-SYNOPSIS
-       bfd_assert_handler_type bfd_get_assert_handler (void);
-
-DESCRIPTION
-       Return the BFD assert handler function.
-*/
-
-bfd_assert_handler_type
-bfd_get_assert_handler (void)
-{
-  return _bfd_assert_handler;
-}
 \f
 /*
 INODE
 \f
 /*
 INODE
@@ -1018,18 +1064,10 @@ DESCRIPTION
        section @var{sec} to the values @var{rel} and @var{count}.
        The argument @var{abfd} is ignored.
 
        section @var{sec} to the values @var{rel} and @var{count}.
        The argument @var{abfd} is ignored.
 
+.#define bfd_set_reloc(abfd, asect, location, count) \
+.     BFD_SEND (abfd, _bfd_set_reloc, (abfd, asect, location, count))
 */
 
 */
 
-void
-bfd_set_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED,
-              sec_ptr asect,
-              arelent **location,
-              unsigned int count)
-{
-  asect->orelocation = location;
-  asect->reloc_count = count;
-}
-
 /*
 FUNCTION
        bfd_set_file_flags
 /*
 FUNCTION
        bfd_set_file_flags
@@ -1078,6 +1116,7 @@ bfd_set_file_flags (bfd *abfd, flagword flags)
 void
 bfd_assert (const char *file, int line)
 {
 void
 bfd_assert (const char *file, int line)
 {
+  /* xgettext:c-format */
   (*_bfd_assert_handler) (_("BFD %s assertion fail %s:%d"),
                          BFD_VERSION_STRING, file, line);
 }
   (*_bfd_assert_handler) (_("BFD %s assertion fail %s:%d"),
                          BFD_VERSION_STRING, file, line);
 }
@@ -1089,14 +1128,16 @@ void
 _bfd_abort (const char *file, int line, const char *fn)
 {
   if (fn != NULL)
 _bfd_abort (const char *file, int line, const char *fn)
 {
   if (fn != NULL)
-    (*_bfd_error_handler)
-      (_("BFD %s internal error, aborting at %s line %d in %s\n"),
+    _bfd_error_handler
+      /* xgettext:c-format */
+      (_("BFD %s internal error, aborting at %s:%d in %s\n"),
        BFD_VERSION_STRING, file, line, fn);
   else
        BFD_VERSION_STRING, file, line, fn);
   else
-    (*_bfd_error_handler)
-      (_("BFD %s internal error, aborting at %s line %d\n"),
+    _bfd_error_handler
+      /* xgettext:c-format */
+      (_("BFD %s internal error, aborting at %s:%d\n"),
        BFD_VERSION_STRING, file, line);
        BFD_VERSION_STRING, file, line);
-  (*_bfd_error_handler) (_("Please report this bug.\n"));
+  _bfd_error_handler (_("Please report this bug.\n"));
   _exit (EXIT_FAILURE);
 }
 
   _exit (EXIT_FAILURE);
 }
 
@@ -1425,27 +1466,6 @@ DESCRIPTION
 
 */
 
 
 */
 
-/*
-FUNCTION
-       bfd_merge_private_bfd_data
-
-SYNOPSIS
-       bfd_boolean bfd_merge_private_bfd_data (bfd *ibfd, bfd *obfd);
-
-DESCRIPTION
-       Merge private BFD information from the BFD @var{ibfd} to the
-       the output file BFD @var{obfd} when linking.  Return <<TRUE>>
-       on success, <<FALSE>> on error.  Possible error returns are:
-
-       o <<bfd_error_no_memory>> -
-       Not enough memory exists to create private data for @var{obfd}.
-
-.#define bfd_merge_private_bfd_data(ibfd, obfd) \
-.     BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
-.              (ibfd, obfd))
-
-*/
-
 /*
 FUNCTION
        bfd_set_private_flags
 /*
 FUNCTION
        bfd_set_private_flags
@@ -2000,7 +2020,8 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents,
                {
                  Elf64_External_Chdr *echdr
                    = (Elf64_External_Chdr *) contents;
                {
                  Elf64_External_Chdr *echdr
                    = (Elf64_External_Chdr *) contents;
-                 bfd_put_64 (abfd, ELFCOMPRESS_ZLIB, &echdr->ch_type);
+                 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_put_64 (abfd, sec->size, &echdr->ch_size);
                  bfd_put_64 (abfd, 1 << sec->alignment_power,
                              &echdr->ch_addralign);
@@ -2061,7 +2082,7 @@ bfd_check_compression_header (bfd *abfd, bfd_byte *contents,
       else
        {
          Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents;
       else
        {
          Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents;
-         chdr.ch_type = bfd_get_64 (abfd, &echdr->ch_type);
+         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);
        }
          chdr.ch_size = bfd_get_64 (abfd, &echdr->ch_size);
          chdr.ch_addralign = bfd_get_64 (abfd, &echdr->ch_addralign);
        }
@@ -2111,3 +2132,161 @@ bfd_get_compression_header_size (bfd *abfd, asection *sec)
 
   return 0;
 }
 
   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 input file will be decompressed.  */
+  if ((ibfd->flags & BFD_DECOMPRESS))
+    return 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;
+
+  /* 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 input file will be decompressed.  */
+  if ((ibfd->flags & BFD_DECOMPRESS))
+    return TRUE;
+
+  /* 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;
+
+  /* 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;
+
+  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
+    {
+      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_get_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;
+}
This page took 0.034083 seconds and 4 git commands to generate.