fix XCOFF line number handling
authorIan Lance Taylor <ian@airs.com>
Wed, 25 Oct 1995 20:33:38 +0000 (20:33 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 25 Oct 1995 20:33:38 +0000 (20:33 +0000)
bfd/ChangeLog
bfd/libcoff-in.h
bfd/libcoff.h
bfd/xcofflink.c

index 418904fb1edad3315e10a59836c055843ca2bb62..530dc3d292c23d7b0eb17035396f470908788b71 100644 (file)
@@ -8,8 +8,8 @@ Wed Oct 25 11:32:54 1995  Ian Lance Taylor  <ian@cygnus.com>
        * xcofflink.c: Extensive changes to support linking shared objects
        and generating a .loader section.
        * libcoff-in.h (struct xcoff_tdata): Add import_file_id field.
-       (struct xcoff_section_tdata): Add first_symndx, last_symndx,
-       and ldrel_count fields.
+       (struct xcoff_section_tdata): Add lineno_count, first_symndx,
+       last_symndx, and ldrel_count fields.
        * libcoff.h: Rebuild.
        * coff-rs6000.c (xcoff_howto_table): Correct reloc names.
        * coffcode.h (styp_to_sec_flags): Don't set any flags if STYP_PAD
index aefa69bb25489e3b189255cd3dbc79d970429817..0dd01846b018682f0a32c1b36c6d7d12593bc1eb 100644 (file)
@@ -171,6 +171,9 @@ struct xcoff_section_tdata
   /* Used for XCOFF csects created by the linker; points to the real
      XCOFF section which contains this csect.  */
   asection *enclosing;
+  /* The lineno_count field for the enclosing section, because we are
+     going to clobber it there.  */
+  unsigned int lineno_count;
   /* The first and one past the last symbol indices for symbols used
      by this csect.  */
   unsigned long first_symndx;
index bf6bd5f4b0e6a08769e49a3021df6ffcd027f083..ebdcdfbb0d8b2391956bb81c5caf2c8adcc78d34 100644 (file)
@@ -171,6 +171,9 @@ struct xcoff_section_tdata
   /* Used for XCOFF csects created by the linker; points to the real
      XCOFF section which contains this csect.  */
   asection *enclosing;
+  /* The lineno_count field for the enclosing section, because we are
+     going to clobber it there.  */
+  unsigned int lineno_count;
   /* The first and one past the last symbol indices for symbols used
      by this csect.  */
   unsigned long first_symndx;
index 3e07d05ade93fad28707420f7b504fa7b6121099..60396207df4a4fa74238fdadccc5595f80d1cfe7 100644 (file)
@@ -1032,6 +1032,14 @@ xcoff_link_add_symbols (abfd, info)
              bfd_size_type linoff;
 
              enclosing = xcoff_section_data (abfd, csect)->enclosing;
+             if (enclosing == NULL)
+               {
+                 (*_bfd_error_handler)
+                   ("%s: `%s' has line numbers but no enclosing section",
+                    bfd_get_filename (abfd), name);
+                 bfd_set_error (bfd_error_bad_value);
+                 goto error_return;
+               }
              linoff = (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr
                        - enclosing->line_filepos);
              if (linoff < enclosing->lineno_count * linesz)
@@ -1310,6 +1318,8 @@ xcoff_link_add_symbols (abfd, info)
                goto error_return;
              }
            xcoff_section_data (abfd, csect)->enclosing = enclosing;
