vms updates

This commit is contained in:
Ken Raeburn
1995-09-15 21:41:56 +00:00
parent 1862bbd8d9
commit d57bf0e0de

View File

@ -1340,12 +1340,13 @@ VMS_TBT_Source_Lines (ID_Number, Starting_Line_Number, Number_Of_Lines)
} }
/****** Debugger Information support routines ******/
/* This routine locates a file in the list of files. If an entry does
not exist, one is created. For include files, a new entry is always
created such that inline functions can be properly debugged. */
/*
* This routine locates a file in the list of files. If an entry does not
* exist, one is created. For include files, a new entry is always created
* such that inline functions can be properly debugged.
*/
static struct input_file * static struct input_file *
find_file (sp) find_file (sp)
symbolS *sp; symbolS *sp;
@ -1387,62 +1388,61 @@ find_file (sp)
fpnt->same_file_fpnt = same_file; fpnt->same_file_fpnt = same_file;
return fpnt; return fpnt;
} }
/*
* The following functions and definitions are used to generate object records
* that will describe program variables to the VMS debugger.
*
* This file contains many of the routines needed to output debugging info into
* the object file that the VMS debugger needs to understand symbols. These
* routines are called very late in the assembly process, and thus we can be
* fairly lax about changing things, since the GSD and the TIR sections have
* already been output.
*/
/* This routine converts a number string into an integer, and stops when it /* This routine converts a number string into an integer, and stops when
* sees an invalid character. The return value is the address of the character it sees an invalid character. The return value is the address of the
* just past the last character read. No error is generated. character just past the last character read. No error is generated. */
*/
static char * static char *
cvt_integer (str, rtn) cvt_integer (str, rtn)
char *str; char *str;
int *rtn; int *rtn;
{ {
int ival, neg; int ival = 0, sgn = 1;
neg = *str == '-' ? ++str, -1 : 1;
ival = 0; if (*str == '-')
while ((*str <= '9') && (*str >= '0')) sgn = -1, ++str;
while (*str >= '0' && *str <= '9')
ival = 10 * ival + *str++ - '0'; ival = 10 * ival + *str++ - '0';
*rtn = neg * ival; *rtn = sgn * ival;
return str; return str;
} }
/* this routine fixes the names that are generated by C++, ".this" is a good /*
* example. The period does not work for the debugger, since it looks like * The following functions and definitions are used to generate object
* the syntax for a structure element, and thus it gets mightily confused * records that will describe program variables to the VMS debugger.
* *
* We also use this to strip the PsectAttribute hack from the name before we * This file contains many of the routines needed to output debugging info
* write a debugger record */ * into the object file that the VMS debugger needs to understand symbols.
* These routines are called very late in the assembly process, and thus
* we can be fairly lax about changing things, since the GSD and the TIR
* sections have already been output.
*/
/* This routine fixes the names that are generated by C++, ".this" is a good
example. The period does not work for the debugger, since it looks like
the syntax for a structure element, and thus it gets mightily confused.
We also use this to strip the PsectAttribute hack from the name before we
write a debugger record. */
static char * static char *
fix_name (pnt) fix_name (pnt)
char *pnt; char *pnt;
{ {
char *pnt1; char *pnt1;
/*
* Kill any leading "_" /* Kill any leading "_". */
*/
if (*pnt == '_') if (*pnt == '_')
pnt++; pnt++;
/*
* Is there a Psect Attribute to skip?? /* Is there a Psect Attribute to skip?? */
*/
if (HAS_PSECT_ATTRIBUTES (pnt)) if (HAS_PSECT_ATTRIBUTES (pnt))
{ {
/* /* Yes: Skip it. */
* Yes: Skip it
*/
pnt += PSECT_ATTRIBUTES_STRING_LENGTH; pnt += PSECT_ATTRIBUTES_STRING_LENGTH;
while (*pnt) while (*pnt)
{ {
@ -1454,21 +1454,22 @@ fix_name (pnt)
pnt++; pnt++;
} }
} }
/* Here we fix the .this -> $this conversion */
/* Here we fix the .this -> $this conversion. */
for (pnt1 = pnt; *pnt1 != 0; pnt1++) for (pnt1 = pnt; *pnt1 != 0; pnt1++)
{ if (*pnt1 == '.')
if (*pnt1 == '.') *pnt1 = '$';
*pnt1 = '$';
}
return pnt; return pnt;
} }
/* When defining a structure, this routine is called to find the name of /* When defining a structure, this routine is called to find the name of
* the actual structure. It is assumed that str points to the equal sign the actual structure. It is assumed that str points to the equal sign
* in the definition, and it moves backward until it finds the start of the in the definition, and it moves backward until it finds the start of the
* name. If it finds a 0, then it knows that this structure def is in the name. If it finds a 0, then it knows that this structure def is in the
* outermost level, and thus symbol_name points to the symbol name. outermost level, and thus symbol_name points to the symbol name. */
*/
static char * static char *
get_struct_name (str) get_struct_name (str)
char *str; char *str;
@ -1491,7 +1492,10 @@ get_struct_name (str)
return pnt; return pnt;
} }
/* search symbol list for type number dbx_type. Return a pointer to struct */
/* Search symbol list for type number dbx_type.
Return a pointer to struct. */
static struct VMS_DBG_Symbol * static struct VMS_DBG_Symbol *
find_symbol (dbx_type) find_symbol (dbx_type)
int dbx_type; int dbx_type;
@ -1586,7 +1590,9 @@ rpush (value, size)
} }
} }
/* this routine generates the array descriptor for a given array */
/* This routine generates the array descriptor for a given array. */
static void static void
array_suffix (spnt2) array_suffix (spnt2)
struct VMS_DBG_Symbol *spnt2; struct VMS_DBG_Symbol *spnt2;
@ -1601,7 +1607,7 @@ array_suffix (spnt2)
while (spnt->advanced != ARRAY) while (spnt->advanced != ARRAY)
{ {
spnt = find_symbol (spnt->type2); spnt = find_symbol (spnt->type2);
if (spnt == (struct VMS_DBG_Symbol *) NULL) if (!spnt)
return; return;
} }
spnt1 = spnt; spnt1 = spnt;
@ -1641,11 +1647,12 @@ array_suffix (spnt2)
} }
} }
/* this routine generates the start of a variable descriptor based upon
* a struct/union/enum that has yet to be defined. We define this spot as /* This routine generates the start of a variable descriptor based upon
* a new location, and save four bytes for the address. When the struct is a struct/union/enum that has yet to be defined. We define this spot as
* finally defined, then we can go back and plug in the correct address. a new location, and save four bytes for the address. When the struct is
*/ finally defined, then we can go back and plug in the correct address. */
static void static void
new_forward_ref (dbx_type) new_forward_ref (dbx_type)
int dbx_type; int dbx_type;
@ -1663,12 +1670,13 @@ new_forward_ref (dbx_type)
struct_number = -fpnt->struc_numb; struct_number = -fpnt->struc_numb;
} }
/* this routine generates the variable descriptor used to describe non-basic
* variables. It calls itself recursively until it gets to the bottom of it /* This routine generates the variable descriptor used to describe non-basic
* all, and then builds the descriptor backwards. It is easiest to do it this variables. It calls itself recursively until it gets to the bottom of it
*way since we must periodically write length bytes, and it is easiest if we know all, and then builds the descriptor backwards. It is easiest to do it
*the value when it is time to write it. this way since we must periodically write length bytes, and it is easiest
*/ if we know the value when it is time to write it. */
static int static int
gen1 (spnt, array_suffix_len) gen1 (spnt, array_suffix_len)
struct VMS_DBG_Symbol *spnt; struct VMS_DBG_Symbol *spnt;
@ -1767,12 +1775,13 @@ gen1 (spnt, array_suffix_len)
return 0; return 0;
} }
/* This generates a suffix for a variable. If it is not a defined type yet, /* This generates a suffix for a variable. If it is not a defined type yet,
* then dbx_type contains the type we are expecting so we can generate a then dbx_type contains the type we are expecting so we can generate a
* forward reference. This calls gen1 to build most of the descriptor, and forward reference. This calls gen1 to build most of the descriptor, and
* then it puts the icing on at the end. It then dumps whatever is needed then it puts the icing on at the end. It then dumps whatever is needed
* to get a complete descriptor (i.e. struct reference, array suffix ). to get a complete descriptor (i.e. struct reference, array suffix). */
*/
static void static void
generate_suffix (spnt, dbx_type) generate_suffix (spnt, dbx_type)
struct VMS_DBG_Symbol *spnt; struct VMS_DBG_Symbol *spnt;
@ -1804,9 +1813,8 @@ generate_suffix (spnt, dbx_type)
rpush (DST_K_TYPSPEC, 1); rpush (DST_K_TYPSPEC, 1);
total_len += 4; total_len += 4;
rpush (total_len, 1); rpush (total_len, 1);
/* if the variable descriptor overflows the record, output a descriptor for /* If the variable descriptor overflows the record, output a descriptor
* a pointer to void. for a pointer to void. */
*/
if ((total_len >= MAX_DEBUG_RECORD) || overflow) if ((total_len >= MAX_DEBUG_RECORD) || overflow)
{ {
as_warn ("Variable descriptor %d too complicated. Defined as `void *'.", as_warn ("Variable descriptor %d too complicated. Defined as `void *'.",
@ -1818,17 +1826,16 @@ generate_suffix (spnt, dbx_type)
while (Lpnt < MAX_DEBUG_RECORD - 1) while (Lpnt < MAX_DEBUG_RECORD - 1)
Local[i++] = Local[++Lpnt]; Local[i++] = Local[++Lpnt];
Lpnt = i; Lpnt = i;
/* we use this for a reference to a structure that has already been defined */ /* we use this for reference to structure that has already been defined */
if (struct_number > 0) if (struct_number > 0)
{ {
VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
Lpnt = 0; Lpnt = 0;
VMS_Store_Struct (struct_number); VMS_Store_Struct (struct_number);
} }
/* We use this for a forward reference to a structure that has yet to be /* We use this for a forward reference to a structure that has yet to
* defined. We store four bytes of zero to make room for the actual address be defined. We store four bytes of zero to make room for the actual
* once it is known. address once it is known. */
*/
if (struct_number < 0) if (struct_number < 0)
{ {
struct_number = -struct_number; struct_number = -struct_number;
@ -1848,10 +1855,13 @@ generate_suffix (spnt, dbx_type)
Lpnt = 0; Lpnt = 0;
} }
/* "novel length" type doesn't work for simple atomic types */ /* "novel length" type doesn't work for simple atomic types */
#define USE_BITSTRING_DESCRIPTOR(t) ((t)->advanced == BASIC) #define USE_BITSTRING_DESCRIPTOR(t) ((t)->advanced == BASIC)
#undef SETUP_BASIC_TYPES #undef SETUP_BASIC_TYPES
/* This routine generates a type description for a bitfield. */
static void static void
bitfield_suffix (spnt, width) bitfield_suffix (spnt, width)
struct VMS_DBG_Symbol *spnt; struct VMS_DBG_Symbol *spnt;
@ -1872,10 +1882,12 @@ bitfield_suffix (spnt, width)
VMS_Store_Struct (spnt->struc_numb); /* output 4 more bytes */ VMS_Store_Struct (spnt->struc_numb); /* output 4 more bytes */
} }
/* Formally define a builtin type, so that it can serve as the target of /* Formally define a builtin type, so that it can serve as the target of
an indirect reference. It makes bitfield_suffix() easier by avoiding an indirect reference. It makes bitfield_suffix() easier by avoiding
the need to use a forward reference for the first occurrence of each the need to use a forward reference for the first occurrence of each
type used in a bitfield. */ type used in a bitfield. */
static void static void
setup_basic_type (spnt) setup_basic_type (spnt)
struct VMS_DBG_Symbol *spnt; struct VMS_DBG_Symbol *spnt;
@ -1925,11 +1937,12 @@ setup_basic_type (spnt)
return; return;
} }
/* This routine generates a symbol definition for a C symbol for the debugger. /* This routine generates a symbol definition for a C symbol for the debugger.
* It takes a psect and offset for global symbols; if psect < 0, then this is It takes a psect and offset for global symbols; if psect < 0, then this is
* a local variable and the offset is relative to FP. In this case it can a local variable and the offset is relative to FP. In this case it can
* be either a variable (Offset < 0) or a parameter (Offset > 0). be either a variable (Offset < 0) or a parameter (Offset > 0). */
*/
static void static void
VMS_DBG_record (spnt, Psect, Offset, Name) VMS_DBG_record (spnt, Psect, Offset, Name)
struct VMS_DBG_Symbol *spnt; struct VMS_DBG_Symbol *spnt;
@ -1972,22 +1985,22 @@ VMS_DBG_record (spnt, Psect, Offset, Name)
/* This routine parses the stabs entries in order to make the definition /* This routine parses the stabs entries in order to make the definition
* for the debugger of local symbols and function parameters for the debugger of local symbols and function parameters. */
*/
static void static void
VMS_local_stab_Parse (sp) VMS_local_stab_Parse (sp)
symbolS *sp; symbolS *sp;
{ {
struct VMS_DBG_Symbol *spnt;
char *pnt; char *pnt;
char *pnt1; char *pnt1;
char *str; char *str;
struct VMS_DBG_Symbol *spnt;
int dbx_type; int dbx_type;
dbx_type = 0; dbx_type = 0;
str = S_GET_NAME (sp); str = S_GET_NAME (sp);
pnt = (char *) strchr (str, ':'); pnt = (char *) strchr (str, ':');
if (pnt == (char *) NULL) if (!pnt)
return; /* no colon present */ return; /* no colon present */
pnt1 = pnt++; /* save this for later, and skip colon */ pnt1 = pnt++; /* save this for later, and skip colon */
if (*pnt == 'c') if (*pnt == 'c')
@ -2000,9 +2013,10 @@ VMS_local_stab_Parse (sp)
* this function to see if this parameter is assigned to a register. * this function to see if this parameter is assigned to a register.
*/ */
{ {
symbolS *sp1;
char *str1; char *str1;
char *pnt2; char *pnt2;
symbolS *sp1;
if (*pnt == 'p') if (*pnt == 'p')
{ {
for (sp1 = symbol_next (sp); sp1; sp1 = symbol_next (sp1)) for (sp1 = symbol_next (sp); sp1; sp1 = symbol_next (sp1))
@ -2011,8 +2025,9 @@ VMS_local_stab_Parse (sp)
continue; continue;
if (S_GET_RAW_TYPE (sp1) == N_FUN) if (S_GET_RAW_TYPE (sp1) == N_FUN)
{ {
char * pnt3=(char*) strchr (S_GET_NAME (sp1), ':') + 1; pnt2 = (char *) strchr (S_GET_NAME (sp1), ':') + 1;
if (*pnt3 == 'F' || *pnt3 == 'f') break; if (*pnt2 == 'F' || *pnt2 == 'f')
break;
} }
if (S_GET_RAW_TYPE (sp1) != N_RSYM) if (S_GET_RAW_TYPE (sp1) != N_RSYM)
continue; continue;
@ -2025,14 +2040,13 @@ VMS_local_stab_Parse (sp)
pnt2++; pnt2++;
str1++; str1++;
} }
if ((*str1 != ':') || (*pnt2 != ':')) if (*str1 == ':' && *pnt2 == ':')
continue; return; /* they are the same! lets skip this one */
return; /* they are the same! lets skip this one */
} /* for */ } /* for */
/* first find the dbx symbol type from list, and then find VMS type */
pnt++; /* skip p in case no register */ pnt++; /* skip p in case no register */
} /* if */ } /* if */
} /* p block */ } /* p block */
pnt = cvt_integer (pnt, &dbx_type); pnt = cvt_integer (pnt, &dbx_type);
spnt = find_symbol (dbx_type); spnt = find_symbol (dbx_type);
if (!spnt) if (!spnt)
@ -2043,17 +2057,18 @@ VMS_local_stab_Parse (sp)
return; return;
} }
/* This routine parses a stabs entry to find the information required to define
* a variable. It is used for global and static variables. /* This routine parses a stabs entry to find the information required
* Basically we need to know the address of the symbol. With older versions to define a variable. It is used for global and static variables.
* of the compiler, const symbols are Basically we need to know the address of the symbol. With older
* treated differently, in that if they are global they are written into the versions of the compiler, const symbols are treated differently, in
* text psect. The global symbol entry for such a const is actually written that if they are global they are written into the text psect. The
* as a program entry point (Yuk!!), so if we cannot find a symbol in the list global symbol entry for such a const is actually written as a program
* of psects, we must search the entry points as well. static consts are even entry point (Yuk!!), so if we cannot find a symbol in the list of
* harder, since they are never assigned a memory address. The compiler passes psects, we must search the entry points as well. static consts are
* a stab to tell us the value, but I am not sure what to do with it. even harder, since they are never assigned a memory address. The
*/ compiler passes a stab to tell us the value, but I am not sure what
to do with it. */
static void static void
VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect) VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect)
@ -2072,7 +2087,7 @@ VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect)
dbx_type = 0; dbx_type = 0;
str = S_GET_NAME (sp); str = S_GET_NAME (sp);
pnt = (char *) strchr (str, ':'); pnt = (char *) strchr (str, ':');
if (pnt == (char *) NULL) if (!pnt)
return; /* no colon present */ return; /* no colon present */
pnt1 = pnt; /* save this for later*/ pnt1 = pnt; /* save this for later*/
pnt++; pnt++;
@ -2080,33 +2095,33 @@ VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect)
{ {
pnt = cvt_integer (pnt + 1, &dbx_type); pnt = cvt_integer (pnt + 1, &dbx_type);
spnt = find_symbol (dbx_type); spnt = find_symbol (dbx_type);
if (spnt == (struct VMS_DBG_Symbol *) NULL) if (!spnt)
return; /*Dunno what this is*/ return; /*Dunno what this is*/
/* now we need to search the symbol table to find the psect and offset for /*
* this variable. * Now we need to search the symbol table to find the psect and
*/ * offset for this variable.
*/
*pnt1 = '\0'; *pnt1 = '\0';
vsp = VMS_Symbols; vsp = VMS_Symbols;
while (vsp != (struct VMS_Symbol *) NULL) while (vsp)
{ {
pnt = S_GET_NAME (vsp->Symbol); pnt = S_GET_NAME (vsp->Symbol);
if (pnt != (char *) NULL) if (pnt && *pnt++ == '_'
if (*pnt++ == '_') /* make sure name is the same and symbol type matches */
/* make sure name is the same, and make sure correct symbol type */ && strcmp (pnt, str) == 0
if ((strlen (pnt) == strlen (str)) && (strcmp (pnt, str) == 0) && (S_GET_RAW_TYPE (vsp->Symbol) == type1
&& ((S_GET_RAW_TYPE (vsp->Symbol) == type1) || || S_GET_RAW_TYPE (vsp->Symbol) == type2))
(S_GET_RAW_TYPE (vsp->Symbol) == type2))) break;
break;
vsp = vsp->Next; vsp = vsp->Next;
} }
if (vsp != (struct VMS_Symbol *) NULL) if (vsp)
{ {
VMS_DBG_record (spnt, vsp->Psect_Index, vsp->Psect_Offset, str); VMS_DBG_record (spnt, vsp->Psect_Index, vsp->Psect_Offset, str);
*pnt1 = ':'; /* and restore the string */ *pnt1 = ':'; /* and restore the string */
return; return;
} }
/* the symbol was not in the symbol list, but it may be an "entry point" /* The symbol was not in the symbol list, but it may be an
if it was a constant */ "entry point" if it was a constant. */
for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1)) for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1))
{ {
/* /*
@ -2138,9 +2153,10 @@ VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect)
S_GET_VALUE (sp1), S_GET_VALUE (sp1),
str); str);
*pnt1 = ':'; *pnt1 = ':';
*S_GET_NAME (sp1) = 'L'; /* fool assembler to not output this as a routine in the TBT */
/* fool assembler to not output this pnt1 = S_GET_NAME (sp1);
* as a routine in the TBT */ *pnt1 = 'L';
S_SET_NAME (sp1, pnt1);
return; return;
} }
} }
@ -4975,7 +4991,7 @@ local_symbols_DST (s0P, Current_Routine)
char *s0P_name, *pnt0, *pnt1; char *s0P_name, *pnt0, *pnt1;
s0P_name = S_GET_NAME (s0P); s0P_name = S_GET_NAME (s0P);
if (*++s0P_name != '_') if (*s0P_name++ != '_')
return; return;
for (s1P = Current_Routine; s1P; s1P = symbol_next (s1P)) for (s1P = Current_Routine; s1P; s1P = symbol_next (s1P))