more vms work from pat
authorKen Raeburn <raeburn@cygnus>
Tue, 25 Jul 1995 00:31:20 +0000 (00:31 +0000)
committerKen Raeburn <raeburn@cygnus>
Tue, 25 Jul 1995 00:31:20 +0000 (00:31 +0000)
gas/config/obj-vms.c

index 9f4810b878e2de203fe07336e8b014ef1aecba7a..72ae2e4c1dae7d96190d06c01b073bf9ed2a3ba0 100644 (file)
@@ -396,6 +396,14 @@ static void VMS_Store_Repeated_Data PARAMS ((int,char *,int,int));
 static void VMS_Store_PIC_Symbol_Reference PARAMS ((symbolS *,int,
                                                    int,int,int,int));
 static void VMS_Fix_Indirect_Reference PARAMS ((int,int,fragS *,fragS *));
+
+/* Support code which used to be inline within vms_write_object_file.  */
+static void vms_fixup_text_section PARAMS ((unsigned,struct frag *,struct frag *));
+static void synthesize_data_segment PARAMS ((unsigned,unsigned,struct frag *));
+static void vms_fixup_data_section PARAMS ((unsigned,unsigned));
+static void global_symbol_directory PARAMS ((unsigned,unsigned));
+static void local_symbols_DST PARAMS ((symbolS *,symbolS *));
+static void vms_build_DST PARAMS ((unsigned));
 \f
 
 /* The following code defines the special types of pseudo-ops that we
@@ -4711,119 +4719,304 @@ vms_check_for_main ()
 }
 \f
 
+/*
+ *     Beginning of vms_write_object_file().
+ */
+
+static
+struct vms_obj_state {
+
+  /* Next program section index to use.  */
+  int  psect_number;
+
+  /* Psect index for code.  Always ends up #0.  */
+  int  text_psect;
+
+  /* Psect index for initialized static variables.  */
+  int  data_psect;
+
+  /* Psect index for uninitialized static variables.  */
+  int  bss_psect;
+
+  /* Number of bytes used for local symbol data.  */
+  int  local_initd_data_size;
+
+  /* Dynamic buffer for initialized data.  */
+  char *data_segment;
+
+} vms_obj_state;
+
+#define Psect_Number           vms_obj_state.psect_number
+#define Text_Psect             vms_obj_state.text_psect
+#define Data_Psect             vms_obj_state.data_psect
+#define Bss_Psect              vms_obj_state.bss_psect
+#define Local_Initd_Data_Size  vms_obj_state.local_initd_data_size
+#define Data_Segment           vms_obj_state.data_segment
+
+
 #define IS_GXX_VTABLE(symP) (strncmp (S_GET_NAME (symP), "__vt.", 5) == 0)
+\f
 
 /*
- *     Write a VAX/VMS object file (everything else has been done!)
+ *     Perform text segment fixups.
  */
-void
-vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
-                      data_frag_root)
+static void
+vms_fixup_text_section (text_siz, text_frag_root, data_frag_root)
      unsigned text_siz;
-     unsigned data_siz;
-     unsigned bss_siz;
-     fragS *text_frag_root;
-     fragS *data_frag_root;
+     struct frag *text_frag_root;
+     struct frag *data_frag_root;
 {
   register fragS *fragP;
-  register symbolS *symbolP;
-  register symbolS *sp;
   register struct fix *fixP;
-  register struct VMS_Symbol *vsp;
-  char *Data_Segment = 0;
-  int Local_Initialized_Data_Size = 0;
-  int Globalref;
-  int Psect_Number = 0;                /* Psect Index Number */
-  int Text_Psect = -1;         /* Text Psect Index   */
-  int Data_Psect = -2;         /* Data Psect Index   JF: Was -1 */
-  int Bss_Psect = -3;          /* Bss Psect Index    JF: Was -1 */
+  offsetT dif;
+
+  /* Scan the text fragments.  */
+  for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
+    {
+      /* Stop if we get to the data fragments.  */
+      if (fragP == data_frag_root)
+       break;
+      /* Ignore fragments with no data.  */
+      if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
+       continue;
+      /* Go the the appropriate offset in the Text Psect.  */
+      VMS_Set_Psect (Text_Psect, fragP->fr_address, OBJ_S_C_TIR);
+      /* Store the "fixed" part.  */
+      if (fragP->fr_fix)
+       VMS_Store_Immediate_Data (fragP->fr_literal,
+                                 fragP->fr_fix,
+                                 OBJ_S_C_TIR);
+      /* Store the "variable" part.  */
+      if (fragP->fr_var && fragP->fr_offset)
+       VMS_Store_Repeated_Data (fragP->fr_offset,
+                                fragP->fr_literal + fragP->fr_fix,
+                                fragP->fr_var,
+                                OBJ_S_C_TIR);
+    }                  /* text frag loop */
 
   /*
-   *   Create the VMS object file
-   */
-  Create_VMS_Object_File ();
-  /*
-   *   Write the module header records
-   */
-  Write_VMS_MHD_Records ();
-\f
-  /*
-   *   Store the Data segment:
-   *
-   *   Since this is REALLY hard to do any other way,
-   *   we actually manufacture the data segment and
-   *   the store the appropriate values out of it.
-   *   We need to generate this early, so that globalvalues
-   *   can be properly emitted.
+   *   Now we go through the text segment fixups and generate
+   *   TIR records to fix up addresses within the Text Psect.
    */
-  if (data_siz > 0)
+  for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
     {
-      /*
-       *       Allocate the data segment
-       */
-      Data_Segment = (char *) xmalloc (data_siz);
-      /*
-       *       Run through the data fragments, filling in the segment
-       */
-      for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
+      /* We DO handle the case of "Symbol - Symbol" as
+        long as it is in the same segment.  */
+      if (fixP->fx_subsy && fixP->fx_addsy)
        {
-         register long int count;
-         register char *fill_literal;
-         register long int fill_size;
-         int i;
-
-         i = fragP->fr_address - text_siz;
-         if (fragP->fr_fix)
-           memcpy (Data_Segment + i,
-                   fragP->fr_literal,
-                   fragP->fr_fix);
-         i += fragP->fr_fix;
+         /* They need to be in the same segment.  */
+         if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
+             S_GET_RAW_TYPE (fixP->fx_addsy))
+           error ("Fixup data addsy and subsy don't have the same type");
+         /* And they need to be in one that we can check the psect on.  */
+         if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
+                   (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
+           error ("Fixup data addsy and subsy don't have an appropriate type");
+         /* This had better not be PC relative!  */
+         if (fixP->fx_pcrel)
+           error ("Fixup data is erroneously \"pcrel\"");
+         /* Subtract their values to get the difference.  */
+         dif = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy);
+         md_number_to_chars (Local, (valueT)dif, fixP->fx_size);
+         /* Now generate the fixup object records;
+            set the psect and store the data.  */
+         VMS_Set_Psect (Text_Psect,
+                        fixP->fx_where + fixP->fx_frag->fr_address,
+                        OBJ_S_C_TIR);
+         VMS_Store_Immediate_Data (Local,
+                                   fixP->fx_size,
+                                   OBJ_S_C_TIR);
+         continue;     /* done with this fixup */
+           }           /* if fx_subsy && fx_addsy */
+      /* Size will HAVE to be "long".  */
+      if (fixP->fx_size != 4)
+       error ("Fixup datum is not a longword");
+      /* Symbol must be "added" (if it is ever
+        subtracted we can fix this assumption).  */
+      if (fixP->fx_addsy == 0)
+       error ("Fixup datum is not \"fixP->fx_addsy\"");
+      /* Store the symbol value in a PIC fashion.  */
+      VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
+                                     fixP->fx_offset,
+                                     fixP->fx_pcrel,
+                                     Text_Psect,
+                                   fixP->fx_where + fixP->fx_frag->fr_address,
+                                     OBJ_S_C_TIR);
+         /*
+          *  Check for indirect address reference, which has to be fixed up
+          *  (as the linker will screw it up with TIR_S_C_STO_PICR)...
+          */
+      if (fixP->fx_pcrel)
+       VMS_Fix_Indirect_Reference (Text_Psect,
+                                   fixP->fx_where + fixP->fx_frag->fr_address,
+                                   fixP->fx_frag,
+                                   text_frag_root);
+    }                  /* text fix loop */
+}
+\f
+
+/*
+ *     Create a buffer holding the data segment.
+ */
+static void
+synthesize_data_segment(data_siz, text_siz, data_frag_root)
+     unsigned data_siz, text_siz;
+     struct frag *data_frag_root;
+{
+  register fragS *fragP;
+  char *fill_literal;
+  long fill_size, count, i;
+
+  /* Allocate the data segment.  */
+  Data_Segment = (char *) xmalloc (data_siz);
+  /* Run through the data fragments, filling in the segment.  */
+  for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
+    {
+      i = fragP->fr_address - text_siz;
+      if (fragP->fr_fix)
+       memcpy (Data_Segment + i, fragP->fr_literal, fragP->fr_fix);
+      i += fragP->fr_fix;
 
+      if ((fill_size = fragP->fr_var) != 0)
+       {
          fill_literal = fragP->fr_literal + fragP->fr_fix;
-         if ((fill_size = fragP->fr_var) != 0)
-           for (count = fragP->fr_offset; count; count--)
-             {
-               memcpy (Data_Segment + i, fill_literal, fill_size);
-               i += fill_size;
-             }
+         for (count = fragP->fr_offset; count; count--)
+           {
+             memcpy (Data_Segment + i, fill_literal, fill_size);
+             i += fill_size;
+           }
        }
-    }
+    }                  /* data frag loop */
 
