* config/tc-sh.h (struct sh_segment_info_type): Define.
[deliverable/binutils-gdb.git] / gas / config / obj-coff.c
index e80eeb9df3337193ab895695282cbdf866ed12b8..424feecaa5132908fdf8d548972df0b544e6a4ce 100644 (file)
@@ -1,5 +1,5 @@
 /* coff object file format
-   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994
+   Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 1996
    Free Software Foundation, Inc.
 
    This file is part of GAS.
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GAS; see the file COPYING.  If not, write to
-   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
 #include "as.h"
 #include "obstack.h"
 #include "subsegs.h"
+#include "libiberty.h"
 
 /* I think this is probably always correct.  */
 #ifndef KEEP_RELOC_INFO
 #define KEEP_RELOC_INFO
 #endif
 
+
+/* structure used to keep the filenames which
+   are too long around so that we can stick them
+   into the string table */
+struct filename_list 
+{
+  char *filename;
+  struct filename_list *next;
+};
+
+static struct filename_list *filename_list_head;
+static struct filename_list *filename_list_tail;
+
 const char *s_get_name PARAMS ((symbolS * s));
 static symbolS *def_symbol_in_progress;
 
@@ -401,7 +416,7 @@ obj_symbol_new_hook (symbolP)
 static symbolS *current_lineno_sym;
 static struct line_no *line_nos;
 /* @@ Blindly assume all .ln directives will be in the .text section...  */
-static int n_line_nos;
+int coff_n_line_nos;
 
 static void
 add_lineno (frag, offset, num)
@@ -420,7 +435,7 @@ add_lineno (frag, offset, num)
   new_line->l.line_number = num;
   new_line->l.u.offset = offset;
   line_nos = new_line;
-  n_line_nos++;
+  coff_n_line_nos++;
 }
 
 void
@@ -430,7 +445,7 @@ coff_add_linesym (sym)
   if (line_nos)
     {
       coffsymbol (current_lineno_sym->bsym)->lineno = (alent *) line_nos;
-      n_line_nos++;
+      coff_n_line_nos++;
       line_nos = 0;
     }
   current_lineno_sym = sym;
@@ -759,6 +774,16 @@ obj_coff_line (ignore)
   SA_SET_SYM_LNNO (def_symbol_in_progress, coff_line_base);
 
   demand_empty_rest_of_line ();
+
+#ifndef NO_LISTING
+  if (strcmp (".bf", S_GET_NAME (def_symbol_in_progress)) == 0)
+    {
+      extern int listing;
+
+      if (listing)
+       listing_source_line ((unsigned int) coff_line_base);
+    }
+#endif
 }
 
 static void
@@ -906,6 +931,7 @@ obj_read_begin_hook ()
 
 
 symbolS *coff_last_function;
+static symbolS *coff_last_bf;
 
 void
 coff_frob_symbol (symp, punt)
@@ -915,6 +941,7 @@ coff_frob_symbol (symp, punt)
   static symbolS *last_tagP;
   static stack *block_stack;
   static symbolS *set_end;
+  symbolS *next_set_end = NULL;
 
   if (symp == &abs_symbol)
     {
@@ -935,6 +962,7 @@ coff_frob_symbol (symp, punt)
     {
       symbolS *real;
       if (!SF_GET_LOCAL (symp)
+         && !SF_GET_STATICS (symp)
          && (real = symbol_find_base (S_GET_NAME (symp), DO_NOT_STRIP))
          && real != symp)
        {
@@ -967,7 +995,7 @@ coff_frob_symbol (symp, punt)
                  if (begin == 0)
                    as_warn ("mismatched .eb");
                  else
-                   set_end = begin;
+                   next_set_end = begin;
                }
            }
          if (coff_last_function == 0 && SF_GET_FUNCTION (symp))
@@ -987,14 +1015,14 @@ coff_frob_symbol (symp, punt)
              SA_SET_SYM_FSIZE (coff_last_function,
                                (long) (S_GET_VALUE (symp)
                                        - S_GET_VALUE (coff_last_function)));
-             set_end = coff_last_function;
+             next_set_end = coff_last_function;
              coff_last_function = 0;
            }
        }
       else if (SF_GET_TAG (symp))
        last_tagP = symp;
       else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
-       set_end = last_tagP;
+       next_set_end = last_tagP;
       else if (S_GET_STORAGE_CLASS (symp) == C_FILE)
        {
          if (S_GET_VALUE (symp))
@@ -1007,9 +1035,24 @@ coff_frob_symbol (symp, punt)
        S_SET_STORAGE_CLASS (symp, C_EXT);
       else if (SF_GET_LOCAL (symp))
        *punt = 1;
+
+      if (SF_GET_FUNCTION (symp))
+       symp->bsym->flags |= BSF_FUNCTION;
+
       /* more ... */
     }
 
+#ifdef OBJ_XCOFF
+  /* This is pretty horrible, but we have to set *punt correctly in
+     order to call SA_SET_SYM_ENDNDX correctly.  */
+  if (! symp->sy_used_in_reloc
+      && ((symp->bsym->flags & BSF_SECTION_SYM) != 0
+         || (! S_IS_EXTERNAL (symp)
+             && ! symp->sy_tc.output
+             && S_GET_STORAGE_CLASS (symp) != C_FILE)))
+    *punt = 1;
+#endif
+
   if (set_end != (symbolS *) NULL
       && ! *punt)
     {
@@ -1017,6 +1060,19 @@ coff_frob_symbol (symp, punt)
       set_end = NULL;
     }
 
