From 9675c281afc1e00a613f2820371043df844bff43 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 3 Jul 1995 22:16:40 +0000 Subject: [PATCH] * bfd.c (enum bfd_error): Define bfd_error_no_armap. (bfd_errmsgs): Add string for bfd_error_no_armap. * bfd-in2.h: Rebuild. * ecoff.c (ecoff_link_add_archive_symbols): If an archive has no armap, set bfd_error_no_armap rather than bfd_error_no_symbols. * elfcode.h (elf_link_add_archive_symbols): Likewise. * linker.c (_bfd_generic_link_add_archive_symbols): Likewise. --- bfd/bfd-in2.h | 4 +- bfd/bfd.c | 223 ++++++++++++++- bfd/ecoff.c | 758 ++------------------------------------------------ bfd/elfcode.h | 2 +- bfd/linker.c | 2 +- 5 files changed, 248 insertions(+), 741 deletions(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index cbe8e8ebf1..b197e424a8 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1919,6 +1919,7 @@ typedef enum bfd_error 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, @@ -2120,7 +2121,8 @@ enum bfd_flavour { bfd_target_srec_flavour, bfd_target_som_flavour, bfd_target_os9k_flavour, - bfd_target_versados_flavour + bfd_target_versados_flavour, + bfd_target_msdos_flavour }; /* Forward declaration. */ diff --git a/bfd/bfd.c b/bfd/bfd.c index b0d0a1d9ea..d58e971911 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -169,6 +169,7 @@ CODE_FRAGMENT . 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; . PTR any; . } tdata; . @@ -183,6 +184,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" @@ -192,6 +200,16 @@ CODE_FRAGMENT #undef obj_symbols #include "libelf.h" + +/* 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 */ + +enum bfd_link_subsystem NT_subsystem; + +bfd_link_stack_heap NT_stack_heap; /* SECTION @@ -224,6 +242,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, @@ -233,6 +252,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; . @@ -251,6 +271,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", @@ -260,6 +281,7 @@ CONST char *CONST bfd_errmsgs[] = { "Symbol needs debug section which does not exist", "Bad value", "File truncated", + "File too big", "#" }; @@ -356,6 +378,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 @@ -696,7 +838,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, end, 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)) @@ -760,6 +902,48 @@ DESCRIPTION */ +/* +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 @@ -793,10 +977,6 @@ DESCRIPTION .#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, again) \ . BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) . @@ -824,5 +1004,38 @@ DESCRIPTION .#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); +} diff --git a/bfd/ecoff.c b/bfd/ecoff.c index f5461aee0d..8d6769740a 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -123,6 +123,8 @@ _bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr) ecoff->fprmask = internal_a->fprmask; if (internal_a->magic == ECOFF_AOUT_ZMAGIC) abfd->flags |= D_PAGED; + else + abfd->flags &=~ D_PAGED; } /* It turns out that no special action is required by the MIPS or @@ -408,201 +410,6 @@ _bfd_ecoff_styp_to_sec_flags (abfd, hdr, name) return sec_flags; } -/* Routines to swap auxiliary information in and out. I am assuming - that the auxiliary information format is always going to be target - independent. */ - -/* Swap in a type information record. - BIGEND says whether AUX symbols are big-endian or little-endian; this - info comes from the file header record (fh-fBigendian). */ - -void -_bfd_ecoff_swap_tir_in (bigend, ext_copy, intern) - int bigend; - const struct tir_ext *ext_copy; - TIR *intern; -{ - struct tir_ext ext[1]; - - *ext = *ext_copy; /* Make it reasonable to do in-place. */ - - /* now the fun stuff... */ - if (bigend) { - intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_BIG); - intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_BIG); - intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_BIG) - >> TIR_BITS1_BT_SH_BIG; - intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_BIG) - >> TIR_BITS_TQ4_SH_BIG; - intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_BIG) - >> TIR_BITS_TQ5_SH_BIG; - intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_BIG) - >> TIR_BITS_TQ0_SH_BIG; - intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_BIG) - >> TIR_BITS_TQ1_SH_BIG; - intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_BIG) - >> TIR_BITS_TQ2_SH_BIG; - intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_BIG) - >> TIR_BITS_TQ3_SH_BIG; - } else { - intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_LITTLE); - intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_LITTLE); - intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_LITTLE) - >> TIR_BITS1_BT_SH_LITTLE; - intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_LITTLE) - >> TIR_BITS_TQ4_SH_LITTLE; - intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_LITTLE) - >> TIR_BITS_TQ5_SH_LITTLE; - intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_LITTLE) - >> TIR_BITS_TQ0_SH_LITTLE; - intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_LITTLE) - >> TIR_BITS_TQ1_SH_LITTLE; - intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_LITTLE) - >> TIR_BITS_TQ2_SH_LITTLE; - intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_LITTLE) - >> TIR_BITS_TQ3_SH_LITTLE; - } - -#ifdef TEST - if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) - abort(); -#endif -} - -/* Swap out a type information record. - BIGEND says whether AUX symbols are big-endian or little-endian; this - info comes from the file header record (fh-fBigendian). */ - -void -_bfd_ecoff_swap_tir_out (bigend, intern_copy, ext) - int bigend; - const TIR *intern_copy; - struct tir_ext *ext; -{ - TIR intern[1]; - - *intern = *intern_copy; /* Make it reasonable to do in-place. */ - - /* now the fun stuff... */ - if (bigend) { - ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_BIG : 0) - | (intern->continued ? TIR_BITS1_CONTINUED_BIG : 0) - | ((intern->bt << TIR_BITS1_BT_SH_BIG) - & TIR_BITS1_BT_BIG)); - ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_BIG) - & TIR_BITS_TQ4_BIG) - | ((intern->tq5 << TIR_BITS_TQ5_SH_BIG) - & TIR_BITS_TQ5_BIG)); - ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_BIG) - & TIR_BITS_TQ0_BIG) - | ((intern->tq1 << TIR_BITS_TQ1_SH_BIG) - & TIR_BITS_TQ1_BIG)); - ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_BIG) - & TIR_BITS_TQ2_BIG) - | ((intern->tq3 << TIR_BITS_TQ3_SH_BIG) - & TIR_BITS_TQ3_BIG)); - } else { - ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_LITTLE : 0) - | (intern->continued ? TIR_BITS1_CONTINUED_LITTLE : 0) - | ((intern->bt << TIR_BITS1_BT_SH_LITTLE) - & TIR_BITS1_BT_LITTLE)); - ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_LITTLE) - & TIR_BITS_TQ4_LITTLE) - | ((intern->tq5 << TIR_BITS_TQ5_SH_LITTLE) - & TIR_BITS_TQ5_LITTLE)); - ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_LITTLE) - & TIR_BITS_TQ0_LITTLE) - | ((intern->tq1 << TIR_BITS_TQ1_SH_LITTLE) - & TIR_BITS_TQ1_LITTLE)); - ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_LITTLE) - & TIR_BITS_TQ2_LITTLE) - | ((intern->tq3 << TIR_BITS_TQ3_SH_LITTLE) - & TIR_BITS_TQ3_LITTLE)); - } - -#ifdef TEST - if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) - abort(); -#endif -} - -/* Swap in a relative symbol record. BIGEND says whether it is in - big-endian or little-endian format.*/ - -void -_bfd_ecoff_swap_rndx_in (bigend, ext_copy, intern) - int bigend; - const struct rndx_ext *ext_copy; - RNDXR *intern; -{ - struct rndx_ext ext[1]; - - *ext = *ext_copy; /* Make it reasonable to do in-place. */ - - /* now the fun stuff... */ - if (bigend) { - intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_BIG) - | ((ext->r_bits[1] & RNDX_BITS1_RFD_BIG) - >> RNDX_BITS1_RFD_SH_BIG); - intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_BIG) - << RNDX_BITS1_INDEX_SH_LEFT_BIG) - | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_BIG) - | (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_BIG); - } else { - intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_LITTLE) - | ((ext->r_bits[1] & RNDX_BITS1_RFD_LITTLE) - << RNDX_BITS1_RFD_SH_LEFT_LITTLE); - intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_LITTLE) - >> RNDX_BITS1_INDEX_SH_LITTLE) - | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_LITTLE) - | ((unsigned int) ext->r_bits[3] - << RNDX_BITS3_INDEX_SH_LEFT_LITTLE); - } - -#ifdef TEST - if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) - abort(); -#endif -} - -/* Swap out a relative symbol record. BIGEND says whether it is in - big-endian or little-endian format.*/ - -void -_bfd_ecoff_swap_rndx_out (bigend, intern_copy, ext) - int bigend; - const RNDXR *intern_copy; - struct rndx_ext *ext; -{ - RNDXR intern[1]; - - *intern = *intern_copy; /* Make it reasonable to do in-place. */ - - /* now the fun stuff... */ - if (bigend) { - ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_BIG; - ext->r_bits[1] = (((intern->rfd << RNDX_BITS1_RFD_SH_BIG) - & RNDX_BITS1_RFD_BIG) - | ((intern->index >> RNDX_BITS1_INDEX_SH_LEFT_BIG) - & RNDX_BITS1_INDEX_BIG)); - ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_BIG; - ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_BIG; - } else { - ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_LITTLE; - ext->r_bits[1] = (((intern->rfd >> RNDX_BITS1_RFD_SH_LEFT_LITTLE) - & RNDX_BITS1_RFD_LITTLE) - | ((intern->index << RNDX_BITS1_INDEX_SH_LITTLE) - & RNDX_BITS1_INDEX_LITTLE)); - ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_LITTLE; - ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_LITTLE; - } - -#ifdef TEST - if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0) - abort(); -#endif -} - /* Read in the symbolic header for an ECOFF object file. */ static boolean @@ -2002,164 +1809,6 @@ _bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols) return section->reloc_count; } - -static int -cmp_fdrtab_entry (leftp, rightp) - const void *leftp, *rightp; -{ - const struct ecoff_fdrtab_entry *lp = leftp; - const struct ecoff_fdrtab_entry *rp = rightp; - - if (lp->base_addr < rp->base_addr) - return -1; - if (lp->base_addr > rp->base_addr) - return 1; - return 0; -} - -/* Each file descriptor (FDR) has a memory address, to simplify - looking up an FDR by address, we build a table covering all FDRs - that have a least one procedure descriptor in them. The final - table will be sorted by address so we can look it up via binary - search. */ -static boolean -mk_fdrtab (abfd) - bfd *abfd; -{ - struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info; - const struct ecoff_debug_swap * const debug_swap - = &ecoff_backend (abfd)->debug_swap; - struct ecoff_fdrtab_entry *tab; - FDR *fdr_ptr; - FDR *fdr_start; - FDR *fdr_end; - boolean stabs; - long len; - - /* Make sure we have the FDR's. */ - if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info) - || bfd_get_symcount (abfd) == 0) - return false; - - fdr_start = debug_info->fdr; - fdr_end = fdr_start + debug_info->symbolic_header.ifdMax; - - /* First, let's see how long the table needs to be: */ - for (len = 0, fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++) - { - if (fdr_ptr->cpd == 0) /* skip FDRs that have no PDRs */ - continue; - ++len; - } - - /* Now, create and fill in the table: */ - - ecoff_data (abfd)->fdrtab = (struct ecoff_fdrtab_entry*) - bfd_zalloc (abfd,len * sizeof (struct ecoff_fdrtab_entry)); - if (ecoff_data (abfd)->fdrtab == NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } - ecoff_data (abfd)->fdrtab_len = len; - - tab = ecoff_data (abfd)->fdrtab; - for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++) - { - if (fdr_ptr->cpd == 0) - continue; - - /* Check whether this file has stabs debugging information. In - a file with stabs debugging information, the second local - symbol is named @stabs. */ - stabs = false; - if (fdr_ptr->csym >= 2) - { - char *sym_ptr; - SYMR sym; - - sym_ptr = ((char *) debug_info->external_sym - + (fdr_ptr->isymBase + 1)*debug_swap->external_sym_size); - (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym); - if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss, - STABS_SYMBOL) == 0) - stabs = true; - } - - if (!stabs) - { - bfd_size_type external_pdr_size; - char *pdr_ptr; - PDR pdr; - - external_pdr_size = debug_swap->external_pdr_size; - - pdr_ptr = ((char *) debug_info->external_pdr - + fdr_ptr->ipdFirst * external_pdr_size); - (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); - /* The address of the first PDR is the offset of that - procedure relative to the beginning of file FDR. */ - tab->base_addr = fdr_ptr->adr - pdr.adr; - } - else - { - /* XXX I don't know about stabs, so this is a guess - (davidm@cs.arizona.edu): */ - tab->base_addr = fdr_ptr->adr; - } - tab->fdr = fdr_ptr; - ++tab; - } - /* Finally, the table is sorted in increasing memory-address order. - The table is mostly sorted already, but there are cases (e.g., - static functions in include files), where this does not hold. - Use "odump -PFv" to verify... */ - qsort((char*) ecoff_data (abfd)->fdrtab, len, - sizeof(struct ecoff_fdrtab_entry), cmp_fdrtab_entry); - - return true; -} - -/* Return index of first FDR that covers to OFFSET. */ -static long -lookup (abfd, offset) - bfd *abfd; - bfd_vma offset; -{ - long low, high, len; - long mid = -1; - struct ecoff_fdrtab_entry *tab; - - len = ecoff_data(abfd)->fdrtab_len; - if (!len) - return -1; - - tab = ecoff_data(abfd)->fdrtab; - for (low = 0, high = len - 1 ; low != high ;) - { - mid = (high + low) / 2; - if (offset >= tab[mid].base_addr && offset < tab[mid + 1].base_addr) - goto find_min; - - if (tab[mid].base_addr > offset) - high = mid; - else - low = mid + 1; - } - ++mid; - - /* last entry is catch-all for all higher addresses: */ - if (offset < tab[mid].base_addr) - return -1; - - find_min: - - while (mid > 0 && tab[mid - 1].base_addr == tab[mid].base_addr) - --mid; - - return mid; -} - /* Provided a BFD, a section and an offset into the section, calculate and return the name of the source file and the line nearest to the wanted location. */ @@ -2179,395 +1828,37 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset, const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (abfd)->debug_swap; struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info; - struct ecoff_fdrtab_entry *tab; - boolean stabs; - FDR *fdr_ptr; - int i; + struct ecoff_find_line *line_info; - offset += section->vma; /* If we're not in the .text section, we don't have any line numbers. */ if (strcmp (section->name, _TEXT) != 0 || offset < ecoff_data (abfd)->text_start || offset >= ecoff_data (abfd)->text_end) return false; - /* Build FDR table (sorted by object file's base-address) if we - don't have it already. */ - if (!ecoff_data (abfd)->fdrtab && !mk_fdrtab (abfd)) - return false; - tab = ecoff_data (abfd)->fdrtab; - - i = lookup(abfd, offset); /* find first FDR for address OFFSET */ - if (i < 0) - return false; /* no FDR, no fun... */ - fdr_ptr = tab[i].fdr; - - /* Check whether this file has stabs debugging information. In a - file with stabs debugging information, the second local symbol is - named @stabs. */ - stabs = false; - if (fdr_ptr->csym >= 2) - { - char *sym_ptr; - SYMR sym; - - sym_ptr = ((char *) debug_info->external_sym - + (fdr_ptr->isymBase + 1) * debug_swap->external_sym_size); - (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym); - if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss, - STABS_SYMBOL) == 0) - stabs = true; - } - if (!stabs) - { - bfd_size_type external_pdr_size; - char *pdr_ptr; - char *best_pdr = NULL; - FDR *best_fdr; - bfd_vma best_dist = ~0; - PDR pdr; - unsigned char *line_ptr; - unsigned char *line_end; - int lineno; - /* This file uses ECOFF debugging information. Each FDR has a - list of procedure descriptors (PDR). The address in the FDR - is the absolute address of the first procedure. The address - in the first PDR gives the offset of that procedure relative - to the object file's base-address. The addresses in - subsequent PDRs specify each procedure's address relative to - the object file's base-address. To make things more juicy, - whenever the PROF bit in the PDR is set, the real entry point - of the procedure may be 16 bytes below what would normally be - the procedure's entry point. Instead, DEC came up with a - wicked scheme to create profiled libraries "on the fly": - instead of shipping a regular and a profiled version of each - library, they insert 16 bytes of unused space in front of - each procedure and set the "prof" bit in the PDR to indicate - that there is a gap there (this is done automagically by "as" - when option "-pg" is specified). Thus, normally, you link - against such a library and, except for lots of 16 byte gaps - between functions, things will behave as usual. However, - when invoking "ld" with option "-pg", it will fill those gaps - with code that calls mcount(). It then moves the function's - entry point down by 16 bytes, and out pops a binary that has - all functions profiled. - - NOTE: Neither FDRs nor PDRs are strictly sorted in memory - order. For example, when including header-files that - define functions, the FDRs follow behind the including - file, even though their code may have been generated at - a lower address. File coff-alpha.c from libbfd - illustrates this (use "odump -PFv" to look at a file's - FDR/PDR). Similarly, PDRs are sometimes out of order - as well. An example of this is OSF/1 v3.0 libc's - malloc.c. I'm not sure why this happens, but it could - be due to optimizations that reorder a function's - position within an object-file. - - Strategy: - - On the first call to this function, we build a table of FDRs - that is sorted by the base-address of the object-file the FDR - is referring to. Notice that each object-file may contain - code from multiple source files (e.g., due to code defined in - include files). Thus, for any given base-address, there may - be multiple FDRs (but this case is, fortunately, uncommon). - lookup(addr) guarantees to return the first FDR that applies - to address ADDR. Thus, after invoking lookup(), we have a - list of FDRs that may contain the PDR for ADDR. Next, we - walk through the PDRs of these FDRs and locate the one that - is closest to ADDR (i.e., for which the difference between - ADDR and the PDR's entry point is positive and minimal). - Once, the right FDR and PDR are located, we simply walk - through the line-number table to lookup the line-number that - best matches ADDR. Obviously, things could be sped up by - keeping a sorted list of PDRs instead of a sorted list of - FDRs. However, this would increase space requirements - considerably, which is undesirable. */ - external_pdr_size = debug_swap->external_pdr_size; - - /* Make offset relative to object file's start-address: */ - offset -= tab[i].base_addr; - /* Search FDR list starting at tab[i] for the PDR that best matches - OFFSET. Normally, the FDR list is only one entry long. */ - best_fdr = NULL; - do - { - bfd_vma dist, min_dist = 0; - char *pdr_hold; - char *pdr_end; - - fdr_ptr = tab[i].fdr; - - pdr_ptr = ((char *) debug_info->external_pdr - + fdr_ptr->ipdFirst * external_pdr_size); - pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size; - (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); - /* Find PDR that is closest to OFFSET. If pdr.prof is set, - the procedure entry-point *may* be 0x10 below pdr.adr. We - simply pretend that pdr.prof *implies* a lower entry-point. - This is safe because it just means that may identify 4 NOPs - in front of the function as belonging to the function. */ - for (pdr_hold = NULL; - pdr_ptr < pdr_end; - (pdr_ptr += external_pdr_size, - (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr))) - { - if (offset >= (pdr.adr - 0x10 * pdr.prof)) - { - dist = offset - (pdr.adr - 0x10 * pdr.prof); - if (!pdr_hold || dist < min_dist) - { - min_dist = dist; - pdr_hold = pdr_ptr; - } - } - } - - if (!best_pdr || min_dist < best_dist) - { - best_dist = min_dist; - best_fdr = fdr_ptr; - best_pdr = pdr_hold; - } - /* continue looping until base_addr of next entry is different: */ - } - while (++i < ecoff_data (abfd)->fdrtab_len - && tab[i].base_addr == tab[i - 1].base_addr); - - if (!best_fdr || !best_pdr) - return false; /* shouldn't happen... */ - - /* phew, finally we got something that we can hold onto: */ - fdr_ptr = best_fdr; - pdr_ptr = best_pdr; - (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); - /* Now we can look for the actual line number. The line numbers - are stored in a very funky format, which I won't try to - describe. The search is bounded by the end of the FDRs line - number entries. */ - line_end = debug_info->line + fdr_ptr->cbLineOffset + fdr_ptr->cbLine; - - /* Make offset relative to procedure entry: */ - offset -= pdr.adr - 0x10 * pdr.prof; - lineno = pdr.lnLow; - line_ptr = debug_info->line + fdr_ptr->cbLineOffset + pdr.cbLineOffset; - while (line_ptr < line_end) - { - int delta; - int count; - - delta = *line_ptr >> 4; - if (delta >= 0x8) - delta -= 0x10; - count = (*line_ptr & 0xf) + 1; - ++line_ptr; - if (delta == -8) - { - delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff); - if (delta >= 0x8000) - delta -= 0x10000; - line_ptr += 2; - } - lineno += delta; - if (offset < count * 4) - break; - offset -= count * 4; - } + /* Make sure we have the FDR's. */ + if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info) + || bfd_get_symcount (abfd) == 0) + return false; - /* If fdr_ptr->rss is -1, then this file does not have full - symbols, at least according to gdb/mipsread.c. */ - if (fdr_ptr->rss == -1) - { - *filename_ptr = NULL; - if (pdr.isym == -1) - *functionname_ptr = NULL; - else - { - EXTR proc_ext; - - (*debug_swap->swap_ext_in) - (abfd, - ((char *) debug_info->external_ext - + pdr.isym * debug_swap->external_ext_size), - &proc_ext); - *functionname_ptr = debug_info->ssext + proc_ext.asym.iss; - } - } - else - { - SYMR proc_sym; - - *filename_ptr = debug_info->ss + fdr_ptr->issBase + fdr_ptr->rss; - (*debug_swap->swap_sym_in) - (abfd, - ((char *) debug_info->external_sym - + (fdr_ptr->isymBase + pdr.isym) * debug_swap->external_sym_size), - &proc_sym); - *functionname_ptr = debug_info->ss + fdr_ptr->issBase + proc_sym.iss; - } - if (lineno == ilineNil) - lineno = 0; - *retline_ptr = lineno; - } - else + if (ecoff_data (abfd)->find_line_info == NULL) { - bfd_size_type external_sym_size; - const char *directory_name; - const char *main_file_name; - const char *current_file_name; - const char *function_name; - const char *line_file_name; - bfd_vma low_func_vma; - bfd_vma low_line_vma; - char *sym_ptr, *sym_ptr_end; - size_t len, funclen; - char *buffer = NULL; - - /* This file uses stabs debugging information. */ - - *filename_ptr = NULL; - *functionname_ptr = NULL; - *retline_ptr = 0; - - directory_name = NULL; - main_file_name = NULL; - current_file_name = NULL; - function_name = NULL; - line_file_name = NULL; - low_func_vma = 0; - low_line_vma = 0; - - external_sym_size = debug_swap->external_sym_size; - - sym_ptr = ((char *) debug_info->external_sym - + (fdr_ptr->isymBase + 2) * external_sym_size); - sym_ptr_end = sym_ptr + fdr_ptr->csym * external_sym_size; - for (; sym_ptr < sym_ptr_end; sym_ptr += external_sym_size) - { - SYMR sym; - - (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym); - - if (ECOFF_IS_STAB (&sym)) - { - switch (ECOFF_UNMARK_STAB (sym.index)) - { - case N_SO: - main_file_name = current_file_name = - debug_info->ss + fdr_ptr->issBase + sym.iss; - - /* Check the next symbol to see if it is also an - N_SO symbol. */ - if (sym_ptr + external_sym_size < sym_ptr_end) - { - SYMR nextsym; - - (*debug_swap->swap_sym_in) (abfd, - sym_ptr + external_sym_size, - &nextsym); - if (ECOFF_IS_STAB (&nextsym) - && ECOFF_UNMARK_STAB (nextsym.index) == N_SO) - { - directory_name = current_file_name; - main_file_name = current_file_name = - debug_info->ss + fdr_ptr->issBase + sym.iss; - sym_ptr += external_sym_size; - } - } - break; - - case N_SOL: - current_file_name = - debug_info->ss + fdr_ptr->issBase + sym.iss; - break; - - case N_FUN: - if (sym.value >= low_func_vma - && sym.value <= offset + section->vma) - { - low_func_vma = sym.value; - function_name = - debug_info->ss + fdr_ptr->issBase + sym.iss; - } - break; - } - } - else if (sym.st == stLabel && sym.index != indexNil) - { - if (sym.value > offset + section->vma) - { - /* We have passed the location in the file we are - looking for, so we can get out of the loop. */ - break; - } - - if (sym.value >= low_line_vma) - { - low_line_vma = sym.value; - line_file_name = current_file_name; - *retline_ptr = sym.index; - } - } - } - - if (*retline_ptr != 0) - main_file_name = line_file_name; - - /* We need to remove the stuff after the colon in the function - name. We also need to put the directory name and the file - name together. */ - if (function_name == NULL) - len = funclen = 0; - else - len = funclen = strlen (function_name) + 1; - - if (main_file_name != NULL - && directory_name != NULL - && main_file_name[0] != '/') - len += strlen (directory_name) + strlen (main_file_name) + 1; - - if (len != 0) - { - if (ecoff_data (abfd)->find_buffer != NULL) - free (ecoff_data (abfd)->find_buffer); - buffer = (char *) malloc (len); - if (buffer == NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } - ecoff_data (abfd)->find_buffer = buffer; - } - - if (function_name != NULL) + ecoff_data (abfd)->find_line_info = + ((struct ecoff_find_line *) + bfd_alloc (abfd, sizeof (struct ecoff_find_line))); + if (ecoff_data (abfd)->find_line_info == NULL) { - char *colon; - - strcpy (buffer, function_name); - colon = strchr (buffer, ':'); - if (colon != NULL) - *colon = '\0'; - *functionname_ptr = buffer; - } - - if (main_file_name != NULL) - { - if (directory_name == NULL || main_file_name[0] == '/') - *filename_ptr = main_file_name; - else - { - sprintf (buffer + funclen, "%s%s", directory_name, - main_file_name); - *filename_ptr = buffer + funclen; - } + bfd_set_error (bfd_error_no_memory); + return false; } } + line_info = ecoff_data (abfd)->find_line_info; - return true; + return _bfd_ecoff_locate_line (abfd, section, offset, debug_info, + debug_swap, line_info, filename_ptr, + functionname_ptr, retline_ptr); } - /* Copy private BFD data. This is called by objcopy and strip. We use it to copy the ECOFF debugging information from one BFD to the @@ -3194,8 +2485,8 @@ _bfd_ecoff_write_object_contents (abfd) section.s_flags = ecoff_sec_to_styp_flags (current->name, current->flags); - bfd_coff_swap_scnhdr_out (abfd, (PTR) §ion, buff); - if (bfd_write (buff, 1, scnhsz, abfd) != scnhsz) + if (bfd_coff_swap_scnhdr_out (abfd, (PTR) §ion, buff) == 0 + || bfd_write (buff, 1, scnhsz, abfd) != scnhsz) goto error_return; if ((section.s_flags & STYP_TEXT) != 0 @@ -4087,7 +3378,7 @@ ecoff_link_add_archive_symbols (abfd, info) /* An empty archive is a special case. */ if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL) return true; - bfd_set_error (bfd_error_no_symbols); + bfd_set_error (bfd_error_no_armap); return false; } @@ -4605,10 +3896,11 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext) on Ultrix 4.2 to handle the symbol cred in -lckrb. */ if (h->small && h->root.type == bfd_link_hash_common - && strcmp (h->root.u.c.section->name, SCOMMON) != 0) + && strcmp (h->root.u.c.p->section->name, SCOMMON) != 0) { - h->root.u.c.section = bfd_make_section_old_way (abfd, SCOMMON); - h->root.u.c.section->flags = SEC_ALLOC; + h->root.u.c.p->section = bfd_make_section_old_way (abfd, + SCOMMON); + h->root.u.c.p->section->flags = SEC_ALLOC; if (h->esym.asym.sc == scCommon) h->esym.asym.sc = scSCommon; } diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 4c73825f52..2ce8bed4ed 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -4035,7 +4035,7 @@ elf_link_add_archive_symbols (abfd, info) /* An empty archive is a special case. */ if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL) return true; - bfd_set_error (bfd_error_no_symbols); + bfd_set_error (bfd_error_no_armap); return false; } diff --git a/bfd/linker.c b/bfd/linker.c index 0d7e47a1ff..4ce41e9799 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -867,7 +867,7 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn) /* An empty archive is a special case. */ if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL) return true; - bfd_set_error (bfd_error_no_symbols); + bfd_set_error (bfd_error_no_armap); return false; } -- 2.34.1