* coff-mips.c (ecoff_set_symbol_info): stBlock symbols are always
[platform/upstream/binutils.git] / bfd / coff-mips.c
index 95dba88..c5b3946 100644 (file)
@@ -31,61 +31,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "coff/symconst.h"
 #include "coff/ecoff-ext.h"
 #include "libcoff.h"
-
-/* `Tdata' information kept for ECOFF files.  */
-
-#define ecoff_data(abfd) ((abfd)->tdata.ecoff_obj_data)
-
-typedef struct ecoff_tdata
-{
-  /* The reloc file position, set by
-     ecoff_compute_section_file_positions.  */
-  file_ptr reloc_filepos;
-
-  /* The symbol table file position, set by ecoff_mkobject_hook.  */
-  file_ptr sym_filepos;
-
-  /* The cached gp value.  This is used when relocating.  */
-  bfd_vma gp;
-
-  /* The register masks.  When linking, all the masks found in the
-     input files are combined into the masks of the output file.  */
-  unsigned long gprmask;
-  unsigned long cprmask[4];
-
-  /* The size of the unswapped ECOFF symbolic information.  */
-  bfd_size_type raw_size;
-
-  /* The unswapped ECOFF symbolic information.  */
-  PTR raw_syments;
-
-  /* The swapped ECOFF symbolic header.  */
-  HDRR symbolic_header;
-
-  /* Pointers to the unswapped symbolic information.  */
-  unsigned char *line;
-  struct dnr_ext *external_dnr;
-  struct pdr_ext *external_pdr;
-  struct sym_ext *external_sym;
-  struct opt_ext *external_opt;
-  union aux_ext *external_aux;
-  char *ss;
-  char *ssext;
-  struct fdr_ext *external_fdr;
-  struct rfd_ext *external_rfd;
-  struct ext_ext *external_ext;
-
-  /* The swapped FDR information.  */
-  FDR *fdr;
-
-  /* The FDR index.  This is set for an input BFD to a link so that
-     the external symbols can set their FDR index correctly.  */
-  unsigned int ifdbase;
-
-  /* The canonical BFD symbols.  */
-  struct ecoff_symbol_struct *canonical_symbols;
-
-} ecoff_data_type;
+#include "libecoff.h"
 
 /* Each canonical asymbol really looks like this.  */
 
@@ -145,7 +91,6 @@ static boolean ecoff_set_arch_mach_hook PARAMS ((bfd *abfd, PTR filehdr));
 static long ecoff_sec_to_styp_flags PARAMS ((CONST char *name,
                                             flagword flags));
 static flagword ecoff_styp_to_sec_flags PARAMS ((bfd *abfd, PTR hdr));
-static boolean ecoff_slurp_symbolic_info PARAMS ((bfd *abfd));
 static asymbol *ecoff_make_empty_symbol PARAMS ((bfd *abfd));
 static void ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym,
                                           asymbol *asym, int ext));