+  if (next_set_end != NULL
+      && ! *punt)
+    set_end = next_set_end;
+
+  if (! *punt
+      && S_GET_STORAGE_CLASS (symp) == C_FCN
+      && strcmp (S_GET_NAME (symp), ".bf") == 0)
+    {
+      if (coff_last_bf != NULL)
+       SA_SET_SYM_ENDNDX (coff_last_bf, symp);
+      coff_last_bf = symp;
+    }
+
   if (coffsymbol (symp->bsym)->lineno)
     {
       int i;
@@ -1061,7 +1117,7 @@ coff_adjust_section_syms (abfd, sec, x)
     return;
 
   if (!strcmp (sec->name, ".text"))
-    nlnno = n_line_nos;
+    nlnno = coff_n_line_nos;
   else
     nlnno = 0;
   {
@@ -1116,6 +1172,14 @@ obj_coff_section (ignore)
   flagword flags;
   asection *sec;
 
+  if (flag_mri)
+    {
+      char type;
+
+      s_mri_sect (&type);
+      return;
+    }
+
   section_name = input_line_pointer;
   c = get_symbol_end ();
 
@@ -1177,6 +1241,8 @@ obj_coff_section (ignore)
                 bfd_section_name (stdoutput, sec),
                 bfd_errmsg (bfd_get_error ()));
     }
+
+  demand_empty_rest_of_line ();
 }
 
 void
@@ -1310,6 +1376,10 @@ symbol_dump ()
 #include "libbfd.h"
 #include "libcoff.h"
 
+#ifdef TE_PE
+#include "coff/pe.h"
+#endif
+
 /* The NOP_OPCODE is for the alignment fill value.  Fill with nop so
    that we can stick sections together without causing trouble.  */
 #ifndef NOP_OPCODE
