Lots of changes from Eric Youngdale, mostly for VAX and VMS support.
authorKen Raeburn <raeburn@cygnus>
Thu, 7 Jan 1993 10:49:48 +0000 (10:49 +0000)
committerKen Raeburn <raeburn@cygnus>
Thu, 7 Jan 1993 10:49:48 +0000 (10:49 +0000)
gas/config/ho-vms.h
gas/config/obj-vms.c

index 63f448e1d30258978ab4b149a778e3850a88f341..ec7dc9e18684c0f151ec12fd1c2f534ddff7648d 100644 (file)
@@ -17,7 +17,7 @@
    along with GAS; see the file COPYING.  If not, write to
    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
-#define HO_VAX 1
+#define HO_VMS 1
 
 #include "ho-vax.h"
 
index af8845895523f0563ea21e9171fe82cd1ce1db5b..83abd772c44a5f292bce072330d863240dd9db89 100644 (file)
@@ -100,7 +100,7 @@ static struct input_file *find_file PARAMS ((symbolS *));
 
 enum advanced_type
 {
-  BASIC, POINTER, ARRAY, ENUM, STRUCT, UNION, FUNCTION, VOID, UNKNOWN
+  BASIC, POINTER, ARRAY, ENUM, STRUCT, UNION, FUNCTION, VOID, ALIAS, UNKNOWN
 };
 
 /*
@@ -167,6 +167,12 @@ static char *symbol_name;
 
 static structure_count = 0;
 
+/* This variable is used to indicate that we are making the last attempt to
+   parse the stabs, and that we should define as much as we can, and ignore 
+   the rest */
+
+static int final_pass;
+
 /* This variable is used to keep track of the current structure number
  * for a given variable.  If this is < 0, that means that the structure
  * has not yet been defined to the debugger.  This is still cool, since
@@ -222,6 +228,16 @@ static char Object_Record_Buffer[512];     /* Buffer for object file records  */
 static int Object_Record_Offset;/* Offset to end of data          */
 static int Current_Object_Record_Type; /* Type of record in above         */
 
+/*
+ *     Macros for moving data around.  Must work on big-endian systems.
+ */
+#ifdef HO_VMS  /* These are more efficient for VMS->VMS systems */
+#define COPY_LONG(dest,val) {*(long *) dest = val; }
+#define COPY_SHORT(dest,val) {*(short *) dest = val; }
+#else
+#define        COPY_LONG(dest,val) { md_number_to_chars(dest, val, 4); }
+#define        COPY_SHORT(dest,val) { md_number_to_chars(dest, val, 2); }
+#endif
 /*
  *     Macros for placing data into the object record buffer
  */
@@ -335,6 +351,10 @@ static void
 obj_aout_stab (what)
      int what;
 {
+#ifndef NO_LISTING
+       extern int listing;
+#endif /* NO_LISTING */
+
   register symbolS *symbolP = 0;
   register char *string;
   int saved_type = 0;
@@ -437,6 +457,22 @@ obj_aout_stab (what)
       symbolP->sy_symbol.n_type = saved_type;
     }
 
+#ifndef NO_LISTING
+       if (listing && !goof) 
+           {
+                   if (symbolP->sy_symbol.n_type == N_SLINE) 
+                       {
+                               
+                               listing_source_line(symbolP->sy_symbol.n_desc);
+                       }
+                   else if (symbolP->sy_symbol.n_type == N_SO
+                            || symbolP->sy_symbol.n_type == N_SOL) 
+                       {
+                               listing_source_file(string);
+                       }                         
+           }
+#endif  
+
   if (goof)
     ignore_rest_of_line ();
   else
