bfd/
[deliverable/binutils-gdb.git] / bfd / bfd.c
index 524e7d2af33054ecf5e17a965da64fe6839ab365..a2d4ae90b633b1913f92c1c60fc99c5578d9170b 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -1,6 +1,6 @@
 /* Generic BFD library interface and support routines.
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003
+   2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
    Written by Cygnus Support.
 
@@ -18,7 +18,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /*
 SECTION
@@ -111,8 +111,8 @@ CODE_FRAGMENT
 .  {* Pointer to linked list of sections.  *}
 .  struct bfd_section *sections;
 .
-.  {* The place where we add to the section list.  *}
-.  struct bfd_section **section_tail;
+.  {* The last section on the section list.  *}
+.  struct bfd_section *section_last;
 .
 .  {* The number of sections.  *}
 .  unsigned int section_count;
@@ -133,6 +133,9 @@ CODE_FRAGMENT
 .  {* Pointer to structure which contains architecture information.  *}
 .  const struct bfd_arch_info *arch_info;
 .
+.  {* Flag set if symbols from this BFD should not be exported.  *}
+.  bfd_boolean no_export;
+.
 .  {* Stuff only useful for archives.  *}
 .  void *arelt_data;
 .  struct bfd *my_archive;      {* The containing archive BFD.  *}
@@ -213,6 +216,11 @@ CODE_FRAGMENT
 #include "libecoff.h"
 #undef obj_symbols
 #include "elf-bfd.h"
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+
 \f
 /* provide storage for subsystem, stack and heap data which may have been
    passed in on the command line.  Ld puts this data into a bfd_link_info
@@ -406,23 +414,177 @@ CODE_FRAGMENT
 
 static const char *_bfd_error_program_name;
 
-/* This is the default routine to handle BFD error messages.  */
+/* This is the default routine to handle BFD error messages.
+   Like fprintf (stderr, ...), but also handles some extra format specifiers.
 
-static void
-_bfd_default_error_handler (const char *s, ...)
+   %A section name from section.  For group components, print group name too.
+   %B file name from bfd.  For archive components, prints archive too.
+
+   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, ...)
 {
-  va_list p;
+  va_list ap;
+  char *bufp;
+  const char *new_fmt, *p;
+  size_t avail = 1000;
+  char buf[1000];
 
   if (_bfd_error_program_name != NULL)
     fprintf (stderr, "%s: ", _bfd_error_program_name);
   else
     fprintf (stderr, "BFD: ");
 
-  va_start (p, s);
-  vfprintf (stderr, s, p);
-  va_end (p);
+  va_start (ap, fmt);
+  new_fmt = fmt;
+  bufp = buf;
 
-  fprintf (stderr, "\n");
+  /* Reserve enough space for the existing format string.  */
+  avail -= strlen (fmt) + 1;
+  if (avail > 1000)
+    _exit (EXIT_FAILURE);
+
+  p = fmt;
+  while (1)
+    {
+      char *q;
+      size_t len, extra, trim;
+
+      p = strchr (p, '%');
+      if (p == NULL || p[1] == '\0')
+       {
+         if (new_fmt == buf)
+           {
+             len = strlen (fmt);
+             memcpy (bufp, fmt, len + 1);
+           }
+         break;
+       }
+
+      if (p[1] == 'A' || p[1] == 'B')
+       {
+         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)
+           {
+             *bufp++ = '*';
+             *bufp++ = '*';
+             *bufp = '\0';
+           }
+         else
+           {
+             if (p[1] == '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)
+                   snprintf (bufp, avail, "%s(%s)",
+                             abfd->my_archive->filename, abfd->filename);
+                 else
+                   snprintf (bufp, avail, "%s", abfd->filename);
+               }
+             else
+               {
+                 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;
+               }
+
+             /* 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;
+
+             /* Now double all '%' chars, shuffling the string as we go.  */
+             while (extra != 0)
+               {
+                 while ((q[extra] = *q) != '%')
+                   --q;
+                 q[--extra] = '%';
+                 --q;
+               }
+           }
+       }
+      p = p + 2;
+    }
+
+  vfprintf (stderr, new_fmt, ap);
+  va_end (ap);
+
+  putc ('\n', stderr);
 }
 
 /* This is a function pointer to the routine which should handle BFD
@@ -491,60 +653,13 @@ bfd_get_error_handler (void)
 {
   return _bfd_error_handler;
 }
-
-/*
-FUNCTION
-       bfd_archive_filename
-
-SYNOPSIS
-       const char *bfd_archive_filename (bfd *);
-
-DESCRIPTION
-       For a BFD that is a component of an archive, returns a string
-       with both the archive name and file name.  For other BFDs, just
-       returns the file name.
-*/
-
-const char *
-bfd_archive_filename (bfd *abfd)
-{
-  if (abfd == NULL)
-    return _("<unknown>");
-  
-  if (abfd->my_archive)
-    {
-      static size_t curr = 0;
-      static char *buf;
-      size_t needed;
-
-      needed = (strlen (bfd_get_filename (abfd->my_archive))
-               + strlen (bfd_get_filename (abfd)) + 3);
-      if (needed > curr)
-       {
-         if (curr)
-           free (buf);
-         curr = needed + (needed >> 1);
-         buf = bfd_malloc (curr);
-         /* If we can't malloc, fail safe by returning just the file
-            name. This function is only used when building error
-            messages.  */
-         if (!buf)
-           {
-             curr = 0;
-             return bfd_get_filename (abfd);
-           }
-       }
-      sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive),
-              bfd_get_filename (abfd));
-      return buf;
-    }
-  else
-    return bfd_get_filename (abfd);
-}
 \f
 /*
 SECTION
-       Symbols
+       Miscellaneous
+
+SUBSECTION
+       Miscellaneous functions
 */
 
 /*
@@ -690,10 +805,6 @@ bfd_assert (const char *file, int line)
 /* A more or less friendly abort message.  In libbfd.h abort is
    defined to call this function.  */
 
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif
-
 void
 _bfd_abort (const char *file, int line, const char *fn)
 {
@@ -706,7 +817,7 @@ _bfd_abort (const char *file, int line, const char *fn)
       (_("BFD %s internal error, aborting at %s line %d\n"),
        BFD_VERSION_STRING, file, line);
   (*_bfd_error_handler) (_("Please report this bug.\n"));
-  xexit (EXIT_FAILURE);
+  _exit (EXIT_FAILURE);
 }
 
 /*
@@ -765,12 +876,14 @@ bfd_get_sign_extend_vma (bfd *abfd)
 
   name = bfd_get_target (abfd);
 
-  /* Return a proper value for DJGPP COFF (an x86 COFF variant).
+  /* Return a proper value for DJGPP & PE COFF (x86 COFF variants).
      This function is required for DWARF2 support, but there is
      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 (strncmp (name, "coff-go32", sizeof ("coff-go32") - 1) == 0)
+  if (strncmp (name, "coff-go32", sizeof ("coff-go32") - 1) == 0
+      || strcmp (name, "pe-i386") == 0
+      || strcmp (name, "pei-i386") == 0)
     return 1;
 
   bfd_set_error (bfd_error_wrong_format);
@@ -978,6 +1091,29 @@ bfd_scan_vma (const char *string, const char **end, int base)
   return value;
 }
 
+/*
+FUNCTION
+       bfd_copy_private_header_data
+
+SYNOPSIS
+       bfd_boolean bfd_copy_private_header_data (bfd *ibfd, bfd *obfd);
+
+DESCRIPTION
+       Copy private BFD header information from the BFD @var{ibfd} to the
+       the BFD @var{obfd}.  This copies information that may require
+       sections to exist, but does not require symbol tables.  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_copy_private_header_data(ibfd, obfd) \
+.     BFD_SEND (obfd, _bfd_copy_private_header_data, \
+.              (ibfd, obfd))
+
+*/
+
 /*
 FUNCTION
        bfd_copy_private_bfd_data
@@ -1047,13 +1183,21 @@ FUNCTION
 DESCRIPTION
        The following functions exist but have not yet been documented.
 
-.#define bfd_sizeof_headers(abfd, reloc) \
-.       BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+.#define bfd_sizeof_headers(abfd, info) \
+.       BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, info))
 .
 .#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
 .       BFD_SEND (abfd, _bfd_find_nearest_line, \
 .                 (abfd, sec, syms, off, file, func, line))
 .
+.#define bfd_find_line(abfd, syms, sym, file, line) \
+.       BFD_SEND (abfd, _bfd_find_line, \
+.                 (abfd, syms, sym, file, line))
+.
+.#define bfd_find_inliner_info(abfd, file, func, line) \
+.       BFD_SEND (abfd, _bfd_find_inliner_info, \
+.                 (abfd, file, func, line))
+.
 .#define bfd_debug_info_start(abfd) \
 .       BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
 .
@@ -1081,6 +1225,9 @@ DESCRIPTION
 .#define bfd_merge_sections(abfd, link_info) \
 .      BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
 .
+.#define bfd_is_group_section(abfd, sec) \
+.      BFD_SEND (abfd, _bfd_is_group_section, (abfd, sec))
+.
 .#define bfd_discard_group(abfd, sec) \
 .      BFD_SEND (abfd, _bfd_discard_group, (abfd, sec))
 .
@@ -1093,7 +1240,7 @@ DESCRIPTION
 .#define bfd_link_add_symbols(abfd, info) \
 .      BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
 .
-.#define bfd_link_just_syms(sec, info) \
+.#define bfd_link_just_syms(abfd, sec, info) \
 .      BFD_SEND (abfd, _bfd_link_just_syms, (sec, info))
 .
 .#define bfd_final_link(abfd, info) \
@@ -1111,6 +1258,10 @@ DESCRIPTION
 .#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
 .      BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
 .
+.#define bfd_get_synthetic_symtab(abfd, count, syms, dyncount, dynsyms, ret) \
+.      BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, count, syms, \
+.                                                  dyncount, dynsyms, ret))
+.
 .#define bfd_get_dynamic_reloc_upper_bound(abfd) \
 .      BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
 .
@@ -1185,6 +1336,8 @@ bfd_record_phdr (bfd *abfd,
   m->includes_filehdr = includes_filehdr;
   m->includes_phdrs = includes_phdrs;
   m->count = count;
+  m->p_align_valid = FALSE;
+  m->p_align = 0;
   if (count > 0)
     memcpy (m->sections, secs, count * sizeof (asection *));
 
@@ -1276,7 +1429,7 @@ CODE_FRAGMENT
 .  flagword flags;
 .  const struct bfd_arch_info *arch_info;
 .  struct bfd_section *sections;
-.  struct bfd_section **section_tail;
+.  struct bfd_section *section_last;
 .  unsigned int section_count;
 .  struct bfd_hash_table section_htab;
 .};
@@ -1310,18 +1463,19 @@ bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve)
   preserve->arch_info = abfd->arch_info;
   preserve->flags = abfd->flags;
   preserve->sections = abfd->sections;
-  preserve->section_tail = abfd->section_tail;
+  preserve->section_last = abfd->section_last;
   preserve->section_count = abfd->section_count;
   preserve->section_htab = abfd->section_htab;
 
-  if (! bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc))
+  if (! bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc,
+                            sizeof (struct section_hash_entry)))
     return FALSE;
 
   abfd->tdata.any = NULL;
   abfd->arch_info = &bfd_default_arch_struct;
   abfd->flags &= BFD_IN_MEMORY;
   abfd->sections = NULL;
-  abfd->section_tail = &abfd->sections;
+  abfd->section_last = NULL;
   abfd->section_count = 0;
 
   return TRUE;
@@ -1351,7 +1505,7 @@ bfd_preserve_restore (bfd *abfd, struct bfd_preserve *preserve)
   abfd->flags = preserve->flags;
   abfd->section_htab = preserve->section_htab;
   abfd->sections = preserve->sections;
-  abfd->section_tail = preserve->section_tail;
+  abfd->section_last = preserve->section_last;
   abfd->section_count = preserve->section_count;
 
   /* bfd_release frees all memory more recently bfd_alloc'd than
@@ -1386,3 +1540,130 @@ bfd_preserve_finish (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_preserve *preserve)
      objalloc.  */
   bfd_hash_table_free (&preserve->section_htab);
 }
