Checkpoint. Linker appears to work.
authorIan Lance Taylor <ian@airs.com>
Wed, 27 Jan 1993 19:33:48 +0000 (19:33 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 27 Jan 1993 19:33:48 +0000 (19:33 +0000)
bfd/coff-mips.c

index 210a493..85a9056 100644 (file)
@@ -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;
 }