@@ -568,6 +604,7 @@ Flush_VMS_Object_Record_Buffer ()
 {
   int i;
   short int zero;
+  int RecLen;
   /*
    *   If the buffer is empty, we are done
    */
@@ -577,7 +614,8 @@ Flush_VMS_Object_Record_Buffer ()
    *   Write the data to the file
    */
 #ifndef HO_VMS                 /* For cross-assembly purposes. */
-  i = write (VMS_Object_File_FD, &Object_Record_Offset, 2);
+  md_number_to_chars((char *) &RecLen, Object_Record_Offset, 2);
+  i = write (VMS_Object_File_FD, &RecLen, 2);
 #endif /* not HO_VMS */
   i = write (VMS_Object_File_FD,
             Object_Record_Buffer,
@@ -766,8 +804,7 @@ VMS_Set_Data (Psect_Index, Offset, Record_Type, Force)
  *     Make a debugger reference to a struct, union or enum.
  */
 static
-VMS_Store_Struct (Struct_Index)
-     int Struct_Index;
+VMS_Store_Struct (int Struct_Index)
 {
   /*
    *   We are writing a "OBJ_S_C_DBG" record
@@ -794,8 +831,7 @@ VMS_Store_Struct (Struct_Index)
  *     Make a debugger reference to partially define a struct, union or enum.
  */
 static
-VMS_Def_Struct (Struct_Index)
-     int Struct_Index;
+VMS_Def_Struct (int Struct_Index)
 {
   /*
    *   We are writing a "OBJ_S_C_DBG" record
@@ -818,8 +854,7 @@ VMS_Def_Struct (Struct_Index)
 }
 
 static
-VMS_Set_Struct (Struct_Index)
-     int Struct_Index;
+VMS_Set_Struct (int Struct_Index)
 {                              /* see previous functions for comments */
   Set_VMS_Object_File_Record (OBJ_S_C_DBG);
   if (Object_Record_Offset == 0)
@@ -887,7 +922,7 @@ VMS_TBT_Module_Begin ()
   /*
    *   Language type == "C"
    */
-  *(long *) cp = DST_S_C_C;
+  COPY_LONG (cp, DST_S_C_C);
   cp += sizeof (long);
   /*
    *   Store the module name
@@ -1054,7 +1089,7 @@ VMS_TBT_Routine_End (Max_Size, sp)
   /*
    *   Size of routine
    */
-  *((long *) (Local + 3)) = Size;
+  COPY_LONG (&Local[3], Size);
   /*
    *   Store the record
    */
@@ -1130,8 +1165,7 @@ VMS_TBT_Block_Begin (symbolP, Psect, Name)
  *     Write the Traceback Block End record
  */
 static
-VMS_TBT_Block_End (Size)
-     int Size;
+VMS_TBT_Block_End (int Size)
 {
   char Local[16];
 
@@ -1140,7 +1174,7 @@ VMS_TBT_Block_End (Size)
    */
   Local[0] = 6;
   Local[1] = DST_S_C_BLKEND;
-  *((long *) (Local + 3)) = Size;
+  COPY_LONG (&Local[3], Size);
   /*
    *   Unused
    */
@@ -1180,7 +1214,7 @@ VMS_TBT_Line_PC_Correlation (Line_Number, Offset, Psect, Do_Delta)
        *       Set Line number
        */
       Local[2] = DST_S_C_SET_LINE_NUM;
-      *((unsigned short *) (Local + 3)) = Line_Number - 1;
+      COPY_SHORT (&Local[3], Line_Number - 1);
       /*
        *       Set PC
        */
@@ -1221,7 +1255,7 @@ VMS_TBT_Line_PC_Correlation (Line_Number, Offset, Psect, Do_Delta)
          Local[0] = 1 + 1 + 4;
          Local[1] = DST_S_C_LINE_NUM;
          Local[2] = DST_S_C_TERM_L;
-         *((long *) (Local + 3)) = Offset;
+         COPY_LONG (&Local[3], Offset);
          VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
          /*
           *    Done
@@ -1246,7 +1280,7 @@ VMS_TBT_Line_PC_Correlation (Line_Number, Offset, Psect, Do_Delta)
          else
            {
              *cp++ = DST_S_C_INCR_LINUM_W;
-             *(short *) cp = Line_Number - 1;
+             COPY_SHORT (cp, Line_Number - 1);
              cp += sizeof (short);
            }
        }
@@ -1262,13 +1296,13 @@ VMS_TBT_Line_PC_Correlation (Line_Number, Offset, Psect, Do_Delta)
          if (Offset < 0x10000)
            {
              *cp++ = DST_S_C_DELTA_PC_W;
-             *(short *) cp = Offset;
+             COPY_SHORT (cp, Offset);
              cp += sizeof (short);
            }
          else
            {
              *cp++ = DST_S_C_DELTA_PC_L;
-             *(long *) cp = Offset;
+             COPY_LONG (cp, Offset);
              cp += sizeof (long);
            }
        }
@@ -1366,7 +1400,7 @@ VMS_TBT_Source_File (Filename, ID_Number)
   /*
    *   File ID
    */
-  *(short *) cp = ID_Number;
+  COPY_SHORT (cp, ID_Number);
   cp += sizeof (short);
 #ifndef HO_VMS
   /*
@@ -1465,19 +1499,19 @@ VMS_TBT_Source_Lines (ID_Number, Starting_Line_Number, Number_Of_Lines)
   /*
    *   File ID Number
    */
-  *(short *) cp = ID_Number;
+  COPY_SHORT (cp, ID_Number);
   cp += sizeof (short);
   /*
    *   Set record number
    */
   *cp++ = DST_S_C_SRC_SETREC_L;
-  *(long *) cp = Starting_Line_Number;
+  COPY_LONG (cp, Starting_Line_Number);
   cp += sizeof (long);
   /*
    *   Define lines
    */
   *cp++ = DST_S_C_SRC_DEFLINES_W;
-  *(short *) cp = Number_Of_Lines;
+  COPY_SHORT (cp, Number_Of_Lines);
   cp += sizeof (short);
   /*
    *   Done
@@ -1656,6 +1690,8 @@ find_symbol (dbx_type)
     };
   if (spnt == (struct VMS_DBG_Symbol *) NULL)
     return 0;                  /*Dunno what this is*/
+  if(spnt->advanced == ALIAS)
+    return find_symbol(spnt->type2);
   return spnt;
 }
 
@@ -1669,38 +1705,32 @@ static
 push (value, size)
      int value, size;
 {
-  char *pnt;
   int i;
   int size1;
-  long int val;
-  val = value;
-  pnt = (char *) &val;
   size1 = size;
   if (size < 0)
     {
       size1 = -size;
-      pnt += size1 - 1;
-    };
-  if (size < 0)
-    for (i = 0; i < size1; i++)
-      {
-       Local[Lpnt--] = *pnt--;
-       if (Lpnt < 0)
-         {
-           overflow = 1;
-           Lpnt = 1;
-         };
-      }
+      if (Lpnt < size1)
+       {
+         overflow = 1;
+         Lpnt = 1;
+         return;
+       };
+      Lpnt -= size1;
+      md_number_to_chars (&Local[Lpnt + 1], value, size1);
+    }
   else
-    for (i = 0; i < size1; i++)
-      {
-       Asuffix[Apoint++] = *pnt++;
-       if (Apoint >= MAX_DEBUG_RECORD)
-         {
-           overflow = 1;
-           Apoint = MAX_DEBUG_RECORD - 1;
-         };
-      }
+    {
+      if (Apoint + size1 >= MAX_DEBUG_RECORD)
+       {
+         overflow = 1;
+         Apoint = MAX_DEBUG_RECORD - 1;
+         return;
+       };
+      md_number_to_chars (&Asuffix[Apoint], value, size1);
+      Apoint += size1;
+    };
 }
 
 /* this routine generates the array descriptor for a given array */
@@ -1891,7 +1921,7 @@ generate_suffix (spnt, dbx_type)
 {
   int ilen;
   int i;
-  static CONST char pvoid[6] = {5, 0xaf, 0, 1, 0, 5};
+  CONST char pvoid[6] = {5, 0xaf, 0, 1, 0, 5};
   struct VMS_DBG_Symbol *spnt1;
   Apoint = 0;
   Lpnt = MAX_DEBUG_RECORD - 1;
@@ -1979,9 +2009,8 @@ VMS_DBG_record (spnt, Psect, Offset, Name)
        Local[i++] = DBG_S_C_FUNCTION_PARAMETER;
       else
        Local[i++] = DBG_S_C_LOCAL_SYM;
-      pnt = (char *) &Offset;
-      for (j = 0; j < 4; j++)
-       Local[i++] = *pnt++;    /* copy the offset */
+      COPY_LONG (&Local[i], Offset);
+      i += 4;
     }
   else
     {
@@ -2349,9 +2378,8 @@ forward_reference (pnt)
       pnt = (char *) strchr (pnt, ':');
       pnt = cvt_integer (pnt + 1, &i);
       spnt = find_symbol (i);
-      if (spnt == (struct VMS_DBG_Symbol *) NULL)
-       return 0;
-      while ((spnt->advanced == POINTER) || (spnt->advanced == ARRAY))
+      if(spnt != (struct VMS_DBG_Symbol*) NULL) {
+       while((spnt->advanced == POINTER) || (spnt->advanced == ARRAY))
        {
          i = spnt->type2;
          spnt1 = find_symbol (spnt->type2);
@@ -2362,12 +2390,32 @@ forward_reference (pnt)
            break;
          spnt = spnt1;
        };
+      };
       pnt = cvt_integer (pnt + 1, &i);
       pnt = cvt_integer (pnt + 1, &i);
   } while (*++pnt != ';');
   return 0;                    /* no forward refences found */
 }
 
+/* Used to check a single element of a structure on the final pass*/
+
+static int
+final_forward_reference (spnt)
+  struct VMS_DBG_Symbol * spnt;
+{
+       struct VMS_DBG_Symbol * spnt1;
+       if(spnt != (struct VMS_DBG_Symbol*) NULL) {
+         while((spnt->advanced == POINTER) || (spnt->advanced == ARRAY)){
+           spnt1 = find_symbol(spnt->type2);
+           if((spnt->advanced == ARRAY) &&
+              (spnt1 == (struct VMS_DBG_Symbol*) NULL))return 1;
+           if(spnt1 == (struct VMS_DBG_Symbol*) NULL) break;
+           spnt=spnt1;
+         };
+       };
+       return 0;       /* no forward refences found */
+}
+
 /* This routine parses the stabs directives to find any definitions of dbx type
  * numbers.  It makes a note of all of them, creating a structure element
  * of VMS_DBG_Symbol that describes it.  This also generates the info for the
@@ -2379,6 +2427,10 @@ forward_reference (pnt)
  * a structure/enum/union) and this is why we process them immediately.
  * After we process the pointer, then we search for defs that are nested even
  * deeper.
+ * 8/15/92: We have to process arrays right away too, because there can
+ * be multiple references to identical array types in one structure
+ * definition, and only the first one has the definition.  (We tend to
+ * parse from the back going forward.
  */
 static int
 VMS_typedef_parse (str)
@@ -2396,7 +2448,8 @@ VMS_typedef_parse (str)
   struct VMS_DBG_Symbol *spnt1;
 /* check for any nested def's */
   pnt = (char *) strchr (str + 1, '=');
-  if ((pnt != (char *) NULL) && (*(str + 1) != '*'))
+  if ((pnt != (char *) NULL) && (*(str + 1) != '*')
+    && (str[1] != 'a' || str[2] != 'r'))
     if (VMS_typedef_parse (pnt) == 1)
       return 1;
 /* now find dbx_type of entry */
@@ -2450,6 +2503,14 @@ VMS_typedef_parse (str)
          spnt->advanced = UNKNOWN;
          return 0;
        };
+      pnt1 = cvt_integer(pnt,&i1);
+      if(i1 != spnt->dbx_type)
+       {
+         spnt->advanced = ALIAS;
+         spnt->type2 = i1;
+         strcpy(str, pnt1);
+         return 0;
+       }
       printf ("gcc-as warning(debugger output):");
       printf (" %d is an unknown untyped variable.\n", spnt->dbx_type);
       return 1;                        /* do not know what this is */
@@ -2525,7 +2586,7 @@ VMS_typedef_parse (str)
        spnt->advanced = UNION;
       spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
       pnt1 = cvt_integer (pnt + 1, &spnt->data_size);
-      if (forward_reference (pnt))
+      if (!final_pass && forward_reference(pnt))
        {
          spnt->struc_numb = -1;
          return 1;
@@ -2557,9 +2618,8 @@ VMS_typedef_parse (str)
       while (*pnt2 != '\0')
        Local[i++] = *pnt2++;
       i2 = spnt->data_size * 8;        /* number of bits */
-      pnt2 = (char *) &i2;
-      for (i1 = 0; i1 < 4; i1++)
-       Local[i++] = *pnt2++;
+      COPY_LONG(&Local[i], i2);
+      i += 4;
       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
       i = 0;
       if (pnt != symbol_name)
@@ -2596,14 +2656,20 @@ VMS_typedef_parse (str)
              Local[i++] = 7 + strlen (pnt2);
              spnt1 = find_symbol (dtype);
              /* check if this is a forward reference */
+             if(final_pass && final_forward_reference(spnt1))
+               {
+                 printf("gcc-as warning(debugger output):");
+                 printf("structure element %s has undefined type\n",pnt2);
+                 i--;
+                 continue;
+               }
              if (spnt1 != (struct VMS_DBG_Symbol *) NULL)
                Local[i++] = spnt1->VMS_type;
              else
                Local[i++] = DBG_S_C_ADVANCED_TYPE;
              Local[i++] = DBG_S_C_STRUCT_ITEM;
-             pnt = (char *) &i2;
-             for (i1 = 0; i1 < 4; i1++)
-               Local[i++] = *pnt++;
+             COPY_LONG (&Local[i], i2);
+             i += 4;
              Local[i++] = strlen (pnt2);
              while (*pnt2 != '\0')
                Local[i++] = *pnt2++;
@@ -2657,9 +2723,8 @@ VMS_typedef_parse (str)
          Local[i++] = 7 + strlen (pnt);
          Local[i++] = DBG_S_C_ENUM_ITEM;
          Local[i++] = 0x00;
-         pnt2 = (char *) &i1;
-         for (i2 = 0; i2 < 4; i2++)
-           Local[i++] = *pnt2++;
+         COPY_LONG (&Local[i], i1);
+         i += 4;
          Local[i++] = strlen (pnt);
          pnt2 = pnt;
          while (*pnt != '\0')
@@ -2683,6 +2748,9 @@ VMS_typedef_parse (str)
       pnt1 = cvt_integer (pnt + 1, &spnt->index_min);
       pnt1 = cvt_integer (pnt1 + 1, &spnt->index_max);
       pnt1 = cvt_integer (pnt1 + 1, &spnt->type2);
+      pnt=(char*)strchr(str+1,'=');
+      if((pnt != (char*) NULL)) 
+       if(VMS_typedef_parse(pnt) == 1 ) return 1;
       break;
     case 'f':
       spnt->advanced = FUNCTION;
@@ -2724,6 +2792,10 @@ parsing do not have to worry about it */
  * We need to be careful, since sometimes there are forward references to
  * other symbol types, and these cannot be resolved until we have completed
  * the parse.
+ *
+ * Also check and see if we are using continuation stabs, if we are, then
+ * paste together the entire contents of the stab before we pass it to 
+ * VMS_typedef_parse.
  */
 static int
 VMS_LSYM_Parse ()
@@ -2732,6 +2804,7 @@ VMS_LSYM_Parse ()
   char *pnt1;
   char *pnt2;
   char *str;
+  char *parse_buffer = 0;
   char fixit[10];
   int incomplete, i, pass, incom1;
   struct VMS_DBG_Symbol *spnt;
@@ -2739,6 +2812,7 @@ VMS_LSYM_Parse ()
   struct forward_ref *fpnt;
   symbolS *sp;
   pass = 0;
+  final_pass = 0;
   incomplete = 0;
   do
     {
@@ -2765,24 +2839,65 @@ VMS_LSYM_Parse ()
                case N_FUN:     /*sometimes these contain typedefs*/
                  str = S_GET_NAME (sp);
                  symbol_name = str;
+                 pnt = str + strlen(str) -1;
+                 if (*pnt == '?')  /* Continuation stab.  */
+                   {
+                     symbolS *spnext;
+                     int tlen = 0;
+                     spnext = sp;
+                     do {
+                       tlen += strlen(str) - 1;
+                       spnext = symbol_next (spnext);
+                       str = S_GET_NAME (spnext);
+                       pnt = str + strlen(str) - 1;
+                     } while (*pnt == '?');
+                     tlen += strlen(str);
+                     parse_buffer = (char *) malloc (tlen + 1);
+                     strcpy(parse_buffer, S_GET_NAME (sp));
+                     pnt2 = parse_buffer + strlen(S_GET_NAME (sp)) - 1;
+                     *pnt2 = '\0';
+                     spnext = sp;
+                     do {
+                       spnext = symbol_next (spnext);
+                       str = S_GET_NAME (spnext);
+                       strcat (pnt2, S_GET_NAME (spnext));
+                       pnt2 +=  strlen(str) - 1;
+                       *str = '\0';  /* Erase this string  */
+                       if (*pnt2 != '?') break;
+                       *pnt2 = '\0';
+                     } while (1 == 1);
+                     str = parse_buffer;
+                     symbol_name = str;
+                   };
                  pnt = (char *) strchr (str, ':');
-                 if (pnt == (char *) NULL)
-                   break;
-                 *pnt = '\0';
-                 pnt1 = pnt + 1;
-                 pnt2 = (char *) strchr (pnt1, '=');
-                 if (pnt2 == (char *) NULL)
+                 if (pnt != (char *) NULL)
                    {
-                     *pnt = ':';       /* replace colon */
-                     break;
-                   };          /* no symbol here */
-                 incomplete += VMS_typedef_parse (pnt2);
-                 *pnt = ':';   /* put back colon so variable def code finds dbx_type*/
+                     *pnt = '\0';
+                     pnt1 = pnt + 1;
+                     pnt2 = (char *) strchr (pnt1, '=');
+                     if (pnt2 != (char *) NULL)
+                       incomplete += VMS_typedef_parse (pnt2);
+                     if (parse_buffer){
+                       /*  At this point the parse buffer should just contain name:nn.
+                           If it does not, then we are in real trouble. Anyway, 
+                           this is always shorter than the original line. */
+                       strcpy(S_GET_NAME (sp), parse_buffer);
+                       free (parse_buffer);
+                       parse_buffer = 0;
+                     };
+                     *pnt = ':';       /* put back colon so variable def code finds dbx_type*/
+                   };
                  break;
                }               /*switch*/
            }                   /* if */
        }                       /*for*/
       pass++;
