X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fbfd.c;h=1f92762d2c3824c52d04b118f2389c5bd7915f21;hb=d1778b88f8d8444f15ecf2dbbbf680c5659efb53;hp=1e6d49b4c3ba19817f52d8aed1ce8c6fe185a9d7;hpb=f8adc62df477edf69a97e91aa53ebefdb9a76dae;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/bfd.c b/bfd/bfd.c index 1e6d49b4c3..1f92762d2c 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -1,5 +1,7 @@ /* Generic BFD library interface and support routines. - Copyright (C) 1990-1991 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001 + Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -16,282 +18,630 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* $Id$ */ - -/*proto* -@section @code{typedef bfd} - -A BFD is has type @code{bfd}; objects of this type are the cornerstone -of any application using @code{libbfd}. References though the BFD and -to data in the BFD give the entire BFD functionality. - -Here is the struct used to define the type @code{bfd}. This contains -the major data about the file, and contains pointers to the rest of -the data. +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* +SECTION + <> + + A BFD has type <>; objects of this type are the + cornerstone of any application using BFD. Using BFD + consists of making references though the BFD and to data in the BFD. + + Here is the structure that defines the type <>. It + contains the major data about the file and pointers + to the rest of the data. + +CODE_FRAGMENT +. +.struct _bfd +.{ +. {* The filename the application opened the BFD with. *} +. CONST char *filename; +. +. {* A pointer to the target jump table. *} +. const struct bfd_target *xvec; +. +. {* To avoid dragging too many header files into every file that +. includes `<>', 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; +. +. {* Is the file descriptor being cached? That is, can it be closed as +. needed, and re-opened when accessed later? *} +. +. 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. *} +. +. boolean target_defaulted; +. +. {* The caching routines use these to maintain a +. least-recently-used list of BFDs *} +. +. struct _bfd *lru_prev, *lru_next; +. +. {* When a file is closed by the caching routines, BFD retains +. state information on the file here: *} +. +. file_ptr where; +. +. {* and here: (``once'' means at least once) *} +. +. boolean opened_once; +. +. {* Set if we have a locally maintained mtime value, rather than +. getting it from the file each time: *} +. +. boolean mtime_set; +. +. {* File modified time, if mtime_set is true: *} +. +. long mtime; +. +. {* Reserved for an unimplemented file locking extension.*} +. +. int ifd; +. +. {* The format which belongs to the BFD. (object, core, etc.) *} +. +. bfd_format format; +. +. {* The direction the BFD was opened with*} +. +. enum bfd_direction {no_direction = 0, +. read_direction = 1, +. write_direction = 2, +. both_direction = 3} direction; +. +. {* Format_specific flags*} +. +. flagword flags; +. +. {* 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. *} +. +. file_ptr origin; +. +. {* Remember when output has begun, to stop strange things +. from happening. *} +. boolean output_has_begun; +. +. {* Pointer to linked list of sections*} +. struct sec *sections; +. +. {* 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 +. { +. struct aout_data_struct *aout_data; +. struct artdata *aout_ar_data; +. struct _oasys_data *oasys_obj_data; +. struct _oasys_ar_data *oasys_ar_data; +. struct coff_tdata *coff_obj_data; +. struct pe_tdata *pe_obj_data; +. struct xcoff_tdata *xcoff_obj_data; +. struct ecoff_tdata *ecoff_obj_data; +. struct ieee_data_struct *ieee_data; +. struct ieee_ar_data_struct *ieee_ar_data; +. struct srec_data_struct *srec_data; +. struct ihex_data_struct *ihex_data; +. struct tekhex_data_struct *tekhex_data; +. struct elf_obj_tdata *elf_obj_data; +. struct nlm_obj_tdata *nlm_obj_data; +. struct bout_data_struct *bout_data; +. struct sun_core_struct *sun_core_data; +. struct sco5_core_struct *sco5_core_data; +. struct trad_core_struct *trad_core_data; +. struct som_data_struct *som_data; +. struct hpux_core_struct *hpux_core_data; +. struct hppabsd_core_struct *hppabsd_core_data; +. struct sgi_core_struct *sgi_core_data; +. struct lynx_core_struct *lynx_core_data; +. struct osf_core_struct *osf_core_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; +. +. {* 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; +.}; +. +*/ -*+++ +#include "bfd.h" +#include "sysdep.h" -$struct _bfd -${ - The filename the application opened the BFD with. +#ifdef ANSI_PROTOTYPES +#include +#else +#include +#endif -$ CONST char *filename; +#include "libiberty.h" +#include "bfdlink.h" +#include "libbfd.h" +#include "coff/internal.h" +#include "coff/sym.h" +#include "libcoff.h" +#include "libecoff.h" +#undef obj_symbols +#include "elf-bfd.h" + +#include + +/* 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 + struct which ultimately gets passed in to the bfd. When it arrives, copy + it to the following struct so that the data will be available in coffcode.h + where it is needed. The typedef's used are defined in bfd.h */ + +/* +SECTION + Error reporting + + Most BFD functions return nonzero on success (check their + individual documentation for precise semantics). On an error, + they call <> to set an error condition that callers + can check by calling <>. + If that returns <>, then check + <>. + + The easiest way to report a BFD error to the user is to + use <>. + +SUBSECTION + Type <> + + The values returned by <> are defined by the + enumerated type <>. + +CODE_FRAGMENT +. +.typedef enum bfd_error +.{ +. bfd_error_no_error = 0, +. bfd_error_system_call, +. bfd_error_invalid_target, +. bfd_error_wrong_format, +. bfd_error_invalid_operation, +. bfd_error_no_memory, +. bfd_error_no_symbols, +. bfd_error_no_armap, +. bfd_error_no_more_archived_files, +. bfd_error_malformed_archive, +. bfd_error_file_not_recognized, +. bfd_error_file_ambiguously_recognized, +. bfd_error_no_contents, +. bfd_error_nonrepresentable_section, +. bfd_error_no_debug_section, +. bfd_error_bad_value, +. bfd_error_file_truncated, +. bfd_error_file_too_big, +. bfd_error_invalid_error_code +.} bfd_error_type; +. +*/ -A pointer to the target jump table. +static bfd_error_type bfd_error = bfd_error_no_error; + +CONST char *CONST bfd_errmsgs[] = { + N_("No error"), + N_("System call error"), + N_("Invalid bfd target"), + N_("File in wrong format"), + N_("Invalid operation"), + N_("Memory exhausted"), + N_("No symbols"), + N_("Archive has no index; run ranlib to add one"), + N_("No more archived files"), + N_("Malformed archive"), + N_("File format not recognized"), + N_("File format is ambiguous"), + N_("Section has no contents"), + N_("Nonrepresentable section on output"), + N_("Symbol needs debug section which does not exist"), + N_("Bad value"), + N_("File truncated"), + N_("File too big"), + N_("#") + }; -$ struct bfd_target *xvec; +/* +FUNCTION + bfd_get_error +SYNOPSIS + bfd_error_type bfd_get_error (void); -To avoid dragging too many header files into every file that -includes @file{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". +DESCRIPTION + Return the current BFD error condition. +*/ -The iostream is the result of an fopen on the filename. +bfd_error_type +bfd_get_error () +{ + return bfd_error; +} -$ char *iostream; +/* +FUNCTION + bfd_set_error -Is the file being cached @xref{File Caching}. +SYNOPSIS + void bfd_set_error (bfd_error_type error_tag); -$ boolean cacheable; +DESCRIPTION + Set the BFD error condition to be @var{error_tag}. +*/ -Marks whether there was a default target specified when the BFD was -opened. This is used to select what matching algorithm to use to chose -the back end. +void +bfd_set_error (error_tag) + bfd_error_type error_tag; +{ + bfd_error = error_tag; +} -$ boolean target_defaulted; +/* +FUNCTION + bfd_errmsg -The caching routines use these to maintain a least-recently-used list of -BFDs (@pxref{File Caching}). +SYNOPSIS + CONST char *bfd_errmsg (bfd_error_type error_tag); -$ struct _bfd *lru_prev, *lru_next; +DESCRIPTION + Return a string describing the error @var{error_tag}, or + the system error if @var{error_tag} is <>. +*/ -When a file is closed by the caching routines, BFD retains state -information on the file here: +CONST char * +bfd_errmsg (error_tag) + bfd_error_type error_tag; +{ +#ifndef errno + extern int errno; +#endif + if (error_tag == bfd_error_system_call) + return xstrerror (errno); -$ file_ptr where; + 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 */ -and here: + return _(bfd_errmsgs [(int)error_tag]); +} -$ boolean opened_once; +/* +FUNCTION + bfd_perror -$ boolean mtime_set; -File modified time +SYNOPSIS + void bfd_perror (CONST char *message); -$ long mtime; +DESCRIPTION + Print to the standard error stream a string describing the + last BFD error that occurred, or the last system error if + the last BFD error was a system call failure. If @var{message} + is non-NULL and non-empty, the error string printed is preceded + by @var{message}, a colon, and a space. It is followed by a newline. +*/ -Reserved for an unimplemented file locking extension. +void +bfd_perror (message) + CONST char *message; +{ + if (bfd_get_error () == bfd_error_system_call) + perror((char *)message); /* must be system error then... */ + else { + if (message == NULL || *message == '\0') + fprintf (stderr, "%s\n", bfd_errmsg (bfd_get_error ())); + else + fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_get_error ())); + } +} -$int ifd; +/* +SUBSECTION + BFD error handler -The format which belongs to the BFD. + 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. -$ bfd_format format; + The BFD error handler acts like printf. -The direction the BFD was opened with +CODE_FRAGMENT +. +.typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...)); +. +*/ -$ enum bfd_direction {no_direction = 0, -$ read_direction = 1, -$ write_direction = 2, -$ both_direction = 3} direction; +/* The program name used when printing BFD error messages. */ -Format_specific flags +static const char *_bfd_error_program_name; -$ flagword flags; +/* This is the default routine to handle BFD error messages. */ -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. +#ifdef ANSI_PROTOTYPES -$ file_ptr origin; +static void _bfd_default_error_handler PARAMS ((const char *s, ...)); -Remember when output has begun, to stop strange things happening. +static void +_bfd_default_error_handler (const char *s, ...) +{ + va_list p; -$ boolean output_has_begun; + if (_bfd_error_program_name != NULL) + fprintf (stderr, "%s: ", _bfd_error_program_name); + else + fprintf (stderr, "BFD: "); -Pointer to linked list of sections + va_start (p, s); -$ struct sec *sections; + vfprintf (stderr, s, p); -The number of sections + va_end (p); -$ unsigned int section_count; + fprintf (stderr, "\n"); +} -Stuff only useful for object files: -The start address. +#else /* ! defined (ANSI_PROTOTYPES) */ -$ bfd_vma start_address; -Used for input and output +static void _bfd_default_error_handler (); -$ unsigned int symcount; -Symbol table for output BFD +static void +_bfd_default_error_handler (va_alist) + va_dcl +{ + va_list p; + const char *s; -$ struct symbol_cache_entry **outsymbols; + if (_bfd_error_program_name != NULL) + fprintf (stderr, "%s: ", _bfd_error_program_name); + else + fprintf (stderr, "BFD: "); -Pointer to structure which contains architecture information + va_start (p); -$ struct bfd_arch_info *arch_info; + s = va_arg (p, const char *); + vfprintf (stderr, s, p); -Stuff only useful for archives: + va_end (p); -$ PTR arelt_data; -$ struct _bfd *my_archive; -$ struct _bfd *next; -$ struct _bfd *archive_head; -$ boolean has_armap; + fprintf (stderr, "\n"); +} -Used by the back end to hold private data. +#endif /* ! defined (ANSI_PROTOTYPES) */ -$ PTR tdata; +/* 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. */ -Used by the application to hold private data +bfd_error_handler_type _bfd_error_handler = _bfd_default_error_handler; -$ PTR usrdata; +/* +FUNCTION + bfd_set_error_handler -Where all the allocated stuff under this BFD goes (@pxref{Memory Usage}). +SYNOPSIS + bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type); -$ struct obstack memory; -$}; +DESCRIPTION + Set the BFD error handler function. Returns the previous + function. +*/ -*--- +bfd_error_handler_type +bfd_set_error_handler (pnew) + bfd_error_handler_type pnew; +{ + bfd_error_handler_type pold; -*/ -#include "bfd.h" -#include "sysdep.h" -#include "libbfd.h" + pold = _bfd_error_handler; + _bfd_error_handler = pnew; + return pold; +} -#undef strerror -extern char *strerror(); +/* +FUNCTION + bfd_set_error_program_name +SYNOPSIS + void bfd_set_error_program_name (const char *); -CONST short _bfd_host_big_endian = 0x0100; - /* Accessing the above as (*(char*)&_bfd_host_big_endian), will - return 1 if the host is big-endian, 0 otherwise. - (assuming that a short is two bytes long!!! FIXME) - (See HOST_IS_BIG_ENDIAN_P in bfd.h.) */ - -/** Error handling - o - Most functions return nonzero on success (check doc for - precise semantics); 0 or NULL on error. - o - Internal errors are documented by the value of bfd_error. - If that is system_call_error then check errno. - o - The easiest way to report this to the user is to use bfd_perror. +DESCRIPTION + Set the program name to use when printing a BFD error. This + is printed before the error message followed by a colon and + space. The string must not be changed after it is passed to + this function. */ -bfd_ec bfd_error = no_error; - -char *bfd_errmsgs[] = { "No error", - "System call error", - "Invalid target", - "File in wrong format", - "Invalid operation", - "Memory exhausted", - "No symbols", - "No relocation info", - "No more archived files", - "Malformed archive", - "Symbol not found", - "File format not recognized", - "File format is ambiguous", - "Section has no contents", - "Nonrepresentable section on output", - "Symbol needs debug section which does not exist", - "#" - }; - -static -void -DEFUN(bfd_nonrepresentable_section,(abfd, name), - CONST bfd * CONST abfd AND - CONST char * CONST name) +void +bfd_set_error_program_name (name) + const char *name; { - printf("bfd error writing file %s, format %s can't represent section %s\n", - abfd->filename, - abfd->xvec->name, - name); - exit(1); + _bfd_error_program_name = name; } -bfd_error_vector_type bfd_error_vector = - { - bfd_nonrepresentable_section - }; +/* +FUNCTION + bfd_get_error_handler -char * -bfd_errmsg (error_tag) - bfd_ec error_tag; -{ -#ifndef errno - extern int errno; -#endif - if (error_tag == system_call_error) - return strerror (errno); +SYNOPSIS + bfd_error_handler_type bfd_get_error_handler (void); - if ((((int)error_tag <(int) no_error) || - ((int)error_tag > (int)invalid_error_code))) - error_tag = invalid_error_code;/* sanity check */ +DESCRIPTION + Return the BFD error handler function. +*/ - return bfd_errmsgs [(int)error_tag]; +bfd_error_handler_type +bfd_get_error_handler () +{ + return _bfd_error_handler; } + +/* +SECTION + Symbols +*/ +/* +FUNCTION + bfd_get_reloc_upper_bound -void bfd_default_error_trap(error_tag) -bfd_ec error_tag; -{ - printf("bfd assert fail (%s)\n", bfd_errmsg(error_tag)); -} +SYNOPSIS + long bfd_get_reloc_upper_bound(bfd *abfd, asection *sect); -void (*bfd_error_trap)() = bfd_default_error_trap; -void (*bfd_error_nonrepresentabltrap)() = bfd_default_error_trap; +DESCRIPTION + Return the number of bytes required to store the + relocation information associated with section @var{sect} + attached to bfd @var{abfd}. If an error occurs, return -1. -void -DEFUN(bfd_perror,(message), - CONST char *message) +*/ + +long +bfd_get_reloc_upper_bound (abfd, asect) + bfd *abfd; + sec_ptr asect; { - if (bfd_error == system_call_error) - perror((char *)message); /* must be system error then... */ - else { - if (message == NULL || *message == '\0') - fprintf (stderr, "%s\n", bfd_errmsg (bfd_error)); - else - fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_error)); + if (abfd->format != bfd_object) { + bfd_set_error (bfd_error_invalid_operation); + return -1; } -} - -/** Symbols */ + return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect)); +} -/* returns the number of octets of storage required */ +/* +FUNCTION + bfd_canonicalize_reloc + +SYNOPSIS + long bfd_canonicalize_reloc + (bfd *abfd, + asection *sec, + arelent **loc, + asymbol **syms); + +DESCRIPTION + Call the back end associated with the open BFD + @var{abfd} and translate the external form of the relocation + information attached to @var{sec} into the internal canonical + form. Place the table into memory at @var{loc}, which has + been preallocated, usually by a call to + <>. Returns the number of relocs, or + -1 on error. + + The @var{syms} table is also needed for horrible internal magic + reasons. -unsigned int -get_reloc_upper_bound (abfd, asect) +*/ +long +bfd_canonicalize_reloc (abfd, asect, location, symbols) bfd *abfd; sec_ptr asect; + arelent **location; + asymbol **symbols; { if (abfd->format != bfd_object) { - bfd_error = invalid_operation; - return 0; + bfd_set_error (bfd_error_invalid_operation); + return -1; } - - return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect)); + return BFD_SEND (abfd, _bfd_canonicalize_reloc, + (abfd, asect, location, symbols)); } -unsigned int -DEFUN(bfd_canonicalize_reloc,(abfd, asect, location, symbols), - bfd *abfd AND - sec_ptr asect AND - arelent **location AND - asymbol **symbols) +/* +FUNCTION + bfd_set_reloc + +SYNOPSIS + void bfd_set_reloc + (bfd *abfd, asection *sec, arelent **rel, unsigned int count) + +DESCRIPTION + Set the relocation pointer and count within + section @var{sec} to the values @var{rel} and @var{count}. + The argument @var{abfd} is ignored. + +*/ + +void +bfd_set_reloc (ignore_abfd, asect, location, count) + bfd *ignore_abfd ATTRIBUTE_UNUSED; + sec_ptr asect; + arelent **location; + unsigned int count; { - if (abfd->format != bfd_object) { - bfd_error = invalid_operation; - return 0; - } - return BFD_SEND (abfd, _bfd_canonicalize_reloc, (abfd, asect, location, symbols)); + asect->orelocation = location; + asect->reloc_count = count; } +/* +FUNCTION + bfd_set_file_flags + +SYNOPSIS + boolean bfd_set_file_flags(bfd *abfd, flagword flags); + +DESCRIPTION + Set the flag word in the BFD @var{abfd} to the value @var{flags}. + + Possible errors are: + o <> - The target bfd was not of object format. + o <> - The target bfd was open for reading. + o <> - + The flag word contained a bit which was not applicable to the + type of file. E.g., an attempt was made to set the <> bit + on a BFD format which does not support demand paging. + +*/ boolean bfd_set_file_flags (abfd, flags) @@ -299,51 +649,128 @@ bfd_set_file_flags (abfd, flags) flagword flags; { if (abfd->format != bfd_object) { - bfd_error = wrong_format; + bfd_set_error (bfd_error_wrong_format); return false; } if (bfd_read_p (abfd)) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return false; } + bfd_get_file_flags (abfd) = flags; if ((flags & bfd_applicable_file_flags (abfd)) != flags) { - bfd_error = invalid_operation; + bfd_set_error (bfd_error_invalid_operation); return false; } - bfd_get_file_flags (abfd) = flags; return true; } - void -bfd_set_reloc (ignore_abfd, asect, location, count) - bfd *ignore_abfd; - sec_ptr asect; - arelent **location; - unsigned int count; +bfd_assert (file, line) + const char *file; + int line; { - asect->orelocation = location; - asect->reloc_count = count; + (*_bfd_error_handler) (_("bfd assertion fail %s:%d"), file, 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_assert(file, line) -char *file; -int line; +_bfd_abort (file, line, fn) + const char *file; + int line; + const char *fn; +{ + if (fn != NULL) + (*_bfd_error_handler) + (_("BFD internal error, aborting at %s line %d in %s\n"), + file, line, fn); + else + (*_bfd_error_handler) + (_("BFD internal error, aborting at %s line %d\n"), + file, line); + (*_bfd_error_handler) (_("Please report this bug.\n")); + xexit (EXIT_FAILURE); +} + +/* +FUNCTION + bfd_get_arch_size + +SYNOPSIS + int bfd_get_arch_size (bfd *abfd); + +DESCRIPTION + Returns the architecture address size, in bits, as determined + by the object file's format. For ELF, this information is + included in the header. + +RETURNS + Returns the arch size in bits if known, <<-1>> otherwise. +*/ + +int +bfd_get_arch_size (abfd) + bfd *abfd; +{ + if (abfd->xvec->flavour == bfd_target_elf_flavour) + return (get_elf_backend_data (abfd))->s->arch_size; + + bfd_set_error (bfd_error_wrong_format); + return -1; +} + +/* +FUNCTION + bfd_get_sign_extend_vma + +SYNOPSIS + int bfd_get_sign_extend_vma (bfd *abfd); + +DESCRIPTION + Indicates if the target architecture "naturally" sign extends + an address. Some architectures implicitly sign extend address + values when they are converted to types larger than the size + of an address. For instance, bfd_get_start_address() will + return an address sign extended to fill a bfd_vma when this is + the case. + +RETURNS + Returns <<1>> if the target architecture is known to sign + extend addresses, <<0>> if the target architecture is known to + not sign extend addresses, and <<-1>> otherwise. +*/ + +int +bfd_get_sign_extend_vma (abfd) + bfd *abfd; { - printf("bfd assertion fail %s:%d\n",file,line); + if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) + return (get_elf_backend_data (abfd)->sign_extend_vma); + + bfd_set_error (bfd_error_wrong_format); + return -1; } +/* +FUNCTION + bfd_set_start_address -/*proto* bfd_set_start_address +SYNOPSIS + boolean bfd_set_start_address(bfd *abfd, bfd_vma vma); -Marks the entry point of an output BFD. Returns @code{true} on -success, @code{false} otherwise. +DESCRIPTION + Make @var{vma} the entry point of output BFD @var{abfd}. -*; PROTO(boolean, bfd_set_start_address,(bfd *, bfd_vma)); +RETURNS + Returns <> on success, <> otherwise. */ boolean @@ -355,14 +782,16 @@ bfd_vma vma; return true; } +/* +FUNCTION + bfd_get_mtime -/*proto* bfd_get_mtime - -Return cached file modification time (e.g. as read from archive header -for archive members, or from file system if we have been called -before); else determine modify time, cache it, and return it. +SYNOPSIS + long bfd_get_mtime(bfd *abfd); -*; PROTO(long, bfd_get_mtime, (bfd *)); +DESCRIPTION + Return the file modification time (as read from the file system, or + from the archive header for archive members). */ @@ -380,72 +809,432 @@ bfd_get_mtime (abfd) if (0 != fstat (fileno (fp), &buf)) return 0; - abfd->mtime_set = true; - abfd->mtime = buf.st_mtime; - return abfd->mtime; + 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 <> 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; +} + +/* +FUNCTION + bfd_get_gp_size + +SYNOPSIS + int bfd_get_gp_size(bfd *abfd); + +DESCRIPTION + Return the maximum size of objects to be optimized using the GP + register under MIPS ECOFF. This is typically set by the <<-G>> + argument to the compiler, assembler or linker. +*/ + +int +bfd_get_gp_size (abfd) + bfd *abfd; +{ + if (abfd->format == bfd_object) + { + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + return ecoff_data (abfd)->gp_size; + else if (abfd->xvec->flavour == bfd_target_elf_flavour) + return elf_gp_size (abfd); + } + return 0; +} + +/* +FUNCTION + bfd_set_gp_size + +SYNOPSIS + void bfd_set_gp_size(bfd *abfd, int i); + +DESCRIPTION + Set the maximum size of objects to be optimized using the GP + register under ECOFF or MIPS ELF. This is typically set by + the <<-G>> argument to the compiler, assembler or linker. +*/ + +void +bfd_set_gp_size (abfd, i) + bfd *abfd; + int i; +{ + /* Don't try to set GP size on an archive or core file! */ + if (abfd->format != bfd_object) + return; + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + ecoff_data (abfd)->gp_size = i; + else if (abfd->xvec->flavour == bfd_target_elf_flavour) + elf_gp_size (abfd) = i; } -/*proto* stuff +/* Get the GP value. This is an internal function used by some of the + relocation special_function routines on targets which support a GP + register. */ + +bfd_vma +_bfd_get_gp_value (abfd) + bfd *abfd; +{ + if (abfd->format == bfd_object) + { + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + return ecoff_data (abfd)->gp; + else if (abfd->xvec->flavour == bfd_target_elf_flavour) + return elf_gp (abfd); + } + return 0; +} + +/* Set the GP value. */ + +void +_bfd_set_gp_value (abfd, v) + bfd *abfd; + bfd_vma v; +{ + if (abfd->format != bfd_object) + return; + if (abfd->xvec->flavour == bfd_target_ecoff_flavour) + ecoff_data (abfd)->gp = v; + else if (abfd->xvec->flavour == bfd_target_elf_flavour) + elf_gp (abfd) = v; +} + +/* +FUNCTION + bfd_scan_vma + +SYNOPSIS + bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base); + +DESCRIPTION + Convert, like <>, a numerical expression + @var{string} into a <> integer, and return that integer. + (Though without as many bells and whistles as <>.) + The expression is assumed to be unsigned (i.e., positive). + If given a @var{base}, it is used as the base for conversion. + A base of 0 causes the function to interpret the string + 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. +*/ -*+ +bfd_vma +bfd_scan_vma (string, end, base) + CONST char *string; + CONST char **end; + int base; +{ + bfd_vma value; + int digit; + + /* Let the host do it if possible. */ + if (sizeof (bfd_vma) <= sizeof (unsigned long)) + return (bfd_vma) 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; + + if (base == 0) + { + if (string[0] == '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? */ + +/* Speed could be improved with a table like hex_value[] in gas. */ +#define HEX_VALUE(c) \ + (isxdigit ((unsigned char) c) \ + ? (isdigit ((unsigned char) c) \ + ? (c - '0') \ + : (10 + c - (islower ((unsigned char) c) ? 'a' : 'A'))) \ + : 42) + + for (value = 0; (digit = HEX_VALUE(*string)) < base; string++) + { + value = value * base + digit; + } -#define bfd_sizeof_headers(abfd, reloc) \ - BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) + if (end) + *end = string; -#define bfd_find_nearest_line(abfd, section, symbols, offset, filename_ptr, func, line_ptr) \ - BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, section, symbols, offset, filename_ptr, func, line_ptr)) + return value; +} -#define bfd_debug_info_start(abfd) \ - BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) +/* +FUNCTION + bfd_copy_private_bfd_data -#define bfd_debug_info_end(abfd) \ - BFD_SEND (abfd, _bfd_debug_info_end, (abfd)) +SYNOPSIS + boolean bfd_copy_private_bfd_data(bfd *ibfd, bfd *obfd); -#define bfd_debug_info_accumulate(abfd, section) \ - BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) +DESCRIPTION + Copy private BFD information from the BFD @var{ibfd} to the + the BFD @var{obfd}. Return <> on success, <> on error. + Possible error returns are: -#define bfd_stat_arch_elt(abfd, stat) \ - BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) + o <> - + Not enough memory exists to create private data for @var{obfd}. -#define bfd_coff_swap_aux_in(a,e,t,c,i) \ - BFD_SEND (a, _bfd_coff_swap_aux_in, (a,e,t,c,i)) +.#define bfd_copy_private_bfd_data(ibfd, obfd) \ +. BFD_SEND (obfd, _bfd_copy_private_bfd_data, \ +. (ibfd, obfd)) -#define bfd_coff_swap_sym_in(a,e,i) \ - BFD_SEND (a, _bfd_coff_swap_sym_in, (a,e,i)) +*/ -#define bfd_coff_swap_lineno_in(a,e,i) \ - BFD_SEND ( a, _bfd_coff_swap_lineno_in, (a,e,i)) +/* +FUNCTION + bfd_merge_private_bfd_data -#define bfd_set_arch_mach(abfd, arch, mach)\ - BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) +SYNOPSIS + boolean bfd_merge_private_bfd_data(bfd *ibfd, bfd *obfd); -#define bfd_coff_swap_reloc_out(abfd, i, o) \ - BFD_SEND (abfd, _bfd_coff_swap_reloc_out, (abfd, i, o)) +DESCRIPTION + Merge private BFD information from the BFD @var{ibfd} to the + the output file BFD @var{obfd} when linking. Return <> + on success, <> on error. Possible error returns are: -#define bfd_coff_swap_lineno_out(abfd, i, o) \ - BFD_SEND (abfd, _bfd_coff_swap_lineno_out, (abfd, i, o)) + o <> - + Not enough memory exists to create private data for @var{obfd}. -#define bfd_coff_swap_aux_out(abfd, i, t,c,o) \ - BFD_SEND (abfd, _bfd_coff_swap_aux_out, (abfd, i,t,c, o)) +.#define bfd_merge_private_bfd_data(ibfd, obfd) \ +. BFD_SEND (obfd, _bfd_merge_private_bfd_data, \ +. (ibfd, obfd)) -#define bfd_coff_swap_sym_out(abfd, i,o) \ - BFD_SEND (abfd, _bfd_coff_swap_sym_out, (abfd, i, o)) +*/ -#define bfd_coff_swap_scnhdr_out(abfd, i,o) \ - BFD_SEND (abfd, _bfd_coff_swap_scnhdr_out, (abfd, i, o)) +/* +FUNCTION + bfd_set_private_flags -#define bfd_coff_swap_filehdr_out(abfd, i,o) \ - BFD_SEND (abfd, _bfd_coff_swap_filehdr_out, (abfd, i, o)) +SYNOPSIS + boolean bfd_set_private_flags(bfd *abfd, flagword flags); -#define bfd_coff_swap_aouthdr_out(abfd, i,o) \ - BFD_SEND (abfd, _bfd_coff_swap_aouthdr_out, (abfd, i, o)) +DESCRIPTION + Set private BFD flag information in the BFD @var{abfd}. + Return <> on success, <> on error. Possible error + returns are: -*- + o <> - + 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)) */ +/* +FUNCTION + stuff + +DESCRIPTION + Stuff which should be documented: + +.#define 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)) +. +. {* 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)) +. +.#define 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)) +. +. +.#define 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)) +. +.#define 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_gc_sections(abfd, link_info) \ +. BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info)) +. +.#define bfd_merge_sections(abfd, link_info) \ +. BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info)) +. +.#define bfd_link_hash_table_create(abfd) \ +. BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) +. +.#define bfd_link_add_symbols(abfd, info) \ +. BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) +. +.#define bfd_final_link(abfd, info) \ +. BFD_SEND (abfd, _bfd_final_link, (abfd, info)) +. +.#define bfd_free_cached_info(abfd) \ +. BFD_SEND (abfd, _bfd_free_cached_info, (abfd)) +. +.#define bfd_get_dynamic_symtab_upper_bound(abfd) \ +. BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd)) +. +.#define bfd_print_private_bfd_data(abfd, file)\ +. BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file)) +. +.#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \ +. BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols)) +. +.#define bfd_get_dynamic_reloc_upper_bound(abfd) \ +. BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd)) +. +.#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \ +. 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_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 *abfd2; + bfd_byte *(*fn) PARAMS ((bfd *, struct bfd_link_info *, + struct bfd_link_order *, bfd_byte *, boolean, + asymbol **)); + + if (link_order->type == bfd_indirect_link_order) + { + abfd2 = link_order->u.indirect.section->owner; + if (abfd2 == 0) + abfd2 = abfd; + } + else + abfd2 = abfd; + fn = abfd2->xvec->_bfd_get_relocated_section_contents; + return (*fn) (abfd, link_info, link_order, data, relocateable, 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; +{ + struct elf_segment_map *m, **pm; + + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + return true; + + m = ((struct elf_segment_map *) + bfd_alloc (abfd, + (sizeof (struct elf_segment_map) + + ((size_t) count - 1) * sizeof (asection *)))); + if (m == NULL) + return false; + + m->next = NULL; + m->p_type = type; + m->p_flags = flags; + m->p_paddr = at; + m->p_flags_valid = flags_valid; + m->p_paddr_valid = at_valid; + m->includes_filehdr = includes_filehdr; + m->includes_phdrs = includes_phdrs; + m->count = count; + if (count > 0) + memcpy (m->sections, secs, count * sizeof (asection *)); + + for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL; pm = &(*pm)->next) + ; + *pm = m; + + return true; +}