+  return;
+}
 
-  /*
-   *   Generate the VMS object file records
-   *   1st GSD then TIR records
-   */
+/*
+ *     Perform data segment fixups.
+ */
+static void
+vms_fixup_data_section (data_siz, text_siz)
+     unsigned data_siz, text_siz;
+{
+  register struct VMS_Symbol *vsp;
+  register struct fix *fixP;
+  register symbolS *sp;
+  addressT fr_address;
+  offsetT dif;
+  valueT val;
 
-  /*******       Global Symbol Dictionary       *******/
-  /*
-   * Emit globalvalues now.  We must do this before the text psect
-   * is defined, or we will get linker warnings about multiply defined
-   * symbols.  All of the globalvalues "reference" psect 0, although
-   * it really does not have anything to do with it.
-   */
-  VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment);
-  /*
-   *   Define the Text Psect
-   */
-  Text_Psect = Psect_Number++;
-  VMS_Psect_Spec ("$code", text_siz, "TEXT", 0);
-  /*
-   *   Define the BSS Psect
-   */
-  if (bss_siz > 0)
+  /* Run through all the data symbols and store the data.  */
+  for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
     {
-      Bss_Psect = Psect_Number++;
-      VMS_Psect_Spec ("$uninitialized_data", bss_siz, "DATA", 0);
-    }
+      /* Ignore anything other than data symbols.  */
+      if (S_GET_TYPE (vsp->Symbol) != N_DATA)
+       continue;
+      /* Set the Psect + Offset.  */
+      VMS_Set_Psect (vsp->Psect_Index,
+                      vsp->Psect_Offset,
+                      OBJ_S_C_TIR);
+      /* Store the data.  */
+      val = S_GET_VALUE (vsp->Symbol);
+      VMS_Store_Immediate_Data (Data_Segment + val - text_siz,
+                               vsp->Size,
+                               OBJ_S_C_TIR);
+    }                  /* N_DATA symbol loop */
+
+  /*
+   *   Now we go through the data segment fixups and generate
+   *   TIR records to fix up addresses within the Data Psects.
+   */
+  for (fixP = data_fix_root; fixP; fixP = fixP->fx_next)
+    {
+      /* Find the symbol for the containing datum.  */
+      for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
+       {
+         /* Only bother with Data symbols.  */
+         sp = vsp->Symbol;
+         if (S_GET_TYPE (sp) != N_DATA)
+           continue;
+         /* Ignore symbol if After fixup.  */
+         val = S_GET_VALUE (sp);
+         fr_address = fixP->fx_frag->fr_address;
+         if (val > fixP->fx_where + fr_address)
+           continue;
+         /* See if the datum is here.  */
+         if (val + vsp->Size <= fixP->fx_where + fr_address)
+           continue;
+         /* We DO handle the case of "Symbol - Symbol" as
+            long as it is in the same segment.  */
+         if (fixP->fx_subsy && fixP->fx_addsy)
+           {
+             /* They need to be in the same segment.  */
+             if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
+                 S_GET_RAW_TYPE (fixP->fx_addsy))
+               error ("Fixup data addsy and subsy don't have the same type");
+             /* And they need to be in one that we can check the psect on.  */
+             if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
+                 (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
+               error ("Fixup data addsy and subsy don't have an appropriate type");
+             /* This had better not be PC relative!  */
+             if (fixP->fx_pcrel)
+               error ("Fixup data is erroneously \"pcrel\"");
+             /* Subtract their values to get the difference.  */
+             dif = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy);
+             md_number_to_chars (Local, (valueT)dif, fixP->fx_size);
+             /*
+              * Now generate the fixup object records;
+              * set the psect and store the data.
+              */
+             VMS_Set_Psect (vsp->Psect_Index,
+                            fr_address + fixP->fx_where
+                                - val + vsp->Psect_Offset,
+                            OBJ_S_C_TIR);
+             VMS_Store_Immediate_Data (Local,
+                                       fixP->fx_size,
+                                       OBJ_S_C_TIR);
+                 break;        /* done with this fixup */
+               }
+         /* Size will HAVE to be "long".  */
+         if (fixP->fx_size != 4)
+           error ("Fixup datum is not a longword");
+         /* Symbol must be "added" (if it is ever
+            subtracted we can fix this assumption).  */
+         if (fixP->fx_addsy == 0)
+           error ("Fixup datum is not \"fixP->fx_addsy\"");
+         /* Store the symbol value in a PIC fashion.  */
+         VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
+                                         fixP->fx_offset,
+                                         fixP->fx_pcrel,
+                                         vsp->Psect_Index,
+                                         fr_address + fixP->fx_where
+                                             - val + vsp->Psect_Offset,
+                                         OBJ_S_C_TIR);
+         /* Done with this fixup.  */
+         break;
+       }               /* vms_symbol loop */
+
+    }                  /* data fix loop */
+}
+\f
+
+/*
+ *     Define symbols for the linker.
+ */
+static void
+global_symbol_directory (text_siz, data_siz)
+     unsigned text_siz, data_siz;
+{
+  register fragS *fragP;
+  register symbolS *sp;
+  register struct VMS_Symbol *vsp;
+  int Globalref, define_as_global_symbol;
+
 #ifndef gxx_bug_fixed
-  /* 
+  /*
    * The g++ compiler does not write out external references to vtables
    * correctly.  Check for this and holler if we see it happening.
    * If that compiler bug is ever fixed we can remove this.
    * (Jun'95:  gcc 2.7.0's cc1plus still exhibits this behavior.)
    */
-  for (sp = symbol_rootP; sp; sp = symbol_next (sp)) 
+  for (sp = symbol_rootP; sp; sp = symbol_next (sp))
     if (S_GET_RAW_TYPE (sp) == N_UNDF && IS_GXX_VTABLE (sp))
       {
        S_SET_TYPE (sp, N_UNDF | N_EXT);
@@ -4833,24 +5026,21 @@ vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
                 "I will fix it, but I hope that it was not really a routine.");
       }
 #endif /* gxx_bug_fixed */