+/* Make one last pass, if needed, and define whatever we can that is left */
+      if(final_pass == 0 && incomplete == incom1)
+        {
+          final_pass = 1;
+         incom1 ++;  /* Force one last pass through */
+       };
   } while ((incomplete != 0) && (incomplete != incom1));
   /* repeat until all refs resolved if possible */
 /*     if (pass > 1) printf(" Required %d passes\n",pass);*/
@@ -2931,8 +3046,7 @@ VMS_DBG_Define_Routine (symbolP, Curr_Routine, Txt_Psect)
 #include <time.h>
 
 /* Manufacure a VMS like time on a unix based system. */
-get_VMS_time_on_unix (Now)
-     char *Now;
+get_VMS_time_on_unix (char *Now)
 {
   char *pnt;
   time_t timeb;
@@ -3058,7 +3172,7 @@ Write_VMS_MHD_Records ()
       cp = "GNU AS  V";
       while (*cp)
        PUT_CHAR (*cp++);
-      cp = strchr (version_string, '.');
+      cp = strchr (&version_string, '.');
       while (*cp != ' ')
        cp--;
       cp++;
@@ -3631,9 +3745,8 @@ VMS_Psect_Spec (Name, Size, Type, vsp)
        default:
          {
            char Error_Line[256];
-           sprintf (Error_Line,
-                    "Globalsymbol attribute for symbol %s was unexpected.\n",
-                    Name);
+           sprintf (Error_Line, "Globalsymbol attribute for"
+                    " symbol %s was unexpected.\n", Name);
            error (Error_Line);
            break;
          };
@@ -3803,10 +3916,8 @@ VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment)
              Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
              if (Size > 4)
                error ("Invalid data type for globalvalue");
