aboutsummaryrefslogtreecommitdiff
path: root/bfd/ecoff.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/ecoff.c')
-rw-r--r--bfd/ecoff.c758
1 files changed, 25 insertions, 733 deletions
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index f5461ae..8d67697 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) &section, buff);
- if (bfd_write (buff, 1, scnhsz, abfd) != scnhsz)
+ if (bfd_coff_swap_scnhdr_out (abfd, (PTR) &section, 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;
}