+
   /*
-   *   Now scan the symbols and emit the appropriate GSD records
+   * Now scan the symbols and emit the appropriate GSD records
    */
   for (sp = symbol_rootP; sp; sp = symbol_next (sp))
     {
-      /*
-       *       Dispatch on symbol type
-       */
+      define_as_global_symbol = 0;
+      /* Dispatch on symbol type.  */
       switch (S_GET_RAW_TYPE (sp))
        {
-         /*
-          *    Global uninitialized data
-          */
+
+       /* Global uninitialized data.  */
        case N_UNDF | N_EXT:
-         /*
-          *    Make a VMS data symbol entry
-          */
-         vsp = (struct VMS_Symbol *) xmalloc (sizeof (*vsp));
+         /* Make a VMS data symbol entry.  */
+         vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
          vsp->Symbol = sp;
          vsp->Size = S_GET_VALUE (sp);
          vsp->Psect_Index = Psect_Number++;
@@ -4858,46 +5048,29 @@ vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
          vsp->Next = VMS_Symbols;
          VMS_Symbols = vsp;
          sp->sy_obj = vsp;
-         /*
-          *    Make the psect for this data
-          */
+         /* Make the psect for this data.  */
          Globalref = VMS_Psect_Spec (S_GET_NAME (sp),
                                      vsp->Size,
                                      S_GET_OTHER (sp) ? "CONST" : "COMMON",
                                      vsp);
          if (Globalref)
            Psect_Number--;
-
-/* See if this is an external vtable.  We want to help the linker find
-   these things in libraries, so we make a symbol reference.  This
-   is not compatible with VAX-C usage for variables, but since vtables are
-   only used internally by g++, we can get away with this hack.  */
-
-         if (IS_GXX_VTABLE (sp))
-           VMS_Global_Symbol_Spec (S_GET_NAME(sp),
-                                   vsp->Psect_Index,
-                                   0,
-                                   GBLSYM_REF);
-
 #ifdef NOT_VAX_11_C_COMPATIBLE
-         /*
-          *    Place a global symbol at the
-          *    beginning of the Psect
-          */
-         VMS_Global_Symbol_Spec (S_GET_NAME (sp),
-                                 vsp->Psect_Index,
-                                 0,
-                                 GBLSYM_DEF);
-#endif /* NOT_VAX_11_C_COMPATIBLE */
+         define_as_global_symbol = 1;
+#else
+         /* See if this is an external vtable.  We want to help the
+            linker find these things in libraries, so we make a symbol
+            reference.  This is not compatible with VAX-C usage for
+            variables, but since vtables are only used internally by
+            g++, we can get away with this hack.  */
+         define_as_global_symbol = IS_GXX_VTABLE (sp);
+#endif
          break;
-         /*
-          *    Local uninitialized data
-          */
+
+       /* Local uninitialized data.  */
        case N_BSS:
-         /*
-          *    Make a VMS data symbol entry
-          */
-         vsp = (struct VMS_Symbol *) xmalloc (sizeof (*vsp));
+         /* Make a VMS data symbol entry.  */
+         vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
          vsp->Symbol = sp;
          vsp->Size = 0;
          vsp->Psect_Index = Bss_Psect;
@@ -4906,14 +5079,11 @@ vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
          VMS_Symbols = vsp;
          sp->sy_obj = vsp;
          break;
-         /*
-          *    Global initialized data
-          */
+
+       /* Global initialized data.  */
        case N_DATA | N_EXT:
-         /*
-          *    Make a VMS data symbol entry
-          */
-         vsp = (struct VMS_Symbol *) xmalloc (sizeof (*vsp));
+         /* Make a VMS data symbol entry.  */
+         vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
          vsp->Symbol = sp;
          vsp->Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
          vsp->Psect_Index = Psect_Number++;
@@ -4921,41 +5091,22 @@ vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
          vsp->Next = VMS_Symbols;
          VMS_Symbols = vsp;
          sp->sy_obj = vsp;
-         /*
-          *    Make its psect
-          */
+         /* Make its psect.  */
          Globalref = VMS_Psect_Spec (S_GET_NAME (sp),
                                      vsp->Size,
                                      S_GET_OTHER (sp) ? "CONST" : "COMMON",
                                      vsp);
          if (Globalref)
            Psect_Number--;
-
-/* See if this is an external vtable.  We want to help the linker find
-   these things in libraries, so we make a symbol definition.  This
-   is not compatible with VAX-C usage for variables, but since vtables are
-   only used internally by g++, we can get away with this hack.  */
-
-         if (IS_GXX_VTABLE (sp))
-           VMS_Global_Symbol_Spec (S_GET_NAME (sp),
-                                   vsp->Psect_Index,
-                                   0,
-                                   GBLSYM_DEF);
-
 #ifdef NOT_VAX_11_C_COMPATIBLE
-         /*
-          *    Place a global symbol at the
-          *    beginning of the Psect
-          */
-         VMS_Global_Symbol_Spec (S_GET_NAME (sp),
-                                 vsp->Psect_Index,
-                                 0,
-                                 GBLSYM_DEF);
-#endif /* NOT_VAX_11_C_COMPATIBLE */
+         define_as_global_symbol = 1;
+#else
+         /* See N_UNDF|N_EXT above for explanation.  */
+         define_as_global_symbol = IS_GXX_VTABLE (sp);
+#endif
          break;
-         /*
-          *    Local initialized data
-          */
+
+       /* Local initialized data.  */
        case N_DATA:
          {
            char *sym_name = S_GET_NAME (sp);
@@ -4963,31 +5114,26 @@ vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
            /* Always suppress local numeric labels.  */
            if (!sym_name || strcmp (sym_name, FAKE_LABEL_NAME) != 0)
              {
-               /*
-                *      Make a VMS data symbol entry.
-                */
-               vsp = (struct VMS_Symbol *) xmalloc (sizeof (*vsp));
+               /* Make a VMS data symbol entry.  */
+               vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
                vsp->Symbol = sp;
                vsp->Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
                vsp->Psect_Index = Data_Psect;
-               vsp->Psect_Offset = Local_Initialized_Data_Size;
-               Local_Initialized_Data_Size += vsp->Size;
+               vsp->Psect_Offset = Local_Initd_Data_Size;
+               Local_Initd_Data_Size += vsp->Size;
                vsp->Next = VMS_Symbols;
                VMS_Symbols = vsp;
                sp->sy_obj = vsp;
              }
          }
          break;
-         /*
-          *    Global Text definition
-          */
+
+       /* Global Text definition.  */
        case N_TEXT | N_EXT:
          {
            unsigned short Entry_Mask;
 
-           /*
-            *  Get the entry mask
-            */
+           /* Get the entry mask.  */
            fragP = sp->sy_frag;
            /* First frag might be empty if we're generating listings.
               So skip empty rs_fill frags.  */
@@ -5007,25 +5153,20 @@ vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
 
            Entry_Mask = (fragP->fr_literal[0] & 0x00ff) |
                         ((fragP->fr_literal[1] & 0x00ff) << 8);
-           /*
-            *  Define the procedure entry point.
-            */
+           /* Define the procedure entry point.  */
            VMS_Procedure_Entry_Pt (S_GET_NAME (sp),
                                    Text_Psect,
                                    S_GET_VALUE (sp),
                                    Entry_Mask);
            break;
          }
-         /*
-          *    Local Text definition
-          */
+
+       /* Local Text definition.  */
        case N_TEXT:
-         /*
-          *    Make a VMS data symbol entry
-          */
+         /* Make a VMS data symbol entry.  */
          if (Text_Psect != -1)
            {
-             vsp = (struct VMS_Symbol *) xmalloc (sizeof (*vsp));
+             vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
              vsp->Symbol = sp;
              vsp->Size = 0;
              vsp->Psect_Index = Text_Psect;
@@ -5035,29 +5176,22 @@ vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
              sp->sy_obj = vsp;
            }
          break;
-         /*
-          *    Global Reference
-          */
+
+       /* Global Reference.  */
        case N_UNDF:
-         /*
-          *    Make a GSD global symbol reference
-          *    record.
-          */
+         /* Make a GSD global symbol reference record.  */
          VMS_Global_Symbol_Spec (S_GET_NAME (sp),
                                  0,
                                  0,
                                  GBLSYM_REF);
          break;
-         /*
-          *    Absolute symbol
-          */
+
+       /* Absolute symbol.  */
        case N_ABS:
        case N_ABS | N_EXT:
-         /*
-          *    gcc doesn't generate these;
-          *    VMS_Emit_Globalvalue handles them though.
-          */
-         vsp = (struct VMS_Symbol *) xmalloc (sizeof (*vsp));
+         /* gcc doesn't generate these;
+            VMS_Emit_Globalvalue handles them though.  */
+         vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
          vsp->Symbol = sp;
          vsp->Size = 4;                /* always assume 32 bits */
          vsp->Psect_Index = 0;
@@ -5066,13 +5200,10 @@ vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
          VMS_Symbols = vsp;
          sp->sy_obj = vsp;
          break;
-         /*
-          *    Anything else
-          */
+
+       /* Anything else.  */
        default:
-         /*
-          *    Ignore STAB symbols, including .stabs emitted by g++.
-          */
+         /* Ignore STAB symbols, including .stabs emitted by g++.  */
          if (S_IS_DEBUG (sp) || (S_GET_TYPE (sp) == 22))
            break;
          /*
@@ -5081,652 +5212,452 @@ vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
          as_tsktsk ("unhandled stab type %d", S_GET_TYPE (sp));
          break;
        }
+
+      /* Global symbols have different linkage than external variables.  */
+      if (define_as_global_symbol)
+       VMS_Global_Symbol_Spec (S_GET_NAME (sp),
+                               vsp->Psect_Index,
+                               0,
+                               GBLSYM_DEF);
+    }
+
+  return;
+}
+\f
+
+/*
+ *     Output debugger symbol table information for symbols which
+ *     are local to a specific routine.
+ */
+static void
+local_symbols_DST (s0P, Current_Routine)
+     symbolS *s0P, *Current_Routine;
+{
+  symbolS *s1P;
+  char *s0P_name, *pnt0, *pnt1;
+
+  s0P_name = S_GET_NAME (s0P);
+  if (*++s0P_name != '_')
+    return;
+
+  for (s1P = Current_Routine; s1P; s1P = symbol_next (s1P))
+    {
+#if 0          /* redundant; RAW_TYPE != N_FUN suffices */
+      if (!S_IS_DEBUG (s1P))
+       continue;
+#endif
+      if (S_GET_RAW_TYPE (s1P) != N_FUN)
+       continue;
+      pnt0 = s0P_name;
+      pnt1 = S_GET_NAME (s1P);
+      /* We assume the two strings are never exactly equal...  */
+      while (*pnt0++ == *pnt1++)
+       {
+       }
+      /* Found it if s0P name is exhausted and s1P name has ":F" or ":f" next.
+        Note:  both pointers have advanced one past the non-matching char.  */
+      if ((*pnt1 == 'F' || *pnt1 == 'f') && *--pnt1 == ':' && *--pnt0 == '\0')
+       {
+         Define_Routine (s1P, 0, Current_Routine, Text_Psect);
+         return;
+       }
     }
+}
+
+/*
+ *     Construct and output the debug symbol table.
+ */
+static void
+vms_build_DST (text_siz)
+     unsigned text_siz;
+{
+  register symbolS *symbolP;
+  symbolS *Current_Routine = 0;
+  struct input_file *Cur_File = 0;
+  offsetT Cur_Offset = -1;
+  int Cur_Line_Number = 0;
+  int File_Number = 0;
+  int Debugger_Offset = 0;
+  int file_available;
+  int dsc;
+  offsetT val;
+
   /*
-   *   Define the Data Psect
+   *   Write the Traceback Begin Module record
+   */
+  VMS_TBT_Module_Begin ();
+
+  /*
+   *   Output debugging info for global variables and static variables
+   *   that are not specific to one routine.  We also need to examine
+   *   all stabs directives, to find the definitions to all of the
+   *   advanced data types, and this is done by VMS_LSYM_Parse.  This
+   *   needs to be done before any definitions are output to the object
+   *   file, since there can be forward references in the stabs
+   *   directives.  When through with parsing, the text of the stabs
+   *   directive is altered, with the definitions removed, so that later
+   *   passes will see directives as they would be written if the type
+   *   were already defined.
+   *
+   *   We also look for files and include files, and make a list of
+   *   them.  We examine the source file numbers to establish the actual
+   *   lines that code was generated from, and then generate offsets.
    */
-  if ((data_siz > 0) && (Local_Initialized_Data_Size > 0))
+  VMS_LSYM_Parse ();
+  for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
     {
+      /* Only deal with STAB symbols here.  */
+      if (!S_IS_DEBUG (symbolP))
+       continue;
       /*
-       *       Do it
-       */
-      Data_Psect = Psect_Number++;
-      VMS_Psect_Spec ("$data",
-                     Local_Initialized_Data_Size,
-                     "DATA", 0);
-      /*
-       *       Scan the VMS symbols and fill in the data psect
+       *       Dispatch on STAB type.
        */
-      for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
+      switch (S_GET_RAW_TYPE (symbolP))
        {
-         /*
-          *    Only look for undefined psects
-          */
-         if (vsp->Psect_Index < 0)
+       case N_SLINE:
+         dsc = S_GET_DESC (symbolP);
+         if (dsc > Cur_File->max_line)
+           Cur_File->max_line = dsc;
+         if (dsc < Cur_File->min_line)
+           Cur_File->min_line = dsc;
+         break;
+       case N_SO:
+         Cur_File = find_file (symbolP);
+         Cur_File->flag = 1;
+         Cur_File->min_line = 1;
+         break;
+       case N_SOL:
+         Cur_File = find_file (symbolP);
+         break;
+       case N_GSYM:
+         VMS_GSYM_Parse (symbolP, Text_Psect);
+         break;
+       case N_LCSYM:
+         VMS_LCSYM_Parse (symbolP, Text_Psect);
+         break;
+       case N_FUN:             /* For static constant symbols */
+       case N_STSYM:
+         VMS_STSYM_Parse (symbolP, Text_Psect);
+         break;
+       default:
+         break;
+       }               /* switch */
+    }                  /* for */
+
+  /*
+   *   Now we take a quick sweep through the files and assign offsets
+   *   to each one.  This will essentially be the starting line number to
+   *   the debugger for each file.  Output the info for the debugger to
+   *   specify the files, and then tell it how many lines to use.
+   */
+  for (Cur_File = file_root; Cur_File; Cur_File = Cur_File->next)
+    {
+      if (Cur_File->max_line == 0)
+       continue;
+      if ((strncmp (Cur_File->name, "GNU_GXX_INCLUDE:", 16) == 0) &&
+         !flag_debug)
+       continue;
+      if ((strncmp (Cur_File->name, "GNU_CC_INCLUDE:", 15) == 0) &&
+         !flag_debug)
+       continue;
+      /* show a few extra lines at the start of the region selected */
+      if (Cur_File->min_line > 2)
+       Cur_File->min_line -= 2;
+      Cur_File->offset = Debugger_Offset - Cur_File->min_line + 1;
+      Debugger_Offset += Cur_File->max_line - Cur_File->min_line + 1;
+      if (Cur_File->same_file_fpnt)
+       {
+         Cur_File->file_number = Cur_File->same_file_fpnt->file_number;
+       }
+      else
+       {
+         Cur_File->file_number = ++File_Number;
+         file_available = VMS_TBT_Source_File (Cur_File->name,
+                                               Cur_File->file_number);
+         if (!file_available)
            {
-             /*
-              *        And only initialized data
-              */
-             if (S_GET_TYPE (vsp->Symbol) == N_DATA
-                 && !S_IS_EXTERNAL (vsp->Symbol))
-               vsp->Psect_Index = Data_Psect;
+             Cur_File->file_number = 0;
+             File_Number--;
+             continue;
            }
        }
-    }
-\f
-  /*******  Text Information and Relocation Records  *******/
+      VMS_TBT_Source_Lines (Cur_File->file_number,
+                           Cur_File->min_line,
+                           Cur_File->max_line - Cur_File->min_line + 1);
+  }                    /* for */
+  Cur_File = (struct input_file *) NULL;
+
   /*
-   *   Write the text segment data
+   *   Scan the symbols and write out the routines
+   *   (this makes the assumption that symbols are in
+   *    order of ascending text segment offset)
    */