@@ -353,6 +298,8 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr)
     {
       int i;
 
+      ecoff->text_start = internal_a->text_start;
+      ecoff->text_end = internal_a->text_start + internal_a->tsize;
       ecoff->gp = internal_a->gp_value;
       ecoff->gprmask = internal_a->gprmask;
       for (i = 0; i < 4; i++)
@@ -375,8 +322,8 @@ ecoff_set_arch_mach_hook (abfd, filehdr)
   switch (internal_f->f_magic)
     {
     case MIPS_MAGIC_1:
-    case MIPS_MAGIC_2:
-    case MIPS_MAGIC_3:
+    case MIPS_MAGIC_LITTLE:
+    case MIPS_MAGIC_BIG:
       arch = bfd_arch_mips;
       break;
 
@@ -491,9 +438,11 @@ ecoff_styp_to_sec_flags (abfd, hdr)
 }
 \f
 /* Read in and swap the important symbolic information for an ECOFF
-   object file.  */
+   object file.  FIXME: This is called by gdb.  If there is ever
+   another ECOFF target, it should be moved into some sort of target
+   specific structure.  */
 
-static boolean
+boolean
 ecoff_slurp_symbolic_info (abfd)
      bfd *abfd;
 {
@@ -558,9 +507,9 @@ ecoff_slurp_symbolic_info (abfd)
     {
       long cbline, issmax, issextmax;
 
-      cbline = (internal_symhdr->cbLine + 3) &~ 4;
-      issmax = (internal_symhdr->issMax + 3) &~ 4;
-      issextmax = (internal_symhdr->issExtMax + 3) &~ 4;
+      cbline = (internal_symhdr->cbLine + 3) &~ 3;
+      issmax = (internal_symhdr->issMax + 3) &~ 3;
+      issextmax = (internal_symhdr->issExtMax + 3) &~ 3;
       raw_size = (cbline * sizeof (unsigned char)
                  + internal_symhdr->idnMax * sizeof (struct dnr_ext)
                  + internal_symhdr->ipdMax * sizeof (struct pdr_ext)
@@ -697,7 +646,6 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext)
     case stLabel:
     case stProc:
     case stStaticProc:
-    case stBlock:
     case stNil:
       break;
     default:
@@ -2095,7 +2043,9 @@ ecoff_find_nearest_line (abfd,
 
   /* If we're not in the .text section, we don't have any line
      numbers.  */
-  if (strcmp (section->name, _TEXT) != 0)
+  if (strcmp (section->name, _TEXT) != 0
+      || offset < ecoff_data (abfd)->text_start
+      || offset >= ecoff_data (abfd)->text_end)
     return false;
 
   /* Make sure we have the FDR's.  */
@@ -2113,10 +2063,11 @@ ecoff_find_nearest_line (abfd,
   fdr_hold = (FDR *) NULL;
   for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
     {
+      if (fdr_ptr->cpd == 0)
+       continue;
       if (offset < fdr_ptr->adr)
        break;
-      if (fdr_ptr->cpd > 0)
-       fdr_hold = fdr_ptr;
+      fdr_hold = fdr_ptr;
     }
   if (fdr_hold == (FDR *) NULL)
     return false;
@@ -2180,10 +2131,6 @@ ecoff_find_nearest_line (abfd,
       offset -= count * 4;
     }
 
-  /* If offset is too large, this line is not interesting.  */
-  if (offset > 100)
-    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)
@@ -2473,6 +2420,7 @@ ecoff_get_debug (output_bfd, seclet, section, relocateable)
   struct sym_ext *sym_out;
   ecoff_symbol_type *esym_ptr;
   ecoff_symbol_type *esym_end;
+  unsigned long pdr_off;
   FDR *fdr_ptr;
   FDR *fdr_end;
   struct fdr_ext *fdr_out;
@@ -2639,6 +2587,15 @@ ecoff_get_debug (output_bfd, seclet, section, relocateable)
       memcpy (output_ecoff->external_pdr + output_symhdr->ipdMax,
              input_ecoff->external_pdr,
              input_symhdr->ipdMax * sizeof (struct pdr_ext));
+      if (input_symhdr->ipdMax == 0)
+       pdr_off = 0;
+      else
+       {
+         PDR pdr;
+
+         ecoff_swap_pdr_in (input_bfd, input_ecoff->external_pdr, &pdr);
+         pdr_off = pdr.adr;
+       }
       memcpy (output_ecoff->external_opt + output_symhdr->ioptMax,
              input_ecoff->external_opt,
              input_symhdr->ioptMax * sizeof (struct opt_ext));
@@ -2651,6 +2608,7 @@ ecoff_get_debug (output_bfd, seclet, section, relocateable)
       struct pdr_ext *pdr_in;
       struct pdr_ext *pdr_end;
       struct pdr_ext *pdr_out;
+      int first_pdr;
       struct opt_ext *opt_in;
       struct opt_ext *opt_end;
       struct opt_ext *opt_out;
@@ -2671,12 +2629,19 @@ ecoff_get_debug (output_bfd, seclet, section, relocateable)
       pdr_in = input_ecoff->external_pdr;
       pdr_end = pdr_in + input_symhdr->ipdMax;
       pdr_out = output_ecoff->external_pdr + output_symhdr->ipdMax;
+      first_pdr = 1;
+      pdr_off = 0;
       for (; pdr_in < pdr_end; pdr_in++, pdr_out++)
        {
          PDR pdr;
 
          ecoff_swap_pdr_in (input_bfd, pdr_in, &pdr);
          ecoff_swap_pdr_out (output_bfd, &pdr, pdr_out);
+         if (first_pdr)
+           {
+             pdr_off = pdr.adr;
+             first_pdr = 0;
+           }
        }
       opt_in = input_ecoff->external_opt;
       opt_end = opt_in + input_symhdr->ioptMax;
@@ -2704,10 +2669,13 @@ ecoff_get_debug (output_bfd, seclet, section, relocateable)
       fdr = *fdr_ptr;
 
       /* The memory address for this fdr is the address for the seclet
-        plus the offset to this fdr within input_bfd.  */
+        plus the offset to this fdr within input_bfd.  For some
+        reason the offset of the first procedure pointer is also
+        added in.  */
       fdr.adr = (bfd_get_section_vma (output_bfd, section)
                 + seclet->offset
-                + (fdr_ptr->adr - input_ecoff->fdr->adr));
+                + (fdr_ptr->adr - input_ecoff->fdr->adr)
+                + pdr_off);
 
       fdr.issBase += output_symhdr->issMax;
       fdr.isymBase += output_symhdr->isymMax;
@@ -3328,7 +3296,10 @@ ecoff_write_object_contents (abfd)
 
   /* Set up the file header.  */
 
-  internal_f.f_magic = MIPS_MAGIC_2;
+  if (abfd->xvec->header_byteorder_big_p != false)
+    internal_f.f_magic = MIPS_MAGIC_BIG;
+  else
+    internal_f.f_magic = MIPS_MAGIC_LITTLE;
 
   /*
     We will NOT put a fucking timestamp in the header here. Every time you
@@ -3659,7 +3630,7 @@ ecoff_slurp_armap (abfd)
   /* Make sure we have the right byte ordering.  */
   if (((nextname[ARMAP_HEADER_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN)
        ^ (abfd->xvec->header_byteorder_big_p != false))
-      || ((nextname[ARMAP_OBJECT_MARKER_INDEX] == ARMAP_BIG_ENDIAN)
+      || ((nextname[ARMAP_OBJECT_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN)
          ^ (abfd->xvec->byteorder_big_p != false)))
     {
       bfd_error = wrong_format;