diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3bf91b1220..52ad1c4ad3 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -7,6 +7,9 @@ Wed Oct 12 16:46:43 1994 Ken Raeburn Wed Oct 12 11:54:37 1994 Ian Lance Taylor + * 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 a2ed76d0b5..a157b2a8d0 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; - - /* 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) + /* 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 *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; + /* The address of the first PDR is an offset which applies to + the addresses of all the PDR's. */ + first_off = pdr.adr; - /* 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) + 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; + 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; - *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); + /* 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))) {