-  if (text_siz > 0)
+  for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
     {
       /*
-       *       Scan the text fragments
+       *       Deal with text symbols.
        */
-      for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
+      if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT)
        {
          /*
-          *    Stop if we get to the data fragments
-          */
-         if (fragP == data_frag_root)
-           break;
-         /*
-          *    Ignore fragments with no data
+          * Ignore symbols starting with "L", as they are local symbols.
           */
-         if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
+         if (*S_GET_NAME (symbolP) == 'L')
            continue;
          /*
-          *    Go the the appropriate offset in the
-          *    Text Psect.
-          */
-         VMS_Set_Psect (Text_Psect, fragP->fr_address, OBJ_S_C_TIR);
-         /*
-          *    Store the "fixed" part
-          */
-         if (fragP->fr_fix)
-           VMS_Store_Immediate_Data (fragP->fr_literal,
-                                     fragP->fr_fix,
-                                     OBJ_S_C_TIR);
-         /*
-          *    Store the "variable" part
+          * If there is a routine start defined, terminate it.
           */
-         if (fragP->fr_var && fragP->fr_offset)
-           VMS_Store_Repeated_Data (fragP->fr_offset,
-                                    fragP->fr_literal +
-                                    fragP->fr_fix,
-                                    fragP->fr_var,
-                                    OBJ_S_C_TIR);
-       }
-      /*
-       *       Now we go through the text segment fixups and
-       *       generate TIR records to fix up addresses within
-       *       the Text Psect
-       */
-      for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
-       {
-         /*
-          *    We DO handle the case of "Symbol - Symbol" as
-          *    long as it is in the same segment.
-          */
-         if (fixP->fx_subsy && fixP->fx_addsy)
-           {
-             offsetT dif;
+         if (Current_Routine)
+           VMS_TBT_Routine_End (text_siz, Current_Routine);
 
-             /*
-              *        They need to be in the same segment
-              */
-             if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
-                 S_GET_RAW_TYPE (fixP->fx_addsy))
-               error ("Fixup data addsy and subsy didn't have the same type");
-             /*
-              *        And they need to be in one that we
-              *        can check the psect on
-              */
-             if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
-                 (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
-               error ("Fixup data addsy and subsy didn't have an appropriate type");
-             /*
-              *        This had better not be PC relative!
-              */
-             if (fixP->fx_pcrel)
-               error ("Fixup data was erroneously \"pcrel\"");
-             /*
-              *        Subtract their values to get the
-              *        difference.
-              */
-             dif = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy);
-             md_number_to_chars (Local, (valueT) dif, fixP->fx_size);
-             /*
-              *        Now generate the fixup object records
-              *        Set the psect and store the data
-              */
-             VMS_Set_Psect (Text_Psect,
-                            fixP->fx_where + fixP->fx_frag->fr_address,
-                            OBJ_S_C_TIR);
-             VMS_Store_Immediate_Data (Local,
-                                       fixP->fx_size,
-                                       OBJ_S_C_TIR);
-             /*
-              *        Done
-              */
-             continue;
-           }
          /*
-          *    Size will HAVE to be "long"
+          * Check for & skip dummy labels like "gcc_compiled.".
+          * They're identified by the IN_DEFAULT_SECTION flag.
           */