-             globalvalue = 0;
-             
-             memcpy (&globalvalue, Data_Segment + S_GET_VALUE (sp) -
-                    text_siz, Size);
+             globalvalue = md_chars_to_number (Data_Segment + 
+                    S_GET_VALUE (sp) - text_siz , Size);
              /* Three times for good luck.  The linker seems to get confused
                 if there are fewer than three */
              VMS_Global_Symbol_Spec (stripped_name, 0, 0, 2);
@@ -4664,6 +4775,18 @@ VMS_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
                                         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(strncmp (S_GET_NAME (sp), "__vt.", 5) == 0)
+           VMS_Global_Symbol_Spec (S_GET_NAME(sp),
+                                   vsp->Psect_Index,
+                                   0,
+                                   0);
+
 #ifdef NOT_VAX_11_C_COMPATIBLE
          /*
           *    Place a global symbol at the
@@ -4728,6 +4851,18 @@ VMS_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
                                         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(strncmp (S_GET_NAME (sp), "__vt.", 5) == 0)
+           VMS_Global_Symbol_Spec (S_GET_NAME (sp),
+                                   vsp->Psect_Index,
+                                   0,
+                                   1);
+
 #ifdef NOT_VAX_11_C_COMPATIBLE
          /*
           *    Place a global symbol at the