diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/coff-mips.c | 246 |
1 files changed, 151 insertions, 95 deletions
diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c index 210a493..85a9056 100644 --- a/bfd/coff-mips.c +++ b/bfd/coff-mips.c @@ -191,7 +191,7 @@ DEFUN (ecoff_new_section_hook, (abfd, section), section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY; else if (strcmp (section->name, _BSS) == 0 || strcmp (section->name, _SBSS) == 0) - section->flags |= SEC_ALLOC | SEC_IS_COMMON; + section->flags |= SEC_ALLOC; /* Probably any other section name is SEC_NEVER_LOAD, but I'm uncertain about .init on some systems and I don't know how shared @@ -518,6 +518,15 @@ DEFUN (ecoff_slurp_symbolic_info, (abfd), /* ECOFF symbol table routines. The ECOFF symbol table is described in gcc/mips-tfile.c. */ +/* ECOFF uses two common sections. One is the usual one, and the + other is for small objects. All the small objects are kept + together, and then referenced via the gp pointer, which yields + faster assembler code. This is what we use for the small common + section. */ +static asection ecoff_scom_section; +static asymbol ecoff_scom_symbol; +static asymbol *ecoff_scom_symbol_ptr; + /* Create an empty symbol. */ static asymbol * @@ -618,7 +627,8 @@ DEFUN (ecoff_set_symbol_info, (abfd, ecoff_sym, asym, ext), break; case scSBss: asym->section = bfd_make_section_old_way (abfd, ".sbss"); - asym->value -= asym->section->vma; + if (! ext) + asym->value -= asym->section->vma; break; case scRData: asym->section = bfd_make_section_old_way (abfd, ".rdata"); @@ -631,8 +641,20 @@ DEFUN (ecoff_set_symbol_info, (abfd, ecoff_sym, asym, ext), asym->section = &bfd_com_section; break; case scSCommon: - asym->section = bfd_make_section_old_way (abfd, ".sbss"); - asym->value -= asym->section->vma; + if (ecoff_scom_section.name == NULL) + { + /* Initialize the small common section. */ + ecoff_scom_section.name = "*SCOM*"; + ecoff_scom_section.flags = SEC_IS_COMMON; + ecoff_scom_section.output_section = &ecoff_scom_section; + ecoff_scom_section.symbol = &ecoff_scom_symbol; + ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr; + ecoff_scom_symbol.name = "*SCOM*"; + ecoff_scom_symbol.flags = BSF_SECTION_SYM; + ecoff_scom_symbol.section = &ecoff_scom_section; + ecoff_scom_symbol_ptr = &ecoff_scom_symbol; + } + asym->section = &ecoff_scom_section; break; case scVarRegister: case scVariant: @@ -1368,23 +1390,57 @@ DEFUN (ecoff_swap_reloc_out, (abfd, src, dst), return RELSZ; } +/* ECOFF relocs are either against external symbols, or against + sections. If we are producing relocateable output, and the reloc + is against an external symbol, the resulting reloc will also be + against the same symbol. In such a case, we don't want to change + anything about the way the reloc is handled, since it will all be + done at final link time. Rather than put special case code into + bfd_perform_relocation, all the reloc types use this howto + function. It just short circuits the reloc if producing + relocateable output against an external symbol. */ + +static bfd_reloc_status_type +ecoff_generic_reloc (abfd, + reloc_entry, + symbol, + data, + input_section, + output_bfd) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol; + PTR data; + asection *input_section; + bfd *output_bfd; +{ + if (output_bfd != (bfd *) NULL + && (symbol->flags & BSF_SECTION_SYM) == 0) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + return bfd_reloc_continue; +} + /* Do a REFHI relocation. The next reloc must be the corresponding REFLO. This has to be done in a function so that carry is handled correctly. */ static bfd_reloc_status_type -DEFUN (ecoff_refhi_reloc, (abfd, - reloc_entry, - symbol, - data, - input_section, - output_bfd), - bfd *abfd AND - arelent *reloc_entry AND - asymbol *symbol AND - PTR data AND - asection *input_section AND - bfd *output_bfd) +ecoff_refhi_reloc (abfd, + reloc_entry, + symbol, + data, + input_section, + output_bfd) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol; + PTR data; + asection *input_section; + bfd *output_bfd; { bfd_reloc_status_type ret; arelent *rello; @@ -1393,6 +1449,15 @@ DEFUN (ecoff_refhi_reloc, (abfd, unsigned long val; unsigned long vallo; + /* If we're relocating, and this an external symbol, we don't want + to change anything. */ + if (output_bfd != (bfd *) NULL + && (symbol->flags & BSF_SECTION_SYM) == 0) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + ret = bfd_reloc_ok; if (symbol->section == &bfd_und_section && output_bfd == (bfd *) NULL) @@ -1407,12 +1472,8 @@ DEFUN (ecoff_refhi_reloc, (abfd, else relocation = symbol->value; - if (output_bfd == (bfd *) NULL) - { - relocation += symbol->section->output_section->vma; - relocation += symbol->section->output_offset; - } - + relocation += symbol->section->output_section->vma; + relocation += symbol->section->output_offset; relocation += reloc_entry->addend; if (reloc_entry->address > input_section->_cooked_size) @@ -1446,24 +1507,33 @@ DEFUN (ecoff_refhi_reloc, (abfd, the offset from the gp register. */ static bfd_reloc_status_type -DEFUN (ecoff_gprel_reloc, (abfd, - reloc_entry, - symbol, - data, - input_section, - output_bfd), - bfd *abfd AND - arelent *reloc_entry AND - asymbol *symbol AND - PTR data AND - asection *input_section AND - bfd *output_bfd) +ecoff_gprel_reloc (abfd, + reloc_entry, + symbol, + data, + input_section, + output_bfd) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol; + PTR data; + asection *input_section; + bfd *output_bfd; { boolean relocateable; bfd_vma relocation; unsigned long val; unsigned long insn; + /* If we're relocating, and this an external symbol, we don't want + to change anything. */ + if (output_bfd != (bfd *) NULL + && (symbol->flags & BSF_SECTION_SYM) == 0) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + if (output_bfd != (bfd *) NULL) relocateable = true; else @@ -1482,7 +1552,7 @@ DEFUN (ecoff_gprel_reloc, (abfd, target data. */ if (ecoff_data (output_bfd)->gp == 0) { - if (relocateable) + if (relocateable != false) { /* Make up a value. */ ecoff_data (output_bfd)->gp = @@ -1547,7 +1617,7 @@ DEFUN (ecoff_gprel_reloc, (abfd, insn = (insn &~ 0xffff) | (val & 0xffff); bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address); - if (relocateable) + if (relocateable != false) reloc_entry->address += input_section->output_offset; /* Make sure it fit in 16 bits. */ @@ -1588,7 +1658,7 @@ static reloc_howto_type ecoff_howto_table[] = 0, /* bitpos */ false, /* absolute (obsolete) */ true, /* complain_on_overflow */ - 0, /* special_function */ + ecoff_generic_reloc, /* special_function */ "REFHALF", /* name */ true, /* partial_inplace */ 0xffff, /* src_mask */ @@ -1604,7 +1674,7 @@ static reloc_howto_type ecoff_howto_table[] = 0, /* bitpos */ false, /* absolute (obsolete) */ true, /* complain_on_overflow */ - 0, /* special_function */ + ecoff_generic_reloc, /* special_function */ "REFWORD", /* name */ true, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -1620,7 +1690,7 @@ static reloc_howto_type ecoff_howto_table[] = 0, /* bitpos */ false, /* absolute (obsolete) */ true, /* complain_on_overflow */ - 0, /* special_function */ + ecoff_generic_reloc, /* special_function */ "JMPADDR", /* name */ true, /* partial_inplace */ 0x3ffffff, /* src_mask */ @@ -1653,7 +1723,7 @@ static reloc_howto_type ecoff_howto_table[] = 0, /* bitpos */ false, /* absolute (obsolete) */ true, /* complain_on_overflow */ - 0, /* special_function */ + ecoff_generic_reloc, /* special_function */ "REFLO", /* name */ true, /* partial_inplace */ 0xffff, /* src_mask */ @@ -1823,7 +1893,7 @@ DEFUN (ecoff_canonicalize_reloc, (abfd, section, relptr, symbols), count++, chain = chain->next) *relptr++ = &chain->relent; } - else + else { arelent *tblptr; @@ -1873,7 +1943,6 @@ DEFUN (ecoff_find_nearest_line, (abfd, unsigned char *line_ptr; unsigned char *line_end; int lineno; - SYMR proc_sym; /* If we're not in the .text section, we don't have any line numbers. */ @@ -1966,13 +2035,38 @@ DEFUN (ecoff_find_nearest_line, (abfd, if (offset > 100) return false; - *filename_ptr = ecoff_data (abfd)->ss + fdr_ptr->issBase + fdr_ptr->rss; - ecoff_swap_sym_in (abfd, - (ecoff_data (abfd)->external_sym - + fdr_ptr->isymBase - + pdr.isym), - &proc_sym); - *functionname_ptr = ecoff_data (abfd)->ss + proc_sym.iss; + /* 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; + + ecoff_swap_ext_in (abfd, + (ecoff_data (abfd)->external_ext + + pdr.isym), + &proc_ext); + *functionname_ptr = ecoff_data (abfd)->ssext + proc_ext.asym.iss; + } + } + else + { + SYMR proc_sym; + + *filename_ptr = ecoff_data (abfd)->ss + fdr_ptr->issBase + fdr_ptr->rss; + ecoff_swap_sym_in (abfd, + (ecoff_data (abfd)->external_sym + + fdr_ptr->isymBase + + pdr.isym), + &proc_sym); + *functionname_ptr = (ecoff_data (abfd)->ss + + fdr_ptr->issBase + + proc_sym.iss); + } *retline_ptr = lineno; return true; } @@ -2235,14 +2329,6 @@ DEFUN (ecoff_get_debug, (output_bfd, seclet, section), FDR *fdr_ptr; FDR *fdr_end; struct fdr_ext *fdr_out; - long iss; - long isym; - long iline; - long iopt; - long ipdr; - long iaux; - long irfd; - long cbline; input_bfd = seclet->u.indirect.section->owner; @@ -2443,17 +2529,6 @@ DEFUN (ecoff_get_debug, (output_bfd, seclet, section), ifd values. */ input_ecoff->ifdbase = output_symhdr->ifdMax; - /* Step through the FDR's of input_bfd, adjust the offsets, and - swap them out. */ - iss = output_symhdr->issMax; - isym = output_symhdr->isymMax; - iline = output_symhdr->ilineMax; - iopt = output_symhdr->ioptMax; - ipdr = output_symhdr->ipdMax; - iaux = output_symhdr->iauxMax; - irfd = output_symhdr->crfd; - cbline = output_symhdr->cbLine; - fdr_ptr = input_ecoff->fdr; fdr_end = fdr_ptr + input_symhdr->ifdMax; fdr_out = output_ecoff->external_fdr + output_symhdr->ifdMax; @@ -2469,20 +2544,13 @@ DEFUN (ecoff_get_debug, (output_bfd, seclet, section), + seclet->offset + (fdr_ptr->adr - input_ecoff->fdr->adr)); - fdr.issBase = iss; - iss += fdr.cbSs; - fdr.isymBase = isym; - isym += fdr.csym; - fdr.ilineBase = iline; - iline += fdr.cline; - fdr.ioptBase = iopt; - iopt += fdr.copt; - fdr.ipdFirst = ipdr; - ipdr += fdr.cpd; - fdr.iauxBase = iaux; - iaux += fdr.caux; - fdr.rfdBase = irfd; - irfd += fdr.crfd; + fdr.issBase += output_symhdr->issMax; + fdr.isymBase += output_symhdr->isymMax; + fdr.ilineBase += output_symhdr->ilineMax; + fdr.ioptBase += output_symhdr->ioptMax; + fdr.ipdFirst += output_symhdr->ipdMax; + fdr.iauxBase += output_symhdr->iauxMax; + fdr.rfdBase += output_symhdr->crfd; /* If there are no RFD's, we are going to add some. We don't want to adjust irfd for this, so that all the FDR's can share @@ -2491,10 +2559,7 @@ DEFUN (ecoff_get_debug, (output_bfd, seclet, section), fdr.crfd = input_symhdr->ifdMax; if (fdr.cbLine != 0) - { - fdr.cbLineOffset = cbline; - cbline += fdr.cbLine; - } + fdr.cbLineOffset += output_symhdr->cbLine; ecoff_swap_fdr_out (output_bfd, &fdr, fdr_out); } @@ -2562,15 +2627,6 @@ DEFUN (ecoff_get_debug, (output_bfd, seclet, section), output_symhdr->issMax += input_symhdr->issMax; output_symhdr->ifdMax += input_symhdr->ifdMax; - /* Double check that the counts we got by stepping through the FDR's - match the counts we got from input_symhdr. We don't check iss or - cbline because they are rounded. */ - BFD_ASSERT (output_symhdr->isymMax == isym - && output_symhdr->ilineMax == iline - && output_symhdr->ioptMax == iopt - && output_symhdr->ipdMax == ipdr - && output_symhdr->iauxMax == iaux); - return true; } |