-         if (fixP->fx_size != 4)
-           error ("Fixup datum was not a longword");
+         if ((S_GET_OTHER (symbolP) & IN_DEFAULT_SECTION) != 0 &&
+             S_GET_VALUE (symbolP) == 0)
+           continue;
          /*
-          *    Symbol must be "added" (if it is ever
-          *                            subtracted we can
-          *                            fix this assumption)
+          * Store the routine begin traceback info.
           */
-         if (fixP->fx_addsy == 0)
-           error ("Fixup datum was not \"fixP->fx_addsy\"");
+         VMS_TBT_Routine_Begin (symbolP, Text_Psect);
+         Current_Routine = symbolP;
          /*
-          *    Store the symbol value in a PIC fashion
+          * Define symbols local to this routine.
           */
-         VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
-                                         fixP->fx_offset,
-                                         fixP->fx_pcrel,
-                                         Text_Psect,
-                                         fixP->fx_where +
-                                         fixP->fx_frag->fr_address,
-                                         OBJ_S_C_TIR);
+         local_symbols_DST (symbolP, Current_Routine);
          /*
-          *    Check for indirect address reference,
-          *    which has to be fixed up (as the linker
-          *    will screw it up with TIR_S_C_STO_PICR).
+          *    Done
           */
-         if (fixP->fx_pcrel)
-           VMS_Fix_Indirect_Reference (Text_Psect,
-                                       fixP->fx_where +
-                                       fixP->fx_frag->fr_address,
-                                       fixP->fx_frag,
-                                       text_frag_root);
-       }
-    }
-  /*
-   *   Store the Data segment:
-   *
-   *   Since this is REALLY hard to do any other way,
-   *   we actually manufacture the data segment and
-   *   the store the appropriate values out of it.
-   *   The segment was manufactured before, now we just
-   *   dump it into the appropriate psects.
-   */
-  if (data_siz > 0)
-    {
+         continue;
 
-      /*
-       *       Now we can run through all the data symbols
-       *       and store the data
-       */
-      for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
-       {
-         /*
-          *    Ignore anything other than data symbols
-          */
-         if (S_GET_TYPE (vsp->Symbol) != N_DATA)
-           continue;
-         /*
-          *    Set the Psect + Offset
-          */
-         VMS_Set_Psect (vsp->Psect_Index,
-                        vsp->Psect_Offset,
-                        OBJ_S_C_TIR);
-         /*
-          *    Store the data
-          */
-         VMS_Store_Immediate_Data (
-                         Data_Segment + S_GET_VALUE (vsp->Symbol) - text_siz,
-                                   vsp->Size,
-                                   OBJ_S_C_TIR);
        }
       /*
-       *       Now we go through the data segment fixups and
-       *       generate TIR records to fix up addresses within
-       *       the Data Psects
+       *       Deal with STAB symbols.
        */
-      for (fixP = data_fix_root; fixP; fixP = fixP->fx_next)
+      else if (S_IS_DEBUG (symbolP))
        {
          /*
-          *    Find the symbol for the containing datum
+          *  Dispatch on STAB type.
           */
-         for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
+         switch (S_GET_RAW_TYPE (symbolP))
            {
+               /*
+                *      Line number
+                */
+           case N_SLINE:
+             /* Offset the line into the correct portion of the file.  */
+             if (Cur_File->file_number == 0)
+               break;
+             val = S_GET_VALUE (symbolP);
+             /* Sometimes the same offset gets several source lines
+                assigned to it.  We should be selective about which
+                lines we allow, we should prefer lines that are in
+                the main source file when debugging inline functions.  */
+             if (val == Cur_Offset && Cur_File->file_number != 1)
+               break;
+
+             /* calculate actual debugger source line */
+             dsc = S_GET_DESC (symbolP) + Cur_File->offset;
+             S_SET_DESC (symbolP, dsc);
              /*
-              *        Only bother with Data symbols
-              */
-             sp = vsp->Symbol;
-             if (S_GET_TYPE (sp) != N_DATA)
-               continue;
-             /*
-              *        Ignore symbol if After fixup
-              */
-             if (S_GET_VALUE (sp) >
-                 (fixP->fx_where +
-                  fixP->fx_frag->fr_address))
-               continue;
-             /*
-              *        See if the datum is here
-              */
-             if ((S_GET_VALUE (sp) + vsp->Size) <=
-                 (fixP->fx_where +
-                  fixP->fx_frag->fr_address))
-               continue;
-             /*
-              *        We DO handle the case of "Symbol - Symbol" as
-              *        long as it is in the same segment.
+              * Define PC/Line correlation.
               */
-             if (fixP->fx_subsy && fixP->fx_addsy)
+             if (Cur_Offset == -1)
                {
-                 offsetT dif;
-
-                 /*
-                  *    They need to be in the same segment
-                  */
-                 if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
-                     S_GET_RAW_TYPE (fixP->fx_addsy))
-                   error ("Fixup data addsy and subsy didn't have the same type");
                  /*
-                  *    And they need to be in one that we
-                  *    can check the psect on
+                  * First N_SLINE; set up initial correlation.
                   */
-                 if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
-                     (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
-                   error ("Fixup data addsy and subsy didn't have an appropriate type");
-                 /*
-                  *    This had better not be PC relative!
-                  */
-                 if (fixP->fx_pcrel)
-                   error ("Fixup data was erroneously \"pcrel\"");
-                 /*
-                  *    Subtract their values to get the
-                  *    difference.
-                  */
-                 dif = S_GET_VALUE (fixP->fx_addsy) -
-                      S_GET_VALUE (fixP->fx_subsy);
-                 md_number_to_chars (Local, (valueT) dif, fixP->fx_size);
+                 VMS_TBT_Line_PC_Correlation (dsc,
+                                              val,
+                                              Text_Psect,
+                                              0);
+               }
+             else if ((dsc - Cur_Line_Number) <= 0)
+               {
                  /*
-                  *    Now generate the fixup object records
-                  *    Set the psect and store the data
+                  * Line delta is not +ve, we need to close the line and
+                  * start a new PC/Line correlation.
                   */
-                 VMS_Set_Psect (vsp->Psect_Index,
-                                fixP->fx_frag->fr_address +
-                                fixP->fx_where -
-                                S_GET_VALUE (vsp->Symbol) +
-                                vsp->Psect_Offset,
-                                OBJ_S_C_TIR);
-                 VMS_Store_Immediate_Data (Local,
-                                           fixP->fx_size,
-                                           OBJ_S_C_TIR);
+                 VMS_TBT_Line_PC_Correlation (0,
+                                              val - Cur_Offset,
+                                              0,
+                                              -1);
+                 VMS_TBT_Line_PC_Correlation (dsc,
+                                              val,
+                                              Text_Psect,
+                                              0);
+               }
+             else
+               {
                  /*
-                  *    Done
+                  * Line delta is +ve, all is well.
                   */
-                 break;
+                 VMS_TBT_Line_PC_Correlation (dsc - Cur_Line_Number,
+                                              val - Cur_Offset,
+                                              0,
+                                              1);
                }
-             /*
-              *        Size will HAVE to be "long"
-              */
-             if (fixP->fx_size != 4)
-               error ("Fixup datum was not a longword");
-             /*
-              *        Symbol must be "added" (if it is ever
-              *                                subtracted we can
-              *                                fix this assumption)
-              */
-             if (fixP->fx_addsy == 0)
-               error ("Fixup datum was not \"fixP->fx_addsy\"");
-             /*
-              *        Store the symbol value in a PIC fashion
-              */
-             VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
-                                             fixP->fx_offset,
-                                             fixP->fx_pcrel,
-                                             vsp->Psect_Index,
-                                             fixP->fx_frag->fr_address +
-                                             fixP->fx_where -
-                                             S_GET_VALUE (vsp->Symbol) +
-                                             vsp->Psect_Offset,
-                                             OBJ_S_C_TIR);
-             /*
-              *        Done
-              */
+             /* Update the current line/PC info.  */
+             Cur_Line_Number = dsc;
+             Cur_Offset = val;
              break;
-           }
-
-       }
-    }
-\f
-  /*
-   *   Write the Traceback Begin Module record
-   */
-  VMS_TBT_Module_Begin ();
-  /*
-   *   Scan the symbols and write out the routines
-   *   (this makes the assumption that symbols are in
-   *    order of ascending text segment offset)
-   */
-  {
-    symbolS *Current_Routine = 0;
-    int Current_Line_Number = 0;
-    int Current_Offset = -1;
-    struct input_file *Current_File = 0;
-
-/* Output debugging info for global variables and static variables that are not
- * specific to one routine. We also need to examine all stabs directives, to
- * find the definitions to all of the advanced data types, and this is done by
- * VMS_LSYM_Parse.  This needs to be done before any definitions are output to
- * the object file, since there can be forward references in the stabs
- * directives. When through with parsing, the text of the stabs directive
- * is altered, with the definitions removed, so that later passes will see
- * directives as they would be written if the type were already defined.
- *
- * We also look for files and include files, and make a list of them.  We
- * examine the source file numbers to establish the actual lines that code was
- * generated from, and then generate offsets.
- */
-    VMS_LSYM_Parse ();
-    for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
-      {
-       /*
-        *      Deal with STAB symbols
-        */
-       if (S_IS_DEBUG (symbolP))
-         {
-           /*
-            *  Dispatch on STAB type
-            */
-           switch ((unsigned char) S_GET_RAW_TYPE (symbolP))
-             {
-             case N_SLINE:
-               if (S_GET_DESC (symbolP) > Current_File->max_line)
-                 Current_File->max_line = S_GET_DESC (symbolP);
-               if (S_GET_DESC (symbolP) < Current_File->min_line)
-                 Current_File->min_line = S_GET_DESC (symbolP);
-               break;
-             case N_SO:
-               Current_File = find_file (symbolP);
-               Current_File->flag = 1;
-               Current_File->min_line = 1;
-               break;
-             case N_SOL:
-               Current_File = find_file (symbolP);
-               break;
-             case N_GSYM:
-               VMS_GSYM_Parse (symbolP, Text_Psect);
-               break;
-             case N_LCSYM:
-               VMS_LCSYM_Parse (symbolP, Text_Psect);
-               break;
-             case N_FUN:       /* For static constant symbols */
-             case N_STSYM:
-               VMS_STSYM_Parse (symbolP, Text_Psect);
-               break;
-             }
-         }
-      }
 
-    /* Now we take a quick sweep through the files and assign offsets
-       to each one.  This will essentially be the starting line number to
-       the debugger for each file.  Output the info for the debugger to
-       specify the files, and then tell it how many lines to use.  */
-    {
-      int File_Number = 0;
-      int Debugger_Offset = 0;
-      int file_available;
-      Current_File = file_root;
-      for (Current_File = file_root; Current_File;
-          Current_File = Current_File->next)
-       {
-         if (Current_File == (struct input_file *) NULL)
-           break;
-         if (Current_File->max_line == 0)
-           continue;
-         if ((strncmp (Current_File->name, "GNU_GXX_INCLUDE:", 16) == 0) &&
-             !flag_debug)
-           continue;
-         if ((strncmp (Current_File->name, "GNU_CC_INCLUDE:", 15) == 0) &&
-             !flag_debug)
-           continue;
-/* show a few extra lines at the start of the region selected */
-         if (Current_File->min_line > 2)
-           Current_File->min_line -= 2;
-         Current_File->offset = Debugger_Offset - Current_File->min_line + 1;
-         Debugger_Offset += Current_File->max_line - Current_File->min_line + 1;
-         if (Current_File->same_file_fpnt != (struct input_file *) NULL)
-           Current_File->file_number = Current_File->same_file_fpnt->file_number;
-         else
-           {
-             Current_File->file_number = ++File_Number;
-             file_available = VMS_TBT_Source_File (Current_File->name,
-                                                Current_File->file_number);
-             if (!file_available)
-               {
-                 Current_File->file_number = 0;
-                 File_Number--;
-                 continue;
-               }
-           }
-         VMS_TBT_Source_Lines (Current_File->file_number,
-                               Current_File->min_line,
-                      Current_File->max_line - Current_File->min_line + 1);
-       }                       /* for */
-    }                          /* scope */
-    Current_File = (struct input_file *) NULL;
-
-    for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
-      {
-       /*
-        *      Deal with text symbols
-        */
-       if (!S_IS_DEBUG (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT))
-         {
-           /*
-            *  Ignore symbols starting with "L",
-            *  as they are local symbols
-            */
-           if (*S_GET_NAME (symbolP) == 'L')
-             continue;
-           /*
-            *  If there is a routine start defined,
-            *  terminate it.
-            */
-           if (Current_Routine)
-             {
-               /*
-                *      End the routine
-                */
-               VMS_TBT_Routine_End (text_siz, Current_Routine);
-             }
-           /*
-            *  Check for & skip dummy labels like "gcc_compiled.".
-            *  They're identified by the IN_DEFAULT_SECTION flag.
-            */
-           if ((S_GET_OTHER (symbolP) & IN_DEFAULT_SECTION) != 0 &&
-                     (S_GET_VALUE (symbolP) == 0))
-             continue;
-           /*
-            *  Store the routine begin traceback info
-            */
-           if (Text_Psect != -1)
-             {
-               VMS_TBT_Routine_Begin (symbolP, Text_Psect);
-               Current_Routine = symbolP;
-             }
-
-/* Output local symbols, i.e. all symbols that are associated with a specific
- * routine.  We output them now so the debugger recognizes them as local to
- * this routine.
- */
-           {
-             symbolS *symbolP1;
-             char *pnt;
-             char *pnt1;
-             for (symbolP1 = Current_Routine; symbolP1; symbolP1 = symbol_next (symbolP1))
-               {
-                 if (!S_IS_DEBUG (symbolP1))
-                   continue;
-                 if (S_GET_RAW_TYPE (symbolP1) != N_FUN)
-                   continue;
-                 pnt = S_GET_NAME (symbolP);
-                 pnt1 = S_GET_NAME (symbolP1);
-                 if (*pnt++ != '_')
-                   continue;
-                 while (*pnt++ == *pnt1++)
-                   {
-                   }
-                 if (*pnt1 != 'F' && *pnt1 != 'f') continue;
-                 if ((*(--pnt) == '\0') && (*(--pnt1) == ':'))
-                   break;
-               }
-             if (symbolP1)
-               Define_Routine (symbolP1, 0, Current_Routine, Text_Psect);
-           }                   /* local symbol block */
-           /*
-            *  Done
-            */
-           continue;
-         }
-       /*
-        *      Deal with STAB symbols
-        */
-       if (S_IS_DEBUG (symbolP))
-         {
-           /*
-            *  Dispatch on STAB type
-            */
-           switch ((unsigned char) S_GET_RAW_TYPE (symbolP))
-             {
-               /*
-                *      Line number
-                */
-             case N_SLINE:
-               /* Offset the line into the correct portion
-                * of the file */
-               if (Current_File->file_number == 0)
-                 break;
-               /* Sometimes the same offset gets several source
-                * lines assigned to it.
-                * We should be selective about which lines
-                * we allow, we should prefer lines that are
-                * in the main source file when debugging
-                * inline functions. */
-               if ((Current_File->file_number != 1) &&
-                   S_GET_VALUE (symbolP) ==
-                   Current_Offset)
-                 break;
-               /* calculate actual debugger source line */
-               S_GET_DESC (symbolP)
-                 += Current_File->offset;
-               /*
-                *      If this is the 1st N_SLINE, setup
-                *      PC/Line correlation.  Otherwise
-                *      do the delta PC/Line.  If the offset
-                *      for the line number is not +ve we need
-                *      to do another PC/Line correlation
-                *      setup
-                */
-               if (Current_Offset == -1)
-                 {
-                   VMS_TBT_Line_PC_Correlation (
-                                                 S_GET_DESC (symbolP),
-                                                 S_GET_VALUE (symbolP),
-                                                 Text_Psect,
-                                                 0);
-                 }
-               else
-                 {
-                   if ((S_GET_DESC (symbolP) -
-                        Current_Line_Number) <= 0)
-                     {
-                       /*
-                        *      Line delta is not +ve, we
-                        *      need to close the line and
-                        *      start a new PC/Line
-                        *      correlation.
-                        */
-                       VMS_TBT_Line_PC_Correlation (0,
-                                                    S_GET_VALUE (symbolP) -
-                                                    Current_Offset,
-                                                    0,
-                                                    -1);
-                       VMS_TBT_Line_PC_Correlation (
-                                                     S_GET_DESC (symbolP),
-                                                     S_GET_VALUE (symbolP),
-                                                     Text_Psect,
-                                                     0);
-                     }
-                   else
-                     {
-                       /*
-                        *      Line delta is +ve, all is well
-                        */
-                       VMS_TBT_Line_PC_Correlation (
-                                                     S_GET_DESC (symbolP) -
-                                                     Current_Line_Number,
-                                                     S_GET_VALUE (symbolP) -
-                                                     Current_Offset,
-                                                     0,
-                                                     1);
-                     }
-                 }
-               /*
-                *      Update the current line/PC
-                */
-               Current_Line_Number = S_GET_DESC (symbolP);
-               Current_Offset = S_GET_VALUE (symbolP);
-               /*
-                *      Done
-                */
-               break;
                /*
                 *      Source file
                 */
-             case N_SO:
-               /*
-                *      Remember that we had a source file
-                *      and emit the source file debugger
-                *      record
-                */
-               Current_File =
-                 find_file (symbolP);
-               break;
-/* We need to make sure that we are really in the actual source file when
- * we compute the maximum line number.  Otherwise the debugger gets really
- * confused */
-             case N_SOL:
-               Current_File =
-                 find_file (symbolP);
-               break;
-             }
-         }
-      }
+           case N_SO:
+             /* Remember that we had a source file and emit
+                the source file debugger record.  */
+             Cur_File = find_file (symbolP);
+             break;
+
+           case N_SOL:
+             /* We need to make sure that we are really in the actual
+                source file when we compute the maximum line number.
+                Otherwise the debugger gets really confused.  */
+             Cur_File = find_file (symbolP);
+             break;
+
+           default:
+             break;
+           }           /* switch */
+       }               /* if (IS_DEBUG) */
+    }                  /* for */
+
     /*
-     * If there is a routine start defined,
-     * terminate it (and the line numbers)
+     * If there is a routine start defined, terminate it
+     * (and the line numbers).
      */
     if (Current_Routine)
       {
-       /*
-        *      Terminate the line numbers
-        */
+       /* Terminate the line numbers.  */
        VMS_TBT_Line_PC_Correlation (0,
-                                  text_siz - S_GET_VALUE (Current_Routine),
+                                    text_siz - S_GET_VALUE (Current_Routine),
                                     0,
                                     -1);
-       /*
-        *      Terminate the routine
-        */
+       /* Terminate the routine.  */
        VMS_TBT_Routine_End (text_siz, Current_Routine);
       }