@@ -1327,16 +1397,10 @@ symbol_dump ()
 const short seg_N_TYPE[] =
 {                              /* in: segT   out: N_TYPE bits */
   C_ABS_SECTION,
-  1,
-  2,
-  3,
-  4,
-  5,
-  6,
-  7,
-  8,
-  9,
-  10,
+  1,    2,  3,   4,    5,   6,   7,   8,   9,  10,
+  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,
+  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,
+  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,
   C_UNDEF_SECTION,             /* SEG_UNKNOWN */
   C_UNDEF_SECTION,             /* SEG_GOOF */
   C_UNDEF_SECTION,             /* SEG_EXPR */
@@ -1396,42 +1460,39 @@ void obj_coff_section PARAMS ((int));
 /* Section stuff
 
    We allow more than just the standard 3 sections, infact, we allow
-   10 sections, (though the usual three have to be there).
+   40 sections, (though the usual three have to be there).
 
    This structure performs the mappings for us:
-
 */
 
-#define N_SEG 32
+
 typedef struct
 {
   segT seg_t;
   int i;
 } seg_info_type;
 
-static const seg_info_type seg_info_off_by_4[N_SEG] =
+static const seg_info_type seg_info_off_by_4[] =
 {
  {SEG_PTV,  },
  {SEG_NTV,  },
  {SEG_DEBUG, },
  {SEG_ABSOLUTE,  },
  {SEG_UNKNOWN,  },
- {SEG_E0},
- {SEG_E1},
- {SEG_E2},
- {SEG_E3},
- {SEG_E4},
- {SEG_E5},
- {SEG_E6},
- {SEG_E7},
- {SEG_E8},
- {SEG_E9},
- {(segT)15},
- {(segT)16},
- {(segT)17},
- {(segT)18},
- {(segT)19},
- {(segT)20},
+ {SEG_E0}, {SEG_E1}, {SEG_E2}, {SEG_E3}, {SEG_E4},
+ {SEG_E5}, {SEG_E6}, {SEG_E7}, {SEG_E8}, {SEG_E9},
+ {SEG_E10},{SEG_E11},{SEG_E12},{SEG_E13},{SEG_E14},
+ {SEG_E15},{SEG_E16},{SEG_E17},{SEG_E18},{SEG_E19},
+ {SEG_E20},{SEG_E21},{SEG_E22},{SEG_E23},{SEG_E24},
+ {SEG_E25},{SEG_E26},{SEG_E27},{SEG_E28},{SEG_E29},
+ {SEG_E30},{SEG_E31},{SEG_E32},{SEG_E33},{SEG_E34},
+ {SEG_E35},{SEG_E36},{SEG_E37},{SEG_E38},{SEG_E39},
+ {(segT)40},
+ {(segT)41},
+ {(segT)42},
+ {(segT)43},
+ {(segT)44},
+ {(segT)45},
  {(segT)0},
  {(segT)0},
  {(segT)0},
@@ -1499,6 +1560,7 @@ size_section (abfd, idx)
          size += frag->fr_offset * frag->fr_var;
          break;
        case rs_align:
+       case rs_align_code:
          size += frag->fr_fix;
          size += relax_align (size, frag->fr_offset);
          break;
@@ -1542,6 +1604,25 @@ count_entries_in_chain (idx)
   return nrelocs;
 }
 
+#ifdef TE_AUX
+
+static int compare_external_relocs PARAMS ((const PTR, const PTR));
+
+/* AUX's ld expects relocations to be sorted */
+static int
+compare_external_relocs (x, y)
+     const PTR x;
+     const PTR y;
+{
+  struct external_reloc *a = (struct external_reloc *) x;
+  struct external_reloc *b = (struct external_reloc *) y;
+  bfd_vma aadr = bfd_getb32 (a->r_vaddr);
+  bfd_vma badr = bfd_getb32 (b->r_vaddr);
+  return (aadr < badr ? -1 : badr < aadr ? 1 : 0);
+}
+
+#endif
+
 /* output all the relocations for a section */
 void
 do_relocs_for (abfd, h, file_cursor)
@@ -1553,7 +1634,7 @@ do_relocs_for (abfd, h, file_cursor)
   unsigned int idx;
   unsigned long reloc_start = *file_cursor;
 
-  for (idx = SEG_E0; idx < SEG_E9; idx++)
+  for (idx = SEG_E0; idx < SEG_LAST; idx++)
     {
       if (segment_info[idx].scnhdr.s_name[0])
        {
@@ -1584,7 +1665,8 @@ do_relocs_for (abfd, h, file_cursor)
                  if (TC_COUNT_RELOC (fix_ptr))
                    {
 #ifdef TC_RELOC_MANGLE
-                     TC_RELOC_MANGLE (fix_ptr, &intr, base);
+                     TC_RELOC_MANGLE (&segment_info[idx], fix_ptr, &intr,
+                                      base);
 
 #else
                      symbolS *dot;
@@ -1600,6 +1682,11 @@ do_relocs_for (abfd, h, file_cursor)
                      intr.r_offset = 0;
 #endif
 
+                     while (symbol_ptr->sy_value.X_op == O_symbol
+                            && (! S_IS_DEFINED (symbol_ptr)
+                                || S_IS_COMMON (symbol_ptr)))
+                       symbol_ptr = symbol_ptr->sy_value.X_add_symbol;
+
                      /* Turn the segment of the symbol into an offset.  */
                      if (symbol_ptr)
                        {
@@ -1644,6 +1731,12 @@ do_relocs_for (abfd, h, file_cursor)
                  fix_ptr = fix_ptr->fx_next;
                }
 
+#ifdef TE_AUX
+             /* Sort the reloc table */
+             qsort ((PTR) external_reloc_vec, nrelocs,
+                    sizeof (struct external_reloc), compare_external_relocs);
+#endif
+
              /* Write out the reloc table */
              bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size,
                         abfd);
@@ -1749,6 +1842,7 @@ fill_section (abfd, h, file_cursor)
                  assert (frag->fr_symbol == 0);
                case rs_fill:
                case rs_align:
+               case rs_align_code:
                case rs_org:
                  if (frag->fr_fix)
                    {
@@ -1828,14 +1922,31 @@ coff_header_append (abfd, h)
   bfd_write (buffer, i, 1, abfd);
   bfd_write (buffero, H_GET_SIZEOF_OPTIONAL_HEADER (h), 1, abfd);
 
-  for (i = SEG_E0; i < SEG_E9; i++)
+  for (i = SEG_E0; i < SEG_LAST; i++)
     {
+#ifdef COFF_LONG_SECTION_NAMES
+      unsigned long string_size = 4;
+#endif
+
       if (segment_info[i].scnhdr.s_name[0])
        {
-         unsigned int size =
-         bfd_coff_swap_scnhdr_out (abfd,
-                                   &(segment_info[i].scnhdr),
-                                   buffer);
+         unsigned int size;
+
+#ifdef COFF_LONG_SECTION_NAMES
+         /* Support long section names as found in PE.  This code
+             must coordinate with that in write_object_file and
+             w_strings.  */
+         if (strlen (segment_info[i].name) > SCNNMLEN)
+           {
+             memset (segment_info[i].scnhdr.s_name, 0, SCNNMLEN);
+             sprintf (segment_info[i].scnhdr.s_name, "/%lu", string_size);
+             string_size += strlen (segment_info[i].name) + 1;
+           }
+#endif
+
+         size = bfd_coff_swap_scnhdr_out (abfd,
+                                          &(segment_info[i].scnhdr),
+                                          buffer);
          if (size == 0)
            as_bad ("bfd_coff_swap_scnhdr_out failed");
          bfd_write (buffer, size, 1, abfd);
@@ -2058,6 +2169,8 @@ obj_coff_endef (ignore)
          SA_GET_SYM_LNNOPTR (last_line_symbol) = function_lineoff;
 
          SF_SET_PROCESS (last_line_symbol);
+         SF_SET_ADJ_LNNOPTR (last_line_symbol);
+         SF_SET_PROCESS (def_symbol_in_progress);
          function_lineoff = -1;
        }
       /* Value is always set to . */
@@ -2254,7 +2367,7 @@ obj_coff_line (ignore)
 #ifndef NO_LISTING
       {
        extern int listing;
-       if (listing && 0)
+       if (listing)
          {
            listing_source_line ((unsigned int) line_base);
          }
@@ -2414,6 +2527,24 @@ obj_coff_val (ignore)
   demand_empty_rest_of_line ();
 }
 
+#ifdef TE_PE
+
+/* Handle the .linkonce pseudo-op.  This is parsed by s_linkonce in
+   read.c, which then calls this object file format specific routine.  */
+
+void
+obj_coff_pe_handle_link_once (type)
+     enum linkonce_type type;
+{
+  seg_info (now_seg)->scnhdr.s_flags |= IMAGE_SCN_LNK_COMDAT;
+
+  /* We store the type in the seg_info structure, and use it to set up
+     the auxiliary entry for the section symbol in c_section_symbol.  */
+  seg_info (now_seg)->linkonce = type;
+}
+
+#endif /* TE_PE */
+
 void
 obj_read_begin_hook ()
 {
@@ -2428,12 +2559,17 @@ obj_read_begin_hook ()
 /* This function runs through the symbol table and puts all the
    externals onto another chain */
 
+/* The chain of globals.  */
+symbolS *symbol_globalP;
+symbolS *symbol_global_lastP;
+
 /* The chain of externals */
 symbolS *symbol_externP;
 symbolS *symbol_extern_lastP;
 
 stack *block_stack;
 symbolS *last_functionP;
+static symbolS *last_bfP;
 symbolS *last_tagP;
 
 static unsigned int
@@ -2443,10 +2579,21 @@ yank_symbols ()
   unsigned int symbol_number = 0;
   unsigned int last_file_symno = 0;
 
+  struct filename_list *filename_list_scan = filename_list_head;
+
   for (symbolP = symbol_rootP;
        symbolP;
        symbolP = symbolP ? symbol_next (symbolP) : symbol_rootP)
     {
+      if (symbolP->sy_mri_common)
+       {
+         if (S_GET_STORAGE_CLASS (symbolP) == C_EXT)
+           as_bad ("%s: global symbols not supported in common sections",
+                   S_GET_NAME (symbolP));
+         symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+         continue;
+       }
+
       if (!SF_GET_DEBUG (symbolP))
        {
          /* Debug symbols do not need all this rubbish */
@@ -2454,6 +2601,7 @@ yank_symbols ()
 
          /* L* and C_EFCN symbols never merge. */
          if (!SF_GET_LOCAL (symbolP)
+             && !SF_GET_STATICS (symbolP)
              && S_GET_STORAGE_CLASS (symbolP) != C_LABEL
              && symbolP->sy_value.X_op == O_constant
              && (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP))
@@ -2539,11 +2687,19 @@ yank_symbols ()
                         sizeof (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
 #endif
                }
-             /* The C_FCN doesn't need any additional information.  I
-                don't even know if this is needed for sdb. But the
-                standard assembler generates it, so...  */
-             if (S_GET_STORAGE_CLASS (symbolP) == C_EFCN)
+             if (S_GET_STORAGE_CLASS (symbolP) == C_FCN)
                {
+                 if (strcmp (S_GET_NAME (symbolP), ".bf") == 0)
+                   {
+                     if (last_bfP != NULL)
+                       SA_SET_SYM_ENDNDX (last_bfP, symbol_number);
+                     last_bfP = symbolP;
+                   }
+               }
+             else if (S_GET_STORAGE_CLASS (symbolP) == C_EFCN)
+               {
+                 /* I don't even know if this is needed for sdb. But
+                    the standard assembler generates it, so...  */
                  if (last_functionP == (symbolS *) 0)
                    as_fatal ("C_EFCN symbol out of scope");
                  SA_SET_SYM_FSIZE (last_functionP,
@@ -2568,6 +2724,15 @@ yank_symbols ()
        }
       else if (S_GET_STORAGE_CLASS (symbolP) == C_FILE)
        {
+         /* If the filename was too long to fit in the
+            auxent, put it in the string table */
+         if (SA_GET_FILE_FNAME_ZEROS (symbolP) == 0
+             && SA_GET_FILE_FNAME_OFFSET (symbolP) != 0)
+           {
+             SA_SET_FILE_FNAME_OFFSET (symbolP, string_byte_count);
+             string_byte_count += strlen (filename_list_scan->filename) + 1;
+             filename_list_scan = filename_list_scan->next;
+           }
          if (S_GET_VALUE (symbolP))
            {
              S_SET_VALUE (symbolP, last_file_symno);
@@ -2594,6 +2759,13 @@ yank_symbols ()
          symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
 
        }
+      else if (symbolP->sy_value.X_op == O_symbol
+              && (! S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)))
+       {
+         /* Skip symbols which were equated to undefined or common
+            symbols.  */
+         symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+       }
       else if (!S_IS_DEFINED (symbolP)
               && !S_IS_DEBUG (symbolP)
               && !SF_GET_STATICS (symbolP) &&
@@ -2607,6 +2779,23 @@ yank_symbols ()
          symbol_append (symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP);
          symbolP = hold;
        }
+      else if (! S_IS_DEBUG (symbolP)
+              && ! SF_GET_STATICS (symbolP)
+              && ! SF_GET_FUNCTION (symbolP)
+              && S_GET_STORAGE_CLASS (symbolP) == C_EXT)
+       {
+         symbolS *hold = symbol_previous (symbolP);
+
+         /* The O'Reilly COFF book says that defined global symbols
+             come at the end of the symbol table, just before
+             undefined global symbols.  */
+
+         symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+         symbol_clear_list_pointers (symbolP);
+         symbol_append (symbolP, symbol_global_lastP, &symbol_globalP,
+                        &symbol_global_lastP);
+         symbolP = hold;
+       }
       else
        {
          if (SF_GET_STRING (symbolP))
@@ -2629,16 +2818,19 @@ yank_symbols ()
 
 
 static unsigned int
-glue_symbols ()
+glue_symbols (head, tail)
+     symbolS **head;
+     symbolS **tail;
 {
   unsigned int symbol_number = 0;
   symbolS *symbolP;
-  for (symbolP = symbol_externP; symbol_externP;)
+
+  for (symbolP = *head; *head != NULL;)
     {
-      symbolS *tmp = symbol_externP;
+      symbolS *tmp = *head;
 
       /* append */
-      symbol_remove (tmp, &symbol_externP, &symbol_extern_lastP);
+      symbol_remove (tmp, head, tail);
       symbol_append (tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
 
       /* and process */
@@ -2655,8 +2847,8 @@ glue_symbols ()
       tmp->sy_number = symbol_number;
       symbol_number += 1 + S_GET_NUMBER_AUXILIARY (tmp);
     }                          /* append the entire extern chain */
-  return symbol_number;
 
+  return symbol_number;
 }
 
 static unsigned int
@@ -2719,25 +2911,24 @@ crawl_symbols (h, abfd)
    */
 
 
-  for (i = SEG_E0; i < SEG_E9; i++)
-    {
-      if (segment_info[i].scnhdr.s_name[0])
-       {
-         char name[9];
-
-         strncpy (name, segment_info[i].scnhdr.s_name, 8);
-         name[8] = '\0';
-         segment_info[i].dot = c_section_symbol (name, i - SEG_E0 + 1);
-       }
-    }
-
+  for (i = SEG_E0; i < SEG_LAST; i++)
+    if (segment_info[i].scnhdr.s_name[0])
+      segment_info[i].dot = c_section_symbol (segment_info[i].name,
+                                             i - SEG_E0 + 1);
 
   /* Take all the externals out and put them into another chain */
   H_SET_SYMBOL_TABLE_SIZE (h, yank_symbols ());
   /* Take the externals and glue them onto the end.*/
-  H_SET_SYMBOL_TABLE_SIZE (h, H_GET_SYMBOL_COUNT (h) + glue_symbols ());
+  H_SET_SYMBOL_TABLE_SIZE (h,
+                          (H_GET_SYMBOL_COUNT (h)
+                           + glue_symbols (&symbol_globalP,
+                                           &symbol_global_lastP)
+                           + glue_symbols (&symbol_externP,
+                                           &symbol_extern_lastP)));
 
   H_SET_SYMBOL_TABLE_SIZE (h, tie_tags ());
+  know (symbol_globalP == NULL);
+  know (symbol_global_lastP == NULL);
   know (symbol_externP == NULL);
   know (symbol_extern_lastP == NULL);
 }
@@ -2751,10 +2942,33 @@ w_strings (where)
      char *where;
 {
   symbolS *symbolP;
+  struct filename_list *filename_list_scan = filename_list_head;
 
   /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
   md_number_to_chars (where, (valueT) string_byte_count, 4);
   where += 4;
+
+#ifdef COFF_LONG_SECTION_NAMES
+  /* Support long section names as found in PE.  This code must
+     coordinate with that in coff_header_append and write_object_file.  */
+  {
+    unsigned int i;
+
+    for (i = SEG_E0; i < SEG_LAST; i++)
+      {
+       if (segment_info[i].scnhdr.s_name[0]
+           && strlen (segment_info[i].name) > SCNNMLEN)
+         {
+           unsigned int size;
+
+           size = strlen (segment_info[i].name) + 1;
+           memcpy (where, segment_info[i].name, size);
+           where += size;
+         }
+      }
+  }
+#endif /* COFF_LONG_SECTION_NAMES */
+
   for (symbolP = symbol_rootP;
        symbolP;
        symbolP = symbol_next (symbolP))
@@ -2764,10 +2978,17 @@ w_strings (where)
       if (SF_GET_STRING (symbolP))
        {
          size = strlen (S_GET_NAME (symbolP)) + 1;
-
          memcpy (where, S_GET_NAME (symbolP), size);
          where += size;
-
+       }
+      if (S_GET_STORAGE_CLASS (symbolP) == C_FILE
+         && SA_GET_FILE_FNAME_ZEROS (symbolP) == 0
+         && SA_GET_FILE_FNAME_OFFSET (symbolP) != 0)
+       {
+         size = strlen (filename_list_scan->filename) + 1;
+         memcpy (where, filename_list_scan->filename, size);
+         filename_list_scan = filename_list_scan ->next;
+         where += size;
        }
     }
 }
@@ -2781,7 +3002,7 @@ do_linenos_for (abfd, h, file_cursor)
   unsigned int idx;
   unsigned long start = *file_cursor;
 
-  for (idx = SEG_E0; idx < SEG_E9; idx++)
+  for (idx = SEG_E0; idx < SEG_LAST; idx++)
     {
       segment_info_type *s = segment_info + idx;
 
@@ -2863,7 +3084,7 @@ extern void
 write_object_file ()
 {
   int i;
-  char *name;
+  const char *name;
   struct frchain *frchain_ptr;
 
   object_headers headers;
@@ -2895,8 +3116,17 @@ write_object_file ()
       subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
 #ifndef SUB_SEGMENT_ALIGN
 #define SUB_SEGMENT_ALIGN(SEG) 1
+#endif
+#ifdef md_do_align
+      {
+       static char nop = NOP_OPCODE;
+       md_do_align (SUB_SEGMENT_ALIGN (now_seg), &nop, 1, alignment_done);
+      }
 #endif
       frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE);
+#ifdef md_do_align
+    alignment_done:
+#endif
       frag_wane (frag_now);
       frag_now->fr_fix = 0;
       know (frag_now->fr_next == NULL);
@@ -2926,6 +3156,19 @@ write_object_file ()
        {
          H_SET_NUMBER_OF_SECTIONS (&headers,
                                    H_GET_NUMBER_OF_SECTIONS (&headers) + 1);
+
+#ifdef COFF_LONG_SECTION_NAMES
+         /* Support long section names as found in PE.  This code
+            must coordinate with that in coff_header_append and
+            w_strings.  */
+         {
+           unsigned int len;
+
+           len = strlen (segment_info[i].name);
+           if (len > SCNNMLEN)
+             string_byte_count += len + 1;
+         }
+#endif /* COFF_LONG_SECTION_NAMES */
        }
 
       size = size_section (abfd, (unsigned int) i);
@@ -2933,7 +3176,7 @@ write_object_file ()
 
       /* I think the section alignment is only used on the i960; the
         i960 needs it, and it should do no harm on other targets.  */
-      segment_info[i].scnhdr.s_align = section_alignment[i];
+      segment_info[i].scnhdr.s_align = 1 << section_alignment[i];
 
       if (i == SEG_E0)
        H_SET_TEXT_SIZE (&headers, size);
@@ -2951,6 +3194,10 @@ write_object_file ()
 
   H_SET_STRING_SIZE (&headers, string_byte_count);
 
+#ifdef tc_frob_file
+  tc_frob_file ();
+#endif
+
   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
     {
       fixup_mdeps (segment_info[i].frchainP->frch_root, &headers, i);
@@ -2961,7 +3208,7 @@ write_object_file ()
      correctly. */
   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
     {
-      name = segment_info[i].scnhdr.s_name;
+      name = segment_info[i].name;
 
       if (name != NULL
          && strncmp (".stab", name, 5) == 0
@@ -3039,22 +3286,21 @@ segT
 obj_coff_add_segment (name)
      const char *name;
 {
-  unsigned int len;
   unsigned int i;
 
-  /* Find out if we've already got a section of this name.  */
-  len = strlen (name);
-  if (len < sizeof (segment_info[i].scnhdr.s_name))
-    ++len;
-  else
-    len = sizeof (segment_info[i].scnhdr.s_name);
-  for (i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0]; i++)
-    if (strncmp (segment_info[i].scnhdr.s_name, name, len) == 0
-       && (len == sizeof (segment_info[i].scnhdr.s_name)
-           || segment_info[i].scnhdr.s_name[len] == '\0'))
+#ifndef COFF_LONG_SECTION_NAMES
+  char buf[SCNNMLEN + 1];
+
+  strncpy (buf, name, SCNNMLEN);
+  buf[SCNNMLEN] = '\0';
+  name = buf;
+#endif
+
+  for (i = SEG_E0; i < SEG_LAST && segment_info[i].scnhdr.s_name[0]; i++)
+    if (strcmp (name, segment_info[i].name) == 0)
       return (segT) i;
 
-  if (i == SEG_E9)
+  if (i == SEG_LAST)
     {
       as_bad ("Too many new sections; can't add \"%s\"", name);
       return now_seg;
@@ -3064,6 +3310,7 @@ obj_coff_add_segment (name)
   strncpy (segment_info[i].scnhdr.s_name, name,
           sizeof (segment_info[i].scnhdr.s_name));
   segment_info[i].scnhdr.s_flags = STYP_REG;
+  segment_info[i].name = xstrdup (name);
 
   return (segT) i;
 }
@@ -3089,36 +3336,43 @@ obj_coff_section (ignore)
      int ignore;
 {
   /* Strip out the section name */
-  char *section_name;
-  char *section_name_end;
+  char *section_name, *name;
   char c;
-  int argp;
-  unsigned int len;
   unsigned int exp;
   long flags;
 
+  if (flag_mri)
+    {
+      char type;
+
+      s_mri_sect (&type);
+      flags = 0;
+      if (type == 'C')
+       flags = STYP_TEXT;
+      else if (type == 'D')
+       flags = STYP_DATA;
+      segment_info[now_seg].scnhdr.s_flags |= flags;
+
+      return;
+    }
+
   section_name = input_line_pointer;
   c = get_symbol_end ();
-  section_name_end = input_line_pointer;
 
-  len = section_name_end - section_name;
-  input_line_pointer++;
-  SKIP_WHITESPACE ();
+  name = xmalloc (input_line_pointer - section_name + 1);
+  strcpy (name, section_name);
 
-  argp = 0;
-  if (c == ',')
-    argp = 1;
-  else if (*input_line_pointer == ',')
-    {
-      argp = 1;
-      ++input_line_pointer;
-      SKIP_WHITESPACE ();
-    }
+  *input_line_pointer = c;
 
   exp = 0;
   flags = 0;
-  if (argp)
+
+  SKIP_WHITESPACE ();
+  if (*input_line_pointer == ',')
     {
+      ++input_line_pointer;
+      SKIP_WHITESPACE ();
+
       if (*input_line_pointer != '"')
        exp = get_absolute_expression ();
       else
@@ -3149,11 +3403,11 @@ obj_coff_section (ignore)
        }
     }
 
-  subseg_new (section_name, (subsegT) exp);
+  subseg_new (name, (subsegT) exp);
 
   segment_info[now_seg].scnhdr.s_flags |= flags;
 
-  *section_name_end = c;
+  demand_empty_rest_of_line ();
 }
 
 
@@ -3272,7 +3526,32 @@ c_dot_file_symbol (filename)
 
   S_SET_STORAGE_CLASS (symbolP, C_FILE);
   S_SET_NUMBER_AUXILIARY (symbolP, 1);
-  SA_SET_FILE_FNAME (symbolP, filename);
+
+  if (strlen (filename) > FILNMLEN)
+    {
+      /* Filename is too long to fit into an auxent,
+        we stick it into the string table instead.  We keep
+        a linked list of the filenames we find so we can emit
+        them later.*/
+      struct filename_list *f = ((struct filename_list *)
+                                xmalloc (sizeof (struct filename_list)));
+
+      f->filename = filename;
+      f->next = 0;
+
+      SA_SET_FILE_FNAME_ZEROS (symbolP, 0);
+      SA_SET_FILE_FNAME_OFFSET (symbolP, 1);
+
+      if (filename_list_tail) 
+       filename_list_tail->next = f;
+      else
+       filename_list_head = f;
+      filename_list_tail = f;      
+    }
+  else 
+    {
+      SA_SET_FILE_FNAME (symbolP, filename);
+    }
 #ifndef NO_LISTING
   {
     extern int listing;
@@ -3324,6 +3603,36 @@ c_section_symbol (name, idx)
 
   SF_SET_STATICS (symbolP);
 
+#ifdef TE_PE
+  /* If the .linkonce pseudo-op was used for this section, we must
+     store the information in the auxiliary entry for the section
+     symbol.  */
+  if (segment_info[idx].linkonce != LINKONCE_UNSET)
+    {
+      int type;
+
+      switch (segment_info[idx].linkonce)
+       {
+       default:
+         abort ();
+       case LINKONCE_DISCARD:
+         type = IMAGE_COMDAT_SELECT_ANY;
+         break;
+       case LINKONCE_ONE_ONLY:
+         type = IMAGE_COMDAT_SELECT_NODUPLICATES;
+         break;
+       case LINKONCE_SAME_SIZE:
+         type = IMAGE_COMDAT_SELECT_SAME_SIZE;
+         break;
+       case LINKONCE_SAME_CONTENTS:
+         type = IMAGE_COMDAT_SELECT_EXACT_MATCH;
+         break;
+       }
+
+      SYM_AUXENT (symbolP)->x_scn.x_comdat = type;
+    }
+#endif /* TE_PE */
+
   return symbolP;
 }                              /* c_section_symbol() */
 
@@ -3337,7 +3646,7 @@ w_symbols (abfd, where, symbol_rootP)
   unsigned int i;
 
   /* First fill in those values we have only just worked out */
-  for (i = SEG_E0; i < SEG_E9; i++)
+  for (i = SEG_E0; i < SEG_LAST; i++)
     {
       symbolP = segment_info[i].dot;
       if (symbolP)
@@ -3357,6 +3666,15 @@ w_symbols (abfd, where, symbol_rootP)
               to the string in memory but must be a file offset. */
       register char *temp;
 
+      /* We can't fix the lnnoptr field in yank_symbols with the other
+         adjustments, because we have to wait until we know where they
+         go in the file.  */
+      if (SF_GET_ADJ_LNNOPTR (symbolP))
+       {
+         SA_GET_SYM_LNNOPTR (symbolP) +=
+           segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_lnnoptr;
+       }
+
       tc_coff_symbol_emit_hook (symbolP);
 
       temp = S_GET_NAME (symbolP);
@@ -3456,13 +3774,18 @@ fixup_mdeps (frags, h, this_segment)
       switch (frags->fr_type)
        {
        case rs_align:
+       case rs_align_code:
        case rs_org:
+#ifdef HANDLE_ALIGN
+         HANDLE_ALIGN (frags);
+#endif
          frags->fr_type = rs_fill;
          frags->fr_offset =
-           (frags->fr_next->fr_address - frags->fr_address - frags->fr_fix);
+           ((frags->fr_next->fr_address - frags->fr_address - frags->fr_fix)
+            / frags->fr_var);
          break;
        case rs_machine_dependent:
-         md_convert_frag (h, frags);
+         md_convert_frag (h, this_segment, frags);
          frag_wane (frags);
          break;
        default:
@@ -3473,6 +3796,11 @@ fixup_mdeps (frags, h, this_segment)
 }
 
 #if 1
+
+#ifndef TC_FORCE_RELOCATION
+#define TC_FORCE_RELOCATION(fix) 0
+#endif
+
 static void
 fixup_segment (segP, this_segment_type)
      segment_info_type * segP;
@@ -3481,7 +3809,7 @@ fixup_segment (segP, this_segment_type)
   register fixS * fixP;
   register symbolS *add_symbolP;
   register symbolS *sub_symbolP;
-  register long add_number;
+  long add_number;
   register int size;
   register char *place;
   register long where;
@@ -3520,6 +3848,15 @@ fixup_segment (segP, this_segment_type)
       add_number = fixP->fx_offset;
       pcrel = fixP->fx_pcrel;
 
+      if (add_symbolP != NULL
+         && add_symbolP->sy_mri_common)
+       {
+         know (add_symbolP->sy_value.X_op == O_symbol);
+         add_number += S_GET_VALUE (add_symbolP);
+         fixP->fx_offset = add_number;
+         add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol;
+       }
+
       if (add_symbolP)
        {
          add_symbol_segment = S_GET_SEGMENT (add_symbolP);
@@ -3527,25 +3864,37 @@ fixup_segment (segP, this_segment_type)
 
       if (sub_symbolP)
        {
-         if (!add_symbolP)
+         if (add_symbolP == NULL || add_symbol_segment == absolute_section)
            {
-             /* Its just -sym */
-             if (S_GET_SEGMENT (sub_symbolP) != absolute_section)
+             if (add_symbolP != NULL)
+               {
+                 add_number += S_GET_VALUE (add_symbolP);
+                 add_symbolP = NULL;
+                 fixP->fx_addsy = NULL;
+               }
+
+             /* It's just -sym.  */
+             if (S_GET_SEGMENT (sub_symbolP) == absolute_section)
+               {
+                 add_number -= S_GET_VALUE (sub_symbolP);
+                 fixP->fx_subsy = 0;
+                 fixP->fx_done = 1;
+               }
+             else
                {
+#ifndef TC_M68K
                  as_bad_where (fixP->fx_file, fixP->fx_line,
                                "Negative of non-absolute symbol %s",
                                S_GET_NAME (sub_symbolP));
+#endif
+                 add_number -= S_GET_VALUE (sub_symbolP);
                }               /* not absolute */
 
-             add_number -= S_GET_VALUE (sub_symbolP);
-             fixP->fx_subsy = 0;
-
              /* if sub_symbol is in the same segment that add_symbol
-                          and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
+                and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
            }
-         else if ((S_GET_SEGMENT (sub_symbolP) == add_symbol_segment)
-                  && (SEG_NORMAL (add_symbol_segment)
-                      || (add_symbol_segment == absolute_section)))
+         else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment
+                  && SEG_NORMAL (add_symbol_segment))
            {
              /* Difference of 2 symbols from same segment.  Can't
                 make difference of 2 undefineds: 'value' means
@@ -3561,11 +3910,18 @@ fixup_segment (segP, this_segment_type)
 #endif /* TC_I960 */
              add_number += S_GET_VALUE (add_symbolP) -
                S_GET_VALUE (sub_symbolP);
-
              add_symbolP = NULL;
-             fixP->fx_addsy = NULL;
-             fixP->fx_subsy = NULL;
-             fixP->fx_done = 1;
+
+             if (!TC_FORCE_RELOCATION (fixP))
+               {
+                 fixP->fx_addsy = NULL;
+                 fixP->fx_subsy = NULL;
+                 fixP->fx_done = 1;
+#ifdef TC_M68K /* is this right? */
+                 pcrel = 0;
+                 fixP->fx_pcrel = 0;
+#endif
+               }
            }
          else
            {
@@ -3629,8 +3985,11 @@ fixup_segment (segP, this_segment_type)
              add_number -= segP->scnhdr.s_vaddr;
 #endif
              pcrel = 0;        /* Lie. Don't want further pcrel processing. */
-             fixP->fx_addsy = NULL;
-             fixP->fx_done = 1;
+             if (!TC_FORCE_RELOCATION (fixP))
+               {
+                 fixP->fx_addsy = NULL;
+                 fixP->fx_done = 1;
+               }
            }
          else
            {
@@ -3641,14 +4000,18 @@ fixup_segment (segP, this_segment_type)
                  reloc_callj (fixP);   /* See comment about reloc_callj() above*/
 #endif /* TC_I960 */
                  add_number += S_GET_VALUE (add_symbolP);
-                 fixP->fx_addsy = NULL;
-                 fixP->fx_done = 1;
                  add_symbolP = NULL;
+
+                 if (!TC_FORCE_RELOCATION (fixP))
+                   {
+                     fixP->fx_addsy = NULL;
+                     fixP->fx_done = 1;
+                   }
                  break;
                default:
 
 
-#if defined(TC_A29K) || (defined(TE_PE) && defined(TC_I386))
+#if defined(TC_A29K) || (defined(TE_PE) && defined(TC_I386)) || defined(TC_M88K)
                  /* This really should be handled in the linker, but
                     backward compatibility forbids.  */
                  add_number += S_GET_VALUE (add_symbolP);
@@ -3674,7 +4037,7 @@ fixup_segment (segP, this_segment_type)
                      continue;
                    }           /* COBR */
 #endif /* TC_I960 */
-#if (defined (TC_I386) || defined (TE_LYNX)) && !defined(TE_PE)
+#if (defined (TC_I386) || defined (TE_LYNX) || defined (TE_AUX)) && !defined(TE_PE)
                  /* 386 COFF uses a peculiar format in which the
                     value of a common symbol is stored in the .text
                     segment (I've checked this on SVR3.2 and SCO
@@ -3691,7 +4054,7 @@ fixup_segment (segP, this_segment_type)
 
       if (pcrel)
        {
-#if !defined(TC_M88K) && !(defined(TE_PE) && defined(TC_I386))
+#if !defined(TC_M88K) && !(defined(TE_PE) && defined(TC_I386)) && !defined(TC_A29K)
          /* This adjustment is not correct on the m88k, for which the
             linker does all the computation.  */
          add_number -= md_pcrel_from (fixP);
@@ -3741,7 +4104,11 @@ fixup_segment (segP, this_segment_type)
        }                       /* not a bit fix */
       /* Once this fix has been applied, we don't have to output
         anything nothing more need be done.  */
+#ifdef MD_APPLY_FIX3
+      md_apply_fix3 (fixP, &add_number, this_segment_type);
+#else
       md_apply_fix (fixP, add_number);
+#endif
     }                          /* For each fixS in this segment. */
 }                              /* fixup_segment() */
 
@@ -3763,8 +4130,8 @@ obj_coff_init_stab_section (seg)
   /* Zero it out. */
   memset (p, 0, 12);
   as_where (&file, (unsigned int *) NULL);
-  stabstr_name = (char *) alloca (strlen (segment_info[seg].scnhdr.s_name) + 4);
-  strcpy (stabstr_name, segment_info[seg].scnhdr.s_name);
+  stabstr_name = (char *) alloca (strlen (segment_info[seg].name) + 4);
+  strcpy (stabstr_name, segment_info[seg].name);
   strcat (stabstr_name, "str");
   stroff = get_stab_string_offset (file, stabstr_name);
   know (stroff == 1);
@@ -3779,21 +4146,22 @@ adjust_stab_section(abfd, seg)
      segT seg;
 {
   segT stabstrseg = SEG_UNKNOWN;
-  char *secname, *name, *name2;
+  const char *secname, *name2;
+  char *name;
   char *p = NULL;
   int i, strsz = 0, nsyms;
   fragS *frag = segment_info[seg].frchainP->frch_root;
 
   /* Look for the associated string table section. */
 
-  secname = segment_info[seg].scnhdr.s_name;
+  secname = segment_info[seg].name;
   name = (char *) alloca (strlen (secname) + 4);
   strcpy (name, secname);
   strcat (name, "str");
 
   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
     {
-      name2 = segment_info[i].scnhdr.s_name;
+      name2 = segment_info[i].name;
       if (name2 != NULL && strncmp(name2, name, 8) == 0)
        {
          stabstrseg = i;
@@ -3837,9 +4205,12 @@ const pseudo_typeS obj_pseudo_table[] =
   {"type", obj_coff_type, 0},
   {"val", obj_coff_val, 0},
   {"section", obj_coff_section, 0},
+  {"sect", obj_coff_section, 0},
+  /* FIXME: We ignore the MRI short attribute.  */
+  {"section.s", obj_coff_section, 0},
+  {"sect.s", obj_coff_section, 0},
 #ifndef BFD_ASSEMBLER
   {"use", obj_coff_section, 0},
-  {"sect", obj_coff_section, 0},
   {"text", obj_coff_text, 0},
   {"data", obj_coff_data, 0},
   {"bss", obj_coff_bss, 0},
This page took 0.050409 seconds and 4 git commands to generate.