aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog3
-rw-r--r--bfd/ecoff.c422
2 files changed, 307 insertions, 118 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 3bf91b1..52ad1c4 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -7,6 +7,9 @@ Wed Oct 12 16:46:43 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
Wed Oct 12 11:54:37 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+ * ecoff.c (ecoff_set_symbol_info): Mark local stProc or stLabel
+ symbols as BSF_DEBUGGING.
+
* rs6000-core.c (rs6000coff_core_file_matches_executable_p): Make
str1 and str2 const pointers.
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index a2ed76d..a157b2a 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -25,6 +25,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "libbfd.h"
#include "aout/ar.h"
#include "aout/ranlib.h"
+#include "aout/stab_gnu.h"
/* FIXME: We need the definitions of N_SET[ADTB], but aout64.h defines
some other stuff which we don't want and which conflicts with stuff
@@ -152,14 +153,17 @@ _bfd_ecoff_new_section_hook (abfd, section)
asection *section;
{
/* For the .pdata section, which has a special meaning on the Alpha,
- we set the alignment to 8. We correct this later in
+ we set the alignment power to 3. We correct this later in
ecoff_compute_section_file_positions. We do this hackery because
we need to know the exact unaligned size of the .pdata section in
- order to set the lnnoptr field correctly. */
+ order to set the lnnoptr field correctly. For every other
+ section we use an alignment power of 4; this could be made target
+ dependent by adding a field to ecoff_backend_data, but 4 appears
+ to be correct for both the MIPS and the Alpha. */
if (strcmp (section->name, _PDATA) == 0)
section->alignment_power = 3;
else
- section->alignment_power = abfd->xvec->align_power_min;
+ section->alignment_power = 4;
if (strcmp (section->name, _TEXT) == 0)
section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
@@ -340,9 +344,10 @@ ecoff_sec_to_styp_flags (name, flags)
/*ARGSUSED*/
flagword
-_bfd_ecoff_styp_to_sec_flags (abfd, hdr)
+_bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
bfd *abfd;
PTR hdr;
+ const char *name;
{
struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
long styp_flags = internal_s->s_flags;
@@ -871,7 +876,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
(*indirect_ptr_ptr)->value = (bfd_vma) asym;
asym->flags = BSF_DEBUGGING;
- asym->section = &bfd_und_section;
+ asym->section = bfd_und_section_ptr;
*indirect_ptr_ptr = NULL;
return true;
}
@@ -880,7 +885,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
&& (ECOFF_UNMARK_STAB (ecoff_sym->index) | N_EXT) == (N_INDR | N_EXT))
{
asym->flags = BSF_DEBUGGING | BSF_INDIRECT;
- asym->section = &bfd_ind_section;
+ asym->section = bfd_ind_section_ptr;
/* Pass this symbol on to the next call to this function. */
*indirect_ptr_ptr = asym;
return true;
@@ -910,7 +915,18 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
if (ext)
asym->flags = BSF_EXPORT | BSF_GLOBAL;
else
- asym->flags = BSF_LOCAL;
+ {
+ asym->flags = BSF_LOCAL;
+ /* Normally, a local stProc symbol will have a corresponding
+ external symbol. We mark the local symbol as a debugging
+ symbol, in order to prevent nm from printing both out.
+ Similarly, we mark stLabel fields as debugging symbols. In
+ both cases, we do want to set the value correctly based on
+ the symbol class. */
+ if (ecoff_sym->st == stProc
+ || ecoff_sym->st == stLabel)
+ asym->flags |= BSF_DEBUGGING;
+ }
switch (ecoff_sym->sc)
{
case scNil:
@@ -936,10 +952,10 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
asym->flags = BSF_DEBUGGING;
break;
case scAbs:
- asym->section = &bfd_abs_section;
+ asym->section = bfd_abs_section_ptr;
break;
case scUndefined:
- asym->section = &bfd_und_section;
+ asym->section = bfd_und_section_ptr;
asym->flags = 0;
asym->value = 0;
break;
@@ -969,7 +985,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
case scCommon:
if (asym->value > ecoff_data (abfd)->gp_size)
{
- asym->section = &bfd_com_section;
+ asym->section = bfd_com_section_ptr;
asym->flags = 0;
break;
}
@@ -996,7 +1012,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
asym->flags = BSF_DEBUGGING;
break;
case scSUndefined:
- asym->section = &bfd_und_section;
+ asym->section = bfd_und_section_ptr;
asym->flags = 0;
asym->value = 0;
break;
@@ -1895,7 +1911,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols)
else if (intern.r_symndx == RELOC_SECTION_NONE
|| intern.r_symndx == RELOC_SECTION_ABS)
{
- rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+ rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
rptr->addend = 0;
}
else
@@ -2003,18 +2019,12 @@ _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;
FDR *fdr_ptr;
FDR *fdr_start;
FDR *fdr_end;
FDR *fdr_hold;
- bfd_size_type external_pdr_size;
- char *pdr_ptr;
- char *pdr_end;
- PDR pdr;
- bfd_vma first_off;
- unsigned char *line_ptr;
- unsigned char *line_end;
- int lineno;
+ boolean stabs;
/* If we're not in the .text section, we don't have any line
numbers. */
@@ -2024,8 +2034,7 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
return false;
/* Make sure we have the FDR's. */
- if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL,
- &ecoff_data (abfd)->debug_info)
+ if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info)
|| bfd_get_symcount (abfd) == 0)
return false;
@@ -2034,8 +2043,8 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
memory order. If speed is ever important, this can become a
binary search. We must ignore FDR's with no PDR entries; they
will have the adr of the FDR before or after them. */
- fdr_start = ecoff_data (abfd)->debug_info.fdr;
- fdr_end = fdr_start + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax;
+ fdr_start = debug_info->fdr;
+ fdr_end = fdr_start + debug_info->symbolic_header.ifdMax;
fdr_hold = (FDR *) NULL;
for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
{
@@ -2049,112 +2058,289 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
return false;
fdr_ptr = fdr_hold;
- /* Each FDR has a list of procedure descriptors (PDR). PDR's also
- have an address, which is relative to the FDR address, and are
- also stored in increasing memory order. */
- offset -= fdr_ptr->adr;
- external_pdr_size = debug_swap->external_pdr_size;
- pdr_ptr = ((char *) ecoff_data (abfd)->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);
- if (offset < pdr.adr)
- return false;
+ /* 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;
- /* The address of the first PDR is an offset which applies to the
- addresses of all the PDR's. */
- first_off = pdr.adr;
+ 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;
+ }
- for (pdr_ptr += external_pdr_size;
- pdr_ptr < pdr_end;
- pdr_ptr += external_pdr_size)
+ if (! stabs)
{
+ bfd_size_type external_pdr_size;
+ char *pdr_ptr;
+ char *pdr_end;
+ PDR pdr;
+ bfd_vma first_off;
+ 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). PDR's also have an
+ address, which is relative to the FDR address, and are also
+ stored in increasing memory order. */
+ offset -= fdr_ptr->adr;
+ external_pdr_size = debug_swap->external_pdr_size;
+ 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);
if (offset < pdr.adr)
- break;
- }
+ return false;
- /* 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.
- Note that right here pdr_ptr and pdr hold the PDR *after* the one
- we want; we need this to compute line_end. */
- line_end = ecoff_data (abfd)->debug_info.line;
- if (pdr_ptr == pdr_end)
- line_end += fdr_ptr->cbLineOffset + fdr_ptr->cbLine;
- else
- line_end += fdr_ptr->cbLineOffset + pdr.cbLineOffset;
-
- /* Now change pdr and pdr_ptr to the one we want. */
- pdr_ptr -= external_pdr_size;
- (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
-
- offset -= pdr.adr - first_off;
- lineno = pdr.lnLow;
- line_ptr = (ecoff_data (abfd)->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)
+ /* The address of the first PDR is an offset which applies to
+ the addresses of all the PDR's. */
+ first_off = pdr.adr;
+
+ for (pdr_ptr += external_pdr_size;
+ pdr_ptr < pdr_end;
+ pdr_ptr += external_pdr_size)
{
- delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff);
- if (delta >= 0x8000)
- delta -= 0x10000;
- line_ptr += 2;
+ (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
+ if (offset < pdr.adr)
+ break;
}
- lineno += delta;
- if (offset < count * 4)
- break;
- offset -= count * 4;
- }
- /* 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;
+ /* 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. Note that right here pdr_ptr and pdr hold the PDR
+ *after* the one we want; we need this to compute line_end. */
+ line_end = debug_info->line;
+ if (pdr_ptr == pdr_end)
+ line_end += fdr_ptr->cbLineOffset + fdr_ptr->cbLine;
+ else
+ line_end += fdr_ptr->cbLineOffset + pdr.cbLineOffset;
+
+ /* Now change pdr and pdr_ptr to the one we want. */
+ pdr_ptr -= external_pdr_size;
+ (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
+
+ offset -= pdr.adr - first_off;
+ 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;
+ }
+
+ /* 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
{
- EXTR proc_ext;
+ SYMR proc_sym;
- (*debug_swap->swap_ext_in)
+ *filename_ptr = debug_info->ss + fdr_ptr->issBase + fdr_ptr->rss;
+ (*debug_swap->swap_sym_in)
(abfd,
- ((char *) ecoff_data (abfd)->debug_info.external_ext
- + pdr.isym * debug_swap->external_ext_size),
- &proc_ext);
- *functionname_ptr = (ecoff_data (abfd)->debug_info.ssext
- + proc_ext.asym.iss);
+ ((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
{
- SYMR proc_sym;
-
- *filename_ptr = (ecoff_data (abfd)->debug_info.ss
- + fdr_ptr->issBase
- + fdr_ptr->rss);
- (*debug_swap->swap_sym_in)
- (abfd,
- ((char *) ecoff_data (abfd)->debug_info.external_sym
- + (fdr_ptr->isymBase + pdr.isym) * debug_swap->external_sym_size),
- &proc_sym);
- *functionname_ptr = (ecoff_data (abfd)->debug_info.ss
- + fdr_ptr->issBase
- + proc_sym.iss);
+ 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)
+ {
+ 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;
+ }
+ }
}
- if (lineno == ilineNil)
- lineno = 0;
- *retline_ptr = lineno;
+
return true;
}
@@ -2617,7 +2803,7 @@ ecoff_get_extr (sym, esym)
symbol. */
if ((esym->asym.sc == scUndefined
|| esym->asym.sc == scSUndefined)
- && bfd_get_section (sym) != &bfd_und_section)
+ && ! bfd_is_und_section (bfd_get_section (sym)))
esym->asym.sc = scAbs;
/* Adjust the FDR index for the symbol by that used for the input
@@ -4099,10 +4285,10 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
value -= section->vma;
break;
case scAbs:
- section = &bfd_abs_section;
+ section = bfd_abs_section_ptr;
break;
case scUndefined:
- section = &bfd_und_section;
+ section = bfd_und_section_ptr;
break;
case scSData:
section = bfd_make_section_old_way (abfd, ".sdata");
@@ -4119,7 +4305,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
case scCommon:
if (value > ecoff_data (abfd)->gp_size)
{
- section = &bfd_com_section;
+ section = bfd_com_section_ptr;
break;
}
/* Fall through. */
@@ -4140,7 +4326,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
section = &ecoff_scom_section;
break;
case scSUndefined:
- section = &bfd_und_section;
+ section = bfd_und_section_ptr;
break;
case scInit:
section = bfd_make_section_old_way (abfd, ".init");
@@ -4171,7 +4357,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
if (info->hash->creator->flavour == bfd_get_flavour (abfd))
{
if (h->abfd == (bfd *) NULL
- || (section != &bfd_und_section
+ || (! bfd_is_und_section (section)
&& (! bfd_is_com_section (section)
|| h->root.type != bfd_link_hash_defined)))
{