-  }
+
   /*
    *   Write the Traceback End Module TBT record
    */
   VMS_TBT_Module_End ();
+}
 \f
+
+/*
+ *     Write a VAX/VMS object file (everything else has been done!)
+ */
+void
+vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
+                      data_frag_root)
+     unsigned text_siz;
+     unsigned data_siz;
+     unsigned bss_siz;
+     fragS *text_frag_root;
+     fragS *data_frag_root;
+{
+  register struct VMS_Symbol *vsp;
+
+  /*
+   * Initialize program section indices; values get updated later.
+   */
+  Psect_Number = 0;            /* next Psect Index to use */
+  Text_Psect = -1;             /* Text Psect Index   */
+  Data_Psect = -2;             /* Data Psect Index   JF: Was -1 */
+  Bss_Psect = -3;              /* Bss Psect Index    JF: Was -1 */
+  /* Initialize other state variables.  */
+  Data_Segment = 0;
+  Local_Initd_Data_Size = 0;
+
+  /*
+   *   Create the actual output file and populate it with required
+   *   "module header" information.
+   */
+  Create_VMS_Object_File ();
+  Write_VMS_MHD_Records ();
+
+  /*
+   *   Create the Data segment:
+   *
+   *   Since this is REALLY hard to do any other way,
+   *   we actually manufacture the data segment and
+   *   then store the appropriate values out of it.
+   *   We need to generate this early, so that globalvalues
+   *   can be properly emitted.
+   */
+  if (data_siz > 0)
+    synthesize_data_segment(data_siz, text_siz, data_frag_root);
+
+
+  /*******  Global Symbol Directory  *******/
+
+  /*
+   *   Emit globalvalues now.  We must do this before the text psect is
+   *   defined, or we will get linker warnings about multiply defined
+   *   symbols.  All of the globalvalues "reference" psect 0, although
+   *   it really does not have anything to do with it.
+   */
+  VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment);
+  /*
+   *   Define the Text Psect
+   */
+  Text_Psect = Psect_Number++;
+  VMS_Psect_Spec ("$code", text_siz, "TEXT", 0);
+  /*
+   *   Define the BSS Psect
+   */
+  if (bss_siz > 0)
+    {
+      Bss_Psect = Psect_Number++;
+      VMS_Psect_Spec ("$uninitialized_data", bss_siz, "DATA", 0);
+    }
+  /*
+   * Define symbols to the linker.
+   */
+  global_symbol_directory (text_siz, data_siz);
+  /*
+   *   Define the Data Psect
+   */
+  if (data_siz > 0 && Local_Initd_Data_Size > 0)
+    {
+      Data_Psect = Psect_Number++;
+      VMS_Psect_Spec ("$data", Local_Initd_Data_Size, "DATA", 0);
+      /*
+       * Local initialized data (N_DATA) symbols need to be updated to the
+       * proper value of Data_Psect now that it's actually been defined.
+       * (A dummy value was used in global_symbol_directory() above.)
+       */
+      for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
+       if (vsp->Psect_Index < 0 && S_GET_RAW_TYPE (vsp->Symbol) == N_DATA)
+         vsp->Psect_Index = Data_Psect;
+    }
+
+
+  /*******  Text Information and Relocation Records  *******/
+
+  /*
+   *   Write the text segment data
+   */
+  if (text_siz > 0)
+    vms_fixup_text_section (text_siz, text_frag_root, data_frag_root);
+  /*
+   *   Write the data segment data, then discard it.
+   */
+  if (data_siz > 0)
+    {
+      vms_fixup_data_section (data_siz, text_siz);
+      free (Data_Segment),  Data_Segment = 0;
+    }
+
+
+  /*******  Debugger Symbol Table Records  *******/
+
+  vms_build_DST (text_siz);
+
+
   /*
    *   Write the End Of Module record
    */
@@ -5736,7 +5667,6 @@ vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
     Write_VMS_EOM_Record (Text_Psect,
                          S_GET_VALUE (Entry_Point_Symbol));
 
-
   /*
    *   All done, close the object file
    */