X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Fbfd.c;h=5a23c5d690f406cbd8245cf3345273ff2b83bd18;hb=e98fe4f7b54cbdf29aef9287bbb1bea8801dd05a;hp=1a78c6ea27fb1ad1c8b578795f762fa3ab554d54;hpb=fbb8fe5c6e04b6c88f37c7c706a30c9bd7590c3f;p=binutils-gdb.git diff --git a/bfd/bfd.c b/bfd/bfd.c index 1a78c6ea27f..5a23c5d690f 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -1,5 +1,5 @@ /* Generic BFD library interface and support routines. - Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. + Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -16,7 +16,7 @@ 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. */ +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* SECTION @@ -38,14 +38,16 @@ CODE_FRAGMENT . CONST char *filename; . . {* A pointer to the target jump table. *} -. struct bfd_target *xvec; +. 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. *} -. char *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? *} @@ -127,7 +129,7 @@ CODE_FRAGMENT . struct symbol_cache_entry **outsymbols; . . {* Pointer to structure which contains architecture information*} -. struct bfd_arch_info *arch_info; +. const struct bfd_arch_info *arch_info; . . {* Stuff only useful for archives:*} . PTR arelt_data; @@ -152,10 +154,13 @@ CODE_FRAGMENT . 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; @@ -168,6 +173,9 @@ CODE_FRAGMENT . 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; . @@ -182,6 +190,13 @@ CODE_FRAGMENT #include "bfd.h" #include "sysdep.h" + +#ifdef ANSI_PROTOTYPES +#include +#else +#include +#endif + #include "bfdlink.h" #include "libbfd.h" #include "coff/internal.h" @@ -189,7 +204,16 @@ CODE_FRAGMENT #include "libcoff.h" #include "libecoff.h" #undef obj_symbols -#include "libelf.h" +#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 */ + /* @@ -223,6 +247,7 @@ CODE_FRAGMENT . 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, @@ -232,6 +257,7 @@ CODE_FRAGMENT . 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; . @@ -250,6 +276,7 @@ CONST char *CONST bfd_errmsgs[] = { "Invalid operation", "Memory exhausted", "No symbols", + "Archive has no index; run ranlib to add one", "No more archived files", "Malformed archive", "File format not recognized", @@ -259,6 +286,7 @@ CONST char *CONST bfd_errmsgs[] = { "Symbol needs debug section which does not exist", "Bad value", "File truncated", + "File too big", "#" }; @@ -355,6 +383,126 @@ bfd_perror (message) } } +/* +SUBSECTION + BFD error handler + + 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. + + The BFD error handler acts like printf. + +CODE_FRAGMENT +. +.typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...)); +. +*/ + +/* The program name used when printing BFD error messages. */ + +static const char *_bfd_error_program_name; + +/* This is the default routine to handle BFD error messages. */ + +#ifdef ANSI_PROTOTYPES + +static void _bfd_default_error_handler PARAMS ((const char *s, ...)); + +static void +_bfd_default_error_handler (const char *s, ...) +{ + va_list p; + + if (_bfd_error_program_name != NULL) + fprintf (stderr, "%s: ", _bfd_error_program_name); + + va_start (p, s); + + vfprintf (stderr, s, p); + + va_end (p); + + fprintf (stderr, "\n"); +} + +#else /* ! defined (ANSI_PROTOTYPES) */ + +static void _bfd_default_error_handler (); + +static void +_bfd_default_error_handler (va_alist) + va_dcl +{ + va_list p; + const char *s; + + if (_bfd_error_program_name != NULL) + fprintf (stderr, "%s: ", _bfd_error_program_name); + + va_start (p); + + s = va_arg (p, const char *); + vfprintf (stderr, s, p); + + va_end (p); + + fprintf (stderr, "\n"); +} + +#endif /* ! defined (ANSI_PROTOTYPES) */ + +/* 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. */ + +bfd_error_handler_type _bfd_error_handler = _bfd_default_error_handler; + +/* +FUNCTION + bfd_set_error_handler + +SYNOPSIS + bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type); + +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; + + pold = _bfd_error_handler; + _bfd_error_handler = pnew; + return pold; +} + +/* +FUNCTION + bfd_set_error_program_name + +SYNOPSIS + void bfd_set_error_program_name (const char *); + +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. +*/ + +void +bfd_set_error_program_name (name) + const char *name; +{ + _bfd_error_program_name = name; +} /* SECTION @@ -366,24 +514,24 @@ FUNCTION bfd_get_reloc_upper_bound SYNOPSIS - unsigned int 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 relocation information associated with section @var{sect} - attached to bfd @var{abfd}. + attached to bfd @var{abfd}. If an error occurs, return -1. */ -unsigned int +long bfd_get_reloc_upper_bound (abfd, asect) bfd *abfd; sec_ptr asect; { if (abfd->format != bfd_object) { bfd_set_error (bfd_error_invalid_operation); - return 0; + return -1; } return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect)); @@ -394,7 +542,7 @@ FUNCTION bfd_canonicalize_reloc SYNOPSIS - unsigned int bfd_canonicalize_reloc + long bfd_canonicalize_reloc (bfd *abfd, asection *sec, arelent **loc, @@ -406,14 +554,15 @@ DESCRIPTION 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 +long bfd_canonicalize_reloc (abfd, asect, location, symbols) bfd *abfd; sec_ptr asect; @@ -422,7 +571,7 @@ bfd_canonicalize_reloc (abfd, asect, location, symbols) { if (abfd->format != bfd_object) { bfd_set_error (bfd_error_invalid_operation); - return 0; + return -1; } return BFD_SEND (abfd, _bfd_canonicalize_reloc, (abfd, asect, location, symbols)); @@ -499,11 +648,11 @@ return true; } void -bfd_assert(file, line) -char *file; -int line; +bfd_assert (file, line) + const char *file; + int line; { - fprintf(stderr, "bfd assertion fail %s:%d\n",file,line); + (*_bfd_error_handler) ("bfd assertion fail %s:%d", file, line); } @@ -602,6 +751,9 @@ bfd_get_size (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; @@ -663,6 +815,39 @@ bfd_set_gp_size (abfd, i) elf_gp_size (abfd) = i; } +/* 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 @@ -694,7 +879,7 @@ bfd_scan_vma (string, end, base) /* Let the host do it if possible. */ if (sizeof(bfd_vma) <= sizeof(unsigned long)) - return (bfd_vma) strtoul (string, 0, base); + 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)) @@ -737,6 +922,69 @@ bfd_scan_vma (string, end, base) return value; } +/* +FUNCTION + bfd_copy_private_bfd_data + +SYNOPSIS + 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 <> on success, <> on error. + Possible error returns are: + + o <> - + Not enough memory exists to create private data for @var{obfd}. + +.#define bfd_copy_private_bfd_data(ibfd, obfd) \ +. BFD_SEND (ibfd, _bfd_copy_private_bfd_data, \ +. (ibfd, obfd)) + +*/ + +/* +FUNCTION + bfd_merge_private_bfd_data + +SYNOPSIS + 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 <> + on success, <> on error. Possible error returns are: + + o <> - + Not enough memory exists to create private data for @var{obfd}. + +.#define bfd_merge_private_bfd_data(ibfd, obfd) \ +. BFD_SEND (ibfd, _bfd_merge_private_bfd_data, \ +. (ibfd, obfd)) + +*/ + +/* +FUNCTION + bfd_set_private_flags + +SYNOPSIS + boolean bfd_set_private_flags(bfd *abfd, flagword flags); + +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 @@ -764,16 +1012,14 @@ DESCRIPTION .#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_get_relocated_section_contents(abfd, link_info, link_order, data, relocateable, symbols) \ -. BFD_SEND (abfd, _bfd_get_relocated_section_contents, \ -. (abfd, link_info, link_order, data, relocateable, symbols)) -. -.#define bfd_relax_section(abfd, section, link_info, symbols) \ -. BFD_SEND (abfd, _bfd_relax_section, \ -. (abfd, section, link_info, symbols)) +.#define bfd_relax_section(abfd, section, link_info, again) \ +. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) . .#define bfd_link_hash_table_create(abfd) \ . BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) @@ -784,5 +1030,103 @@ DESCRIPTION .#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) + + (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; +}