+
+/*
+FUNCTION
+       bfd_emul_get_maxpagesize
+
+SYNOPSIS
+       bfd_vma bfd_emul_get_maxpagesize (const char *);
+
+DESCRIPTION
+       Returns the maximum page size, in bytes, as determined by
+       emulation.
+
+RETURNS
+       Returns the maximum page size in bytes for ELF, abort
+       otherwise.
+*/
+
+bfd_vma
+bfd_emul_get_maxpagesize (const char *emul)
+{
+  const bfd_target *target;
+
+  target = bfd_find_target (emul, NULL);
+  if (target != NULL
+      && target->flavour == bfd_target_elf_flavour)
+    return xvec_get_elf_backend_data (target)->maxpagesize;
+
+  abort ();
+  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 *);
+
+DESCRIPTION
+       Returns the common page size, in bytes, as determined by
+       emulation.
+
+RETURNS
+       Returns the common page size in bytes for ELF, abort otherwise.
+*/
+
+bfd_vma
+bfd_emul_get_commonpagesize (const char *emul)
+{
+  const bfd_target *target;
+
+  target = bfd_find_target (emul, NULL);
+  if (target != NULL
+      && target->flavour == bfd_target_elf_flavour)
+    return xvec_get_elf_backend_data (target)->commonpagesize;
+
+  abort ();
+  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);
+}
This page took 0.029705 seconds and 4 git commands to generate.