/* Generic BFD library interface and support routines.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001
+ 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Written by Cygnus Support.
-This file is part of BFD, the Binary File Descriptor library.
+ This file is part of BFD, the Binary File Descriptor library.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-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. */
+ 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
/*
SECTION
CODE_FRAGMENT
.
-.struct _bfd
+.struct bfd
.{
-. {* The filename the application opened the BFD with. *}
-. const char *filename;
+. {* A unique identifier of the BFD *}
+. unsigned int id;
.
-. {* A pointer to the target jump table. *}
-. const struct bfd_target *xvec;
+. {* The filename the application opened the BFD with. *}
+. const char *filename;
.
-. {* To avoid dragging too many header files into every file that
-. includes `<<bfd.h>>', IOSTREAM has been declared as a "char
-. *", and MTIME as a "long". Their correct types, to which they
-. are cast when used, are "FILE *" and "time_t". The iostream
-. is the result of an fopen on the filename. However, if the
-. BFD_IN_MEMORY flag is set, then iostream is actually a pointer
-. to a bfd_in_memory struct. *}
-. PTR iostream;
+. {* A pointer to the target jump table. *}
+. const struct bfd_target *xvec;
.
-. {* Is the file descriptor being cached? That is, can it be closed as
-. needed, and re-opened when accessed later? *}
+. {* The IOSTREAM, and corresponding IO vector that provide access
+. to the file backing the BFD. *}
+. void *iostream;
+. const struct bfd_iovec *iovec;
.
-. boolean cacheable;
+. {* Is the file descriptor being cached? That is, can it be closed as
+. needed, and re-opened when accessed later? *}
+. bfd_boolean cacheable;
.
-. {* Marks whether there was a default target specified when the
-. BFD was opened. This is used to select which matching algorithm
-. to use to choose the back end. *}
+. {* Marks whether there was a default target specified when the
+. BFD was opened. This is used to select which matching algorithm
+. to use to choose the back end. *}
+. bfd_boolean target_defaulted;
.
-. boolean target_defaulted;
+. {* The caching routines use these to maintain a
+. least-recently-used list of BFDs. *}
+. struct bfd *lru_prev, *lru_next;
.
-. {* The caching routines use these to maintain a
-. least-recently-used list of BFDs *}
+. {* When a file is closed by the caching routines, BFD retains
+. state information on the file here... *}
+. ufile_ptr where;
.
-. struct _bfd *lru_prev, *lru_next;
+. {* ... and here: (``once'' means at least once). *}
+. bfd_boolean opened_once;
.
-. {* When a file is closed by the caching routines, BFD retains
-. state information on the file here: *}
+. {* Set if we have a locally maintained mtime value, rather than
+. getting it from the file each time. *}
+. bfd_boolean mtime_set;
.
-. ufile_ptr where;
+. {* File modified time, if mtime_set is TRUE. *}
+. long mtime;
.
-. {* and here: (``once'' means at least once) *}
+. {* Reserved for an unimplemented file locking extension. *}
+. int ifd;
.
-. boolean opened_once;
+. {* The format which belongs to the BFD. (object, core, etc.) *}
+. bfd_format format;
.
-. {* Set if we have a locally maintained mtime value, rather than
-. getting it from the file each time: *}
+. {* The direction with which the BFD was opened. *}
+. enum bfd_direction
+. {
+. no_direction = 0,
+. read_direction = 1,
+. write_direction = 2,
+. both_direction = 3
+. }
+. direction;
.
-. boolean mtime_set;
+. {* Format_specific flags. *}
+. flagword flags;
.
-. {* File modified time, if mtime_set is true: *}
+. {* Currently my_archive is tested before adding origin to
+. anything. I believe that this can become always an add of
+. origin, with origin set to 0 for non archive files. *}
+. ufile_ptr origin;
.
-. long mtime;
+. {* Remember when output has begun, to stop strange things
+. from happening. *}
+. bfd_boolean output_has_begun;
.
-. {* Reserved for an unimplemented file locking extension.*}
+. {* A hash table for section names. *}
+. struct bfd_hash_table section_htab;
.
-. int ifd;
+. {* Pointer to linked list of sections. *}
+. struct bfd_section *sections;
.
-. {* The format which belongs to the BFD. (object, core, etc.) *}
+. {* The last section on the section list. *}
+. struct bfd_section *section_last;
.
-. bfd_format format;
+. {* The number of sections. *}
+. unsigned int section_count;
.
-. {* The direction the BFD was opened with*}
+. {* Stuff only useful for object files:
+. The start address. *}
+. bfd_vma start_address;
.
-. enum bfd_direction {no_direction = 0,
-. read_direction = 1,
-. write_direction = 2,
-. both_direction = 3} direction;
+. {* Used for input and output. *}
+. unsigned int symcount;
.
-. {* Format_specific flags*}
+. {* Symbol table for output BFD (with symcount entries). *}
+. struct bfd_symbol **outsymbols;
.
-. flagword flags;
+. {* Used for slurped dynamic symbol tables. *}
+. unsigned int dynsymcount;
.
-. {* Currently my_archive is tested before adding origin to
-. anything. I believe that this can become always an add of
-. origin, with origin set to 0 for non archive files. *}
+. {* Pointer to structure which contains architecture information. *}
+. const struct bfd_arch_info *arch_info;
.
-. ufile_ptr origin;
+. {* Flag set if symbols from this BFD should not be exported. *}
+. bfd_boolean no_export;
.
-. {* Remember when output has begun, to stop strange things
-. from happening. *}
-. boolean output_has_begun;
+. {* Stuff only useful for archives. *}
+. void *arelt_data;
+. struct bfd *my_archive; {* The containing archive BFD. *}
+. struct bfd *next; {* The next BFD in the archive. *}
+. struct bfd *archive_head; {* The first BFD in the archive. *}
+. bfd_boolean has_armap;
.
-. {* A hash table for section names. *}
-. struct bfd_hash_table section_htab;
+. {* A chain of BFD structures involved in a link. *}
+. struct bfd *link_next;
.
-. {* Pointer to linked list of sections. *}
-. struct sec *sections;
+. {* A field used by _bfd_generic_link_add_archive_symbols. This will
+. be used only for archive elements. *}
+. int archive_pass;
.
-. {* The place where we add to the section list. *}
-. struct sec **section_tail;
-.
-. {* The number of sections *}
-. unsigned int section_count;
-.
-. {* Stuff only useful for object files:
-. The start address. *}
-. bfd_vma start_address;
-.
-. {* Used for input and output*}
-. unsigned int symcount;
-.
-. {* Symbol table for output BFD (with symcount entries) *}
-. struct symbol_cache_entry **outsymbols;
-.
-. {* Pointer to structure which contains architecture information*}
-. const struct bfd_arch_info *arch_info;
-.
-. {* Stuff only useful for archives:*}
-. PTR arelt_data;
-. struct _bfd *my_archive; {* The containing archive BFD. *}
-. struct _bfd *next; {* The next BFD in the archive. *}
-. struct _bfd *archive_head; {* The first BFD in the archive. *}
-. boolean has_armap;
-.
-. {* A chain of BFD structures involved in a link. *}
-. struct _bfd *link_next;
-.
-. {* A field used by _bfd_generic_link_add_archive_symbols. This will
-. be used only for archive elements. *}
-. int archive_pass;
-.
-. {* Used by the back end to hold private data. *}
-.
-. union
-. {
+. {* Used by the back end to hold private data. *}
+. union
+. {
. struct aout_data_struct *aout_data;
. struct artdata *aout_ar_data;
. struct _oasys_data *oasys_obj_data;
. struct cisco_core_struct *cisco_core_data;
. struct versados_data_struct *versados_data;
. struct netbsd_core_struct *netbsd_core_data;
-. PTR any;
-. } tdata;
-.
-. {* Used by the application to hold private data*}
-. PTR usrdata;
+. struct mach_o_data_struct *mach_o_data;
+. struct mach_o_fat_data_struct *mach_o_fat_data;
+. struct bfd_pef_data_struct *pef_data;
+. struct bfd_pef_xlib_data_struct *pef_xlib_data;
+. struct bfd_sym_data_struct *sym_data;
+. void *any;
+. }
+. tdata;
+.
+. {* Used by the application to hold private data. *}
+. void *usrdata;
.
. {* Where all the allocated stuff under this BFD goes. This is a
-. struct objalloc *, but we use PTR to avoid requiring the inclusion of
-. objalloc.h. *}
-. PTR memory;
+. struct objalloc *, but we use void * to avoid requiring the inclusion
+. of objalloc.h. *}
+. void *memory;
.};
.
*/
#include "bfd.h"
+#include "bfdver.h"
#include "sysdep.h"
-
-#ifdef ANSI_PROTOTYPES
#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
#include "libiberty.h"
#include "safe-ctype.h"
#include "bfdlink.h"
. bfd_error_file_truncated,
. bfd_error_file_too_big,
. bfd_error_invalid_error_code
-.} bfd_error_type;
+.}
+.bfd_error_type;
.
*/
*/
bfd_error_type
-bfd_get_error ()
+bfd_get_error (void)
{
return bfd_error;
}
*/
void
-bfd_set_error (error_tag)
- bfd_error_type error_tag;
+bfd_set_error (bfd_error_type error_tag)
{
bfd_error = error_tag;
}
*/
const char *
-bfd_errmsg (error_tag)
- bfd_error_type error_tag;
+bfd_errmsg (bfd_error_type error_tag)
{
#ifndef errno
extern int errno;
if (error_tag == bfd_error_system_call)
return xstrerror (errno);
- if ((((int) error_tag < (int) bfd_error_no_error) ||
- ((int) error_tag > (int) bfd_error_invalid_error_code)))
- error_tag = bfd_error_invalid_error_code;/* sanity check */
+ if (error_tag > bfd_error_invalid_error_code)
+ error_tag = bfd_error_invalid_error_code; /* sanity check */
- return _(bfd_errmsgs [(int)error_tag]);
+ return _(bfd_errmsgs [error_tag]);
}
/*
*/
void
-bfd_perror (message)
- const char *message;
+bfd_perror (const char *message)
{
if (bfd_get_error () == bfd_error_system_call)
/* Must be a system error then. */
- perror ((char *)message);
+ perror ((char *) message);
else
{
if (message == NULL || *message == '\0')
Some BFD functions want to print messages describing the
problem. They call a BFD error handler function. This
- function may be overriden by the program.
+ function may be overridden by the program.
The BFD error handler acts like printf.
CODE_FRAGMENT
.
-.typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+.typedef void (*bfd_error_handler_type) (const char *, ...);
.
*/
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 PARAMS ((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.
+ */
-static void
-_bfd_default_error_handler VPARAMS ((const char *s, ...))
+void
+_bfd_default_error_handler (const char *fmt, ...)
{
+ 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_OPEN (p, s);
- VA_FIXEDARG (p, const char *, s);
- vfprintf (stderr, s, p);
- VA_CLOSE (p);
+ va_start (ap, fmt);
+ new_fmt = fmt;
+ bufp = buf;
+
+ /* Reserve enough space for the existing format string. */
+ avail -= strlen (fmt) + 1;
+ if (avail > 1000)
+ abort ();
- fprintf (stderr, "\n");
+ 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->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 = sec->owner;
+ const char *group = NULL;
+ struct coff_comdat_info *ci;
+
+ 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
*/
bfd_error_handler_type
-bfd_set_error_handler (pnew)
- bfd_error_handler_type pnew;
+bfd_set_error_handler (bfd_error_handler_type pnew)
{
bfd_error_handler_type pold;
*/
void
-bfd_set_error_program_name (name)
- const char *name;
+bfd_set_error_program_name (const char *name)
{
_bfd_error_program_name = name;
}
*/
bfd_error_handler_type
-bfd_get_error_handler ()
+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 (abfd)
- bfd *abfd;
-{
- 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 ((bfd_size_type) 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
bfd_get_reloc_upper_bound
SYNOPSIS
- long bfd_get_reloc_upper_bound(bfd *abfd, asection *sect);
+ long bfd_get_reloc_upper_bound (bfd *abfd, asection *sect);
DESCRIPTION
Return the number of bytes required to store the
*/
long
-bfd_get_reloc_upper_bound (abfd, asect)
- bfd *abfd;
- sec_ptr asect;
+bfd_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
{
if (abfd->format != bfd_object)
{
SYNOPSIS
long bfd_canonicalize_reloc
- (bfd *abfd,
- asection *sec,
- arelent **loc,
- asymbol **syms);
+ (bfd *abfd, asection *sec, arelent **loc, asymbol **syms);
DESCRIPTION
Call the back end associated with the open BFD
*/
long
-bfd_canonicalize_reloc (abfd, asect, location, symbols)
- bfd *abfd;
- sec_ptr asect;
- arelent **location;
- asymbol **symbols;
+bfd_canonicalize_reloc (bfd *abfd,
+ sec_ptr asect,
+ arelent **location,
+ asymbol **symbols)
{
if (abfd->format != bfd_object)
{
SYNOPSIS
void bfd_set_reloc
- (bfd *abfd, asection *sec, arelent **rel, unsigned int count)
+ (bfd *abfd, asection *sec, arelent **rel, unsigned int count);
DESCRIPTION
Set the relocation pointer and count within
*/
void
-bfd_set_reloc (ignore_abfd, asect, location, count)
- bfd *ignore_abfd ATTRIBUTE_UNUSED;
- sec_ptr asect;
- arelent **location;
- unsigned int count;
+bfd_set_reloc (bfd *ignore_abfd ATTRIBUTE_UNUSED,
+ sec_ptr asect,
+ arelent **location,
+ unsigned int count)
{
asect->orelocation = location;
asect->reloc_count = count;
bfd_set_file_flags
SYNOPSIS
- boolean bfd_set_file_flags(bfd *abfd, flagword flags);
+ bfd_boolean bfd_set_file_flags (bfd *abfd, flagword flags);
DESCRIPTION
Set the flag word in the BFD @var{abfd} to the value @var{flags}.
*/
-boolean
-bfd_set_file_flags (abfd, flags)
- bfd *abfd;
- flagword flags;
+bfd_boolean
+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;
}
bfd_get_file_flags (abfd) = 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
-bfd_assert (file, line)
- const char *file;
- int line;
+bfd_assert (const char *file, int line)
{
(*_bfd_error_handler) (_("BFD %s assertion fail %s:%d"),
BFD_VERSION_STRING, file, line);
#endif
void
-_bfd_abort (file, line, fn)
- const char *file;
- int line;
- const char *fn;
+_bfd_abort (const char *file, int line, const char *fn)
{
if (fn != NULL)
(*_bfd_error_handler)
BFD_VERSION_STRING, file, line, fn);
else
(*_bfd_error_handler)
- (_("BFD %sinternal error, aborting at %s line %d\n"),
+ (_("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);
*/
int
-bfd_get_arch_size (abfd)
- bfd *abfd;
+bfd_get_arch_size (bfd *abfd)
{
if (abfd->xvec->flavour == bfd_target_elf_flavour)
- return (get_elf_backend_data (abfd))->s->arch_size;
+ return get_elf_backend_data (abfd)->s->arch_size;
- bfd_set_error (bfd_error_wrong_format);
return -1;
}
*/
int
-bfd_get_sign_extend_vma (abfd)
- bfd *abfd;
+bfd_get_sign_extend_vma (bfd *abfd)
{
char *name;
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
- return (get_elf_backend_data (abfd)->sign_extend_vma);
+ return get_elf_backend_data (abfd)->sign_extend_vma;
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);
bfd_set_start_address
SYNOPSIS
- boolean bfd_set_start_address(bfd *abfd, bfd_vma vma);
+ bfd_boolean bfd_set_start_address (bfd *abfd, bfd_vma vma);
DESCRIPTION
Make @var{vma} the entry point of output BFD @var{abfd}.
RETURNS
- Returns <<true>> on success, <<false>> otherwise.
+ Returns <<TRUE>> on success, <<FALSE>> otherwise.
*/
-boolean
-bfd_set_start_address (abfd, vma)
- bfd *abfd;
- bfd_vma vma;
+bfd_boolean
+bfd_set_start_address (bfd *abfd, bfd_vma vma)
{
abfd->start_address = vma;
- return true;
-}
-
-/*
-FUNCTION
- bfd_get_mtime
-
-SYNOPSIS
- long bfd_get_mtime(bfd *abfd);
-
-DESCRIPTION
- Return the file modification time (as read from the file system, or
- from the archive header for archive members).
-
-*/
-
-long
-bfd_get_mtime (abfd)
- bfd *abfd;
-{
- FILE *fp;
- struct stat buf;
-
- if (abfd->mtime_set)
- return abfd->mtime;
-
- fp = bfd_cache_lookup (abfd);
- if (0 != fstat (fileno (fp), &buf))
- return 0;
-
- abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */
- return buf.st_mtime;
-}
-
-/*
-FUNCTION
- bfd_get_size
-
-SYNOPSIS
- long bfd_get_size(bfd *abfd);
-
-DESCRIPTION
- Return the file size (as read from file system) for the file
- associated with BFD @var{abfd}.
-
- The initial motivation for, and use of, this routine is not
- so we can get the exact size of the object the BFD applies to, since
- that might not be generally possible (archive members for example).
- It would be ideal if someone could eventually modify
- it so that such results were guaranteed.
-
- Instead, we want to ask questions like "is this NNN byte sized
- object I'm about to try read from file offset YYY reasonable?"
- As as example of where we might do this, some object formats
- use string tables for which the first <<sizeof (long)>> bytes of the
- table contain the size of the table itself, including the size bytes.
- If an application tries to read what it thinks is one of these
- string tables, without some way to validate the size, and for
- some reason the size is wrong (byte swapping error, wrong location
- for the string table, etc.), the only clue is likely to be a read
- error when it tries to read the table, or a "virtual memory
- exhausted" error when it tries to allocate 15 bazillon bytes
- of space for the 15 bazillon byte table it is about to read.
- This function at least allows us to answer the quesion, "is the
- size reasonable?".
-*/
-
-long
-bfd_get_size (abfd)
- bfd *abfd;
-{
- FILE *fp;
- struct stat buf;
-
- if ((abfd->flags & BFD_IN_MEMORY) != 0)
- return ((struct bfd_in_memory *) abfd->iostream)->size;
-
- fp = bfd_cache_lookup (abfd);
- if (0 != fstat (fileno (fp), & buf))
- return 0;
-
- return buf.st_size;
+ return TRUE;
}
/*
bfd_get_gp_size
SYNOPSIS
- unsigned int bfd_get_gp_size(bfd *abfd);
+ unsigned int bfd_get_gp_size (bfd *abfd);
DESCRIPTION
Return the maximum size of objects to be optimized using the GP
*/
unsigned int
-bfd_get_gp_size (abfd)
- bfd *abfd;
+bfd_get_gp_size (bfd *abfd)
{
if (abfd->format == bfd_object)
{
bfd_set_gp_size
SYNOPSIS
- void bfd_set_gp_size(bfd *abfd, unsigned int i);
+ void bfd_set_gp_size (bfd *abfd, unsigned int i);
DESCRIPTION
Set the maximum size of objects to be optimized using the GP
*/
void
-bfd_set_gp_size (abfd, i)
- bfd *abfd;
- unsigned int i;
+bfd_set_gp_size (bfd *abfd, unsigned int i)
{
/* Don't try to set GP size on an archive or core file! */
if (abfd->format != bfd_object)
register. */
bfd_vma
-_bfd_get_gp_value (abfd)
- bfd *abfd;
+_bfd_get_gp_value (bfd *abfd)
{
+ if (! abfd)
+ return 0;
if (abfd->format != bfd_object)
return 0;
/* Set the GP value. */
void
-_bfd_set_gp_value (abfd, v)
- bfd *abfd;
- bfd_vma v;
+_bfd_set_gp_value (bfd *abfd, bfd_vma v)
{
+ if (! abfd)
+ BFD_FAIL ();
if (abfd->format != bfd_object)
return;
bfd_scan_vma
SYNOPSIS
- bfd_vma bfd_scan_vma(const char *string, const char **end, int base);
+ bfd_vma bfd_scan_vma (const char *string, const char **end, int base);
DESCRIPTION
Convert, like <<strtoul>>, a numerical expression
in hex if a leading "0x" or "0X" is found, otherwise
in octal if a leading zero is found, otherwise in decimal.
- Overflow is not detected.
+ If the value would overflow, the maximum <<bfd_vma>> value is
+ returned.
*/
bfd_vma
-bfd_scan_vma (string, end, base)
- const char *string;
- const char **end;
- int base;
+bfd_scan_vma (const char *string, const char **end, int base)
{
bfd_vma value;
- int digit;
+ bfd_vma cutoff;
+ unsigned int cutlim;
+ int overflow;
/* Let the host do it if possible. */
if (sizeof (bfd_vma) <= sizeof (unsigned long))
- return (bfd_vma) strtoul (string, (char **) end, base);
+ return strtoul (string, (char **) end, base);
- /* A negative base makes no sense, and we only need to go as high as hex. */
- if ((base < 0) || (base > 16))
- return (bfd_vma) 0;
+#ifdef HAVE_STRTOULL
+ if (sizeof (bfd_vma) <= sizeof (unsigned long long))
+ return strtoull (string, (char **) end, base);
+#endif
if (base == 0)
{
{
if ((string[1] == 'x') || (string[1] == 'X'))
base = 16;
- /* XXX should we also allow "0b" or "0B" to set base to 2? */
else
base = 8;
}
- else
- base = 10;
}
- if ((base == 16) &&
- (string[0] == '0') && ((string[1] == 'x') || (string[1] == 'X')))
- string += 2;
- /* XXX should we also skip over "0b" or "0B" if base is 2? */
+ if ((base < 2) || (base > 36))
+ base = 10;
+
+ if (base == 16
+ && string[0] == '0'
+ && (string[1] == 'x' || string[1] == 'X')
+ && ISXDIGIT (string[2]))
+ {
+ string += 2;
+ }
+
+ cutoff = (~ (bfd_vma) 0) / (bfd_vma) base;
+ cutlim = (~ (bfd_vma) 0) % (bfd_vma) base;
+ value = 0;
+ overflow = 0;
+ while (1)
+ {
+ unsigned int digit;
-/* Speed could be improved with a table like hex_value[] in gas. */
-#define HEX_VALUE(c) \
- (ISXDIGIT (c) \
- ? (ISDIGIT (c) \
- ? (c - '0') \
- : (10 + c - (ISLOWER (c) ? 'a' : 'A'))) \
- : 42)
+ digit = *string;
+ if (ISDIGIT (digit))
+ digit = digit - '0';
+ else if (ISALPHA (digit))
+ digit = TOUPPER (digit) - 'A' + 10;
+ else
+ break;
+ if (digit >= (unsigned int) base)
+ break;
+ if (value > cutoff || (value == cutoff && digit > cutlim))
+ overflow = 1;
+ value = value * base + digit;
+ ++string;
+ }
- for (value = 0; (digit = HEX_VALUE (* string)) < base; string ++)
- value = value * base + digit;
+ if (overflow)
+ value = ~ (bfd_vma) 0;
- if (end)
- * end = string;
+ if (end != NULL)
+ *end = string;
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
SYNOPSIS
- boolean bfd_copy_private_bfd_data(bfd *ibfd, bfd *obfd);
+ bfd_boolean bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd);
DESCRIPTION
Copy private BFD information from the BFD @var{ibfd} to the
- the BFD @var{obfd}. Return <<true>> on success, <<false>> on error.
+ the BFD @var{obfd}. Return <<TRUE>> on success, <<FALSE>> on error.
Possible error returns are:
o <<bfd_error_no_memory>> -
bfd_merge_private_bfd_data
SYNOPSIS
- boolean bfd_merge_private_bfd_data(bfd *ibfd, bfd *obfd);
+ 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:
+ 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}.
bfd_set_private_flags
SYNOPSIS
- boolean bfd_set_private_flags(bfd *abfd, flagword flags);
+ bfd_boolean bfd_set_private_flags (bfd *abfd, flagword flags);
DESCRIPTION
Set private BFD flag information in the BFD @var{abfd}.
- Return <<true>> on success, <<false>> on error. Possible error
+ 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_set_private_flags(abfd, flags) \
-. BFD_SEND (abfd, _bfd_set_private_flags, \
-. (abfd, flags))
+. BFD_SEND (abfd, _bfd_set_private_flags, (abfd, flags))
*/
/*
FUNCTION
- stuff
+ Other functions
DESCRIPTION
- Stuff which should be documented:
+ The following functions exist but have not yet been documented.
.#define bfd_sizeof_headers(abfd, reloc) \
-. BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+. BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
.
.#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))
+. 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))
.
-. {* Do these three do anything useful at all, for any back end? *}
.#define bfd_debug_info_start(abfd) \
-. BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+. BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
.
.#define bfd_debug_info_end(abfd) \
-. BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+. BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
.
.#define bfd_debug_info_accumulate(abfd, section) \
-. BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
-.
+. BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
.
.#define bfd_stat_arch_elt(abfd, stat) \
-. BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+. BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
.
.#define bfd_update_armap_timestamp(abfd) \
-. BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+. BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
.
.#define bfd_set_arch_mach(abfd, arch, mach)\
-. BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+. BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
.
.#define bfd_relax_section(abfd, section, link_info, again) \
. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
.#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))
+.
.#define bfd_link_hash_table_create(abfd) \
. BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
.
+.#define bfd_link_hash_table_free(abfd, hash) \
+. BFD_SEND (abfd, _bfd_link_hash_table_free, (hash))
+.
.#define bfd_link_add_symbols(abfd, info) \
. BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
.
+.#define bfd_link_just_syms(abfd, sec, info) \
+. BFD_SEND (abfd, _bfd_link_just_syms, (sec, info))
+.
.#define bfd_final_link(abfd, info) \
. BFD_SEND (abfd, _bfd_final_link, (abfd, info))
.
.#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))
.
. BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
.
.extern bfd_byte *bfd_get_relocated_section_contents
-. PARAMS ((bfd *, struct bfd_link_info *,
-. struct bfd_link_order *, bfd_byte *,
-. boolean, asymbol **));
+. (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *,
+. bfd_boolean, asymbol **);
.
*/
bfd_byte *
-bfd_get_relocated_section_contents (abfd, link_info, link_order, data,
- relocateable, symbols)
- bfd *abfd;
- struct bfd_link_info *link_info;
- struct bfd_link_order *link_order;
- bfd_byte *data;
- boolean relocateable;
- asymbol **symbols;
+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,
+ asymbol **symbols)
{
bfd *abfd2;
- bfd_byte *(*fn) PARAMS ((bfd *, struct bfd_link_info *,
- struct bfd_link_order *, bfd_byte *, boolean,
- asymbol **));
+ bfd_byte *(*fn) (bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, bfd_boolean, asymbol **);
if (link_order->type == bfd_indirect_link_order)
{
fn = abfd2->xvec->_bfd_get_relocated_section_contents;
- return (*fn) (abfd, link_info, link_order, data, relocateable, symbols);
+ return (*fn) (abfd, link_info, link_order, data, relocatable, symbols);
}
/* Record information about an ELF program header. */
-boolean
-bfd_record_phdr (abfd, type, flags_valid, flags, at_valid, at,
- includes_filehdr, includes_phdrs, count, secs)
- bfd *abfd;
- unsigned long type;
- boolean flags_valid;
- flagword flags;
- boolean at_valid;
- bfd_vma at;
- boolean includes_filehdr;
- boolean includes_phdrs;
- unsigned int count;
- asection **secs;
+bfd_boolean
+bfd_record_phdr (bfd *abfd,
+ unsigned long type,
+ bfd_boolean flags_valid,
+ flagword flags,
+ bfd_boolean at_valid,
+ bfd_vma at,
+ bfd_boolean includes_filehdr,
+ bfd_boolean includes_phdrs,
+ unsigned int count,
+ asection **secs)
{
struct elf_segment_map *m, **pm;
bfd_size_type amt;
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_alloc (abfd, amt);
+ m = bfd_alloc (abfd, amt);
if (m == NULL)
- return false;
+ return FALSE;
m->next = NULL;
m->p_type = type;
;
*pm = m;
- return true;
+ return TRUE;
}
void
-bfd_sprintf_vma (abfd, buf, value)
- bfd *abfd;
- char *buf;
- bfd_vma value;
+bfd_sprintf_vma (bfd *abfd, char *buf, bfd_vma value)
{
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
get_elf_backend_data (abfd)->elf_backend_sprintf_vma (abfd, buf, value);
}
void
-bfd_fprintf_vma (abfd, stream, value)
- bfd *abfd;
- PTR stream;
- bfd_vma value;
+bfd_fprintf_vma (bfd *abfd, void *stream, bfd_vma value)
{
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
get_elf_backend_data (abfd)->elf_backend_fprintf_vma (abfd, stream, value);
bfd_alt_mach_code
SYNOPSIS
- boolean bfd_alt_mach_code(bfd *abfd, int index);
+ bfd_boolean bfd_alt_mach_code (bfd *abfd, int alternative);
DESCRIPTION
When more than one machine code number is available for the
same machine type, this function can be used to switch between
- the preferred one (index == 0) and any others. Currently,
+ the preferred one (alternative == 0) and any others. Currently,
only ELF supports this feature, with up to two alternate
machine codes.
*/
-boolean
-bfd_alt_mach_code (abfd, index)
- bfd *abfd;
- int index;
+bfd_boolean
+bfd_alt_mach_code (bfd *abfd, int alternative)
{
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
{
int code;
- switch (index)
+ switch (alternative)
{
case 0:
code = get_elf_backend_data (abfd)->elf_machine_code;
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;
+}
+
+/*
+CODE_FRAGMENT
+
+.struct bfd_preserve
+.{
+. void *marker;
+. void *tdata;
+. flagword flags;
+. const struct bfd_arch_info *arch_info;
+. struct bfd_section *sections;
+. struct bfd_section *section_last;
+. unsigned int section_count;
+. struct bfd_hash_table section_htab;
+.};
+.
+*/
+
+/*
+FUNCTION
+ bfd_preserve_save
+
+SYNOPSIS
+ bfd_boolean bfd_preserve_save (bfd *, struct bfd_preserve *);
+
+DESCRIPTION
+ When testing an object for compatibility with a particular
+ target back-end, the back-end object_p function needs to set
+ up certain fields in the bfd on successfully recognizing the
+ object. This typically happens in a piecemeal fashion, with
+ failures possible at many points. On failure, the bfd is
+ supposed to be restored to its initial state, which is
+ virtually impossible. However, restoring a subset of the bfd
+ state works in practice. This function stores the subset and
+ reinitializes the bfd.
+
+*/
+
+bfd_boolean
+bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve)
+{
+ preserve->tdata = abfd->tdata.any;
+ preserve->arch_info = abfd->arch_info;
+ preserve->flags = abfd->flags;
+ preserve->sections = abfd->sections;
+ 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))
+ return FALSE;
+
+ abfd->tdata.any = NULL;
+ abfd->arch_info = &bfd_default_arch_struct;
+ abfd->flags &= BFD_IN_MEMORY;
+ abfd->sections = NULL;
+ abfd->section_last = NULL;
+ abfd->section_count = 0;
+
+ return TRUE;
+}
+
+/*
+FUNCTION
+ bfd_preserve_restore
+
+SYNOPSIS
+ void bfd_preserve_restore (bfd *, struct bfd_preserve *);
+
+DESCRIPTION
+ This function restores bfd state saved by bfd_preserve_save.
+ If MARKER is non-NULL in struct bfd_preserve then that block
+ and all subsequently bfd_alloc'd memory is freed.
+
+*/
+
+void
+bfd_preserve_restore (bfd *abfd, struct bfd_preserve *preserve)
+{
+ bfd_hash_table_free (&abfd->section_htab);
+
+ abfd->tdata.any = preserve->tdata;
+ abfd->arch_info = preserve->arch_info;
+ abfd->flags = preserve->flags;
+ abfd->section_htab = preserve->section_htab;
+ abfd->sections = preserve->sections;
+ abfd->section_last = preserve->section_last;
+ abfd->section_count = preserve->section_count;
+
+ /* bfd_release frees all memory more recently bfd_alloc'd than
+ its arg, as well as its arg. */
+ if (preserve->marker != NULL)
+ {
+ bfd_release (abfd, preserve->marker);
+ preserve->marker = NULL;
+ }
+}
+
+/*
+FUNCTION
+ bfd_preserve_finish
+
+SYNOPSIS
+ void bfd_preserve_finish (bfd *, struct bfd_preserve *);
+
+DESCRIPTION
+ This function should be called when the bfd state saved by
+ bfd_preserve_save is no longer needed. ie. when the back-end
+ object_p function returns with success.
+
+*/
+
+void
+bfd_preserve_finish (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_preserve *preserve)
+{
+ /* It would be nice to be able to free more memory here, eg. old
+ tdata, but that's not possible since these blocks are sitting
+ inside bfd_alloc'd memory. The section hash is on a separate
+ objalloc. */
+ bfd_hash_table_free (&preserve->section_htab);
}