+           xcoff_section_data (abfd, csect)->lineno_count =
+             enclosing->lineno_count;
 
            /* XCOFF requires that relocs be sorted by address, so we
                could do a binary search here.  FIXME.  (XCOFF
@@ -2783,6 +2793,12 @@ _bfd_xcoff_bfd_final_link (abfd, info)
                max_contents_size = sec->_raw_size;
              if (sec->lineno_count > max_lineno_count)
                max_lineno_count = sec->lineno_count;
+             if (coff_section_data (sec->owner, sec) != NULL
+                 && xcoff_section_data (sec->owner, sec) != NULL
+                 && (xcoff_section_data (sec->owner, sec)->lineno_count
+                     > max_lineno_count))
+               max_lineno_count =
+                 xcoff_section_data (sec->owner, sec)->lineno_count;
              if (sec->reloc_count > max_reloc_count)
                max_reloc_count = sec->reloc_count;
            }
@@ -3201,13 +3217,14 @@ xcoff_link_input_bfd (finfo, input_bfd)
   bfd_size_type linesz;
   bfd_byte *esym;
   bfd_byte *esym_end;
+  struct xcoff_link_hash_entry **sym_hash;
   struct internal_syment *isymp;
   asection **csectpp;
   unsigned long *debug_index;
   long *indexp;
   unsigned long output_index;
   bfd_byte *outsym;
-  struct xcoff_link_hash_entry **sym_hash;
+  asection *oline;
   boolean keep_syms;
   asection *o;
 
@@ -3252,6 +3269,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
   indexp = finfo->sym_indices;
   output_index = syment_base;
   outsym = finfo->outsyms;
+  oline = NULL;
 
   while (esym < esym_end)
     {
@@ -3761,24 +3779,30 @@ xcoff_link_input_bfd (finfo, input_bfd)
                  else
                    {
                      asection *enclosing;
+                     unsigned int enc_count;
                      bfd_size_type linoff;
                      struct internal_lineno lin;
 
                      o = *csectpp;
                      enclosing = xcoff_section_data (abfd, o)->enclosing;
+                     enc_count = xcoff_section_data (abfd, o)->lineno_count;
+                     if (oline != enclosing)
+                       {
+                         if (bfd_seek (input_bfd,
+                                       enclosing->line_filepos,
+                                       SEEK_SET) != 0
+                             || (bfd_read (finfo->linenos, linesz,
+                                           enc_count, input_bfd)
+                                 != linesz * enc_count))
+                           return false;
+                         oline = enclosing;
+                       }
+
                      linoff = (aux.x_sym.x_fcnary.x_fcn.x_lnnoptr
                                - enclosing->line_filepos);
 
-                     if (bfd_seek (input_bfd,
-                                   enclosing->line_filepos + linoff,
-                                   SEEK_SET != 0)
-                         || (bfd_read (finfo->linenos, linesz,
-                                       o->lineno_count, input_bfd)
-                             != linesz * o->lineno_count))
-                       return false;
-
                      bfd_coff_swap_lineno_in (input_bfd,
-                                              (PTR) finfo->linenos,
+                                              (PTR) (finfo->linenos + linoff),
                                               (PTR) &lin);
                      if (lin.l_lnno != 0
                          || ((bfd_size_type) lin.l_addr.l_symndx
@@ -3796,14 +3820,15 @@ xcoff_link_input_bfd (finfo, input_bfd)
 
                          lin.l_addr.l_symndx = *indexp;
                          bfd_coff_swap_lineno_out (output_bfd, (PTR) &lin,
-                                                   (PTR) finfo->linenos);
+                                                   (PTR) (finfo->linenos
+                                                          + linoff));
 
                          linpend = (finfo->linenos
-                                    + o->lineno_count * linesz);
+                                    + enc_count * linesz);
                          offset = (o->output_section->vma
                                    + o->output_offset
                                    - o->vma);
-                         for (linp = finfo->linenos + linesz;
+                         for (linp = finfo->linenos + linoff + linesz;
                               linp < linpend;
                               linp += linesz)
                            {
@@ -3817,7 +3842,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                                                        (PTR) linp);
                            }
 
-                         count = (linp - finfo->linenos) / linesz;
+                         count = (linp - (finfo->linenos + linoff)) / linesz;
 
                          aux.x_sym.x_fcnary.x_fcn.x_lnnoptr =
                            (o->output_section->line_filepos
@@ -3826,8 +3851,8 @@ xcoff_link_input_bfd (finfo, input_bfd)
                          if (bfd_seek (output_bfd,
                                        aux.x_sym.x_fcnary.x_fcn.x_lnnoptr,
                                        SEEK_SET) != 0
-                             || (bfd_write (finfo->linenos, linesz, count,
-                                            output_bfd)
+                             || (bfd_write (finfo->linenos + linoff,
+                                            linesz, count, output_bfd)
                                  != linesz * count))
                            return false;