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 *
find_file (sp)
symbolS *sp;
@ -1387,62 +1388,61 @@ find_file (sp)
fpnt->same_file_fpnt = same_file;
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
* sees an invalid character. The return value is the address of the character
* just past the last character read. No error is generated.
*/
/* This routine converts a number string into an integer, and stops when
it sees an invalid character. The return value is the address of the
character just past the last character read. No error is generated. */
static char *
cvt_integer (str, rtn)
char *str;
int *rtn;
{
int ival, neg;
neg = *str == '-' ? ++str, -1 : 1;
ival = 0;
while ((*str <= '9') && (*str >= '0'))
int ival = 0, sgn = 1;
if (*str == '-')
sgn = -1, ++str;
while (*str >= '0' && *str <= '9')
ival = 10 * ival + *str++ - '0';
*rtn = neg * ival;
*rtn = sgn * ival;
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 syntax for a structure element, and thus it gets mightily confused
/*
* The following functions and definitions are used to generate object
* records that will describe program variables to the VMS debugger.
*
* We also use this to strip the PsectAttribute hack from the name before we
* write a debugger record */
* 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 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 *
fix_name (pnt)
char *pnt;
{
char *pnt1;
/*
* Kill any leading "_"
*/
/* Kill any leading "_". */
if (*pnt == '_')
pnt++;
/*
* Is there a Psect Attribute to skip??
*/
/* Is there a Psect Attribute to skip?? */
if (HAS_PSECT_ATTRIBUTES (pnt))
{
/*
* Yes: Skip it
*/
/* Yes: Skip it. */
pnt += PSECT_ATTRIBUTES_STRING_LENGTH;
while (*pnt)
{
@ -1454,21 +1454,22 @@ fix_name (pnt)
pnt++;
}
}
/* Here we fix the .this -> $this conversion */
/* Here we fix the .this -> $this conversion. */
for (pnt1 = pnt; *pnt1 != 0; pnt1++)
{
if (*pnt1 == '.')
*pnt1 = '$';
}
if (*pnt1 == '.')
*pnt1 = '$';
return pnt;
}
/* 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
* 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
* outermost level, and thus symbol_name points to the symbol name.
*/
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
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. */
static char *
get_struct_name (str)
char *str;
@ -1491,7 +1492,10 @@ get_struct_name (str)
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 *
find_symbol (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
array_suffix (spnt2)
struct VMS_DBG_Symbol *spnt2;
@ -1601,7 +1607,7 @@ array_suffix (spnt2)
while (spnt->advanced != ARRAY)
{
spnt = find_symbol (spnt->type2);
if (spnt == (struct VMS_DBG_Symbol *) NULL)
if (!spnt)
return;
}
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
* 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.
*/
/* 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
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
new_forward_ref (dbx_type)
int dbx_type;
@ -1663,12 +1670,13 @@ new_forward_ref (dbx_type)
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
* all, and then builds the descriptor backwards. It is easiest to do 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.
*/
/* This routine generates the variable descriptor used to describe non-basic
variables. It calls itself recursively until it gets to the bottom of it
all, and then builds the descriptor backwards. It is easiest to do 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
gen1 (spnt, array_suffix_len)
struct VMS_DBG_Symbol *spnt;
@ -1767,12 +1775,13 @@ gen1 (spnt, array_suffix_len)
return 0;
}
/* 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
* 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
* to get a complete descriptor (i.e. struct reference, array suffix ).
*/
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
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). */
static void
generate_suffix (spnt, dbx_type)
struct VMS_DBG_Symbol *spnt;
@ -1804,9 +1813,8 @@ generate_suffix (spnt, dbx_type)
rpush (DST_K_TYPSPEC, 1);
total_len += 4;
rpush (total_len, 1);
/* if the variable descriptor overflows the record, output a descriptor for
* a pointer to void.
*/
/* If the variable descriptor overflows the record, output a descriptor
for a pointer to void. */
if ((total_len >= MAX_DEBUG_RECORD) || overflow)
{
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)
Local[i++] = Local[++Lpnt];
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)
{
VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
Lpnt = 0;
VMS_Store_Struct (struct_number);
}
/* We use this for a forward reference to a structure that has yet to be
* defined. We store four bytes of zero to make room for the actual address
* once it is known.
*/
/* We use this for a forward reference to a structure that has yet to
be defined. We store four bytes of zero to make room for the actual
address once it is known. */
if (struct_number < 0)
{
struct_number = -struct_number;
@ -1848,10 +1855,13 @@ generate_suffix (spnt, dbx_type)
Lpnt = 0;
}
/* "novel length" type doesn't work for simple atomic types */
#define USE_BITSTRING_DESCRIPTOR(t) ((t)->advanced == BASIC)
#undef SETUP_BASIC_TYPES
/* This routine generates a type description for a bitfield. */
static void
bitfield_suffix (spnt, width)
struct VMS_DBG_Symbol *spnt;
@ -1872,10 +1882,12 @@ bitfield_suffix (spnt, width)
VMS_Store_Struct (spnt->struc_numb); /* output 4 more bytes */
}
/* Formally define a builtin type, so that it can serve as the target of
an indirect reference. It makes bitfield_suffix() easier by avoiding
the need to use a forward reference for the first occurrence of each
type used in a bitfield. */
static void
setup_basic_type (spnt)
struct VMS_DBG_Symbol *spnt;
@ -1925,11 +1937,12 @@ setup_basic_type (spnt)
return;
}
/* 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
* 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).
*/
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
be either a variable (Offset < 0) or a parameter (Offset > 0). */
static void
VMS_DBG_record (spnt, Psect, Offset, Name)
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
* for the debugger of local symbols and function parameters
*/
for the debugger of local symbols and function parameters. */
static void
VMS_local_stab_Parse (sp)
symbolS *sp;
{
struct VMS_DBG_Symbol *spnt;
char *pnt;
char *pnt1;
char *str;
struct VMS_DBG_Symbol *spnt;
int dbx_type;
dbx_type = 0;
str = S_GET_NAME (sp);
pnt = (char *) strchr (str, ':');
if (pnt == (char *) NULL)
if (!pnt)
return; /* no colon present */
pnt1 = pnt++; /* save this for later, and skip colon */
if (*pnt == 'c')
@ -2000,9 +2013,10 @@ VMS_local_stab_Parse (sp)
* this function to see if this parameter is assigned to a register.
*/
{
symbolS *sp1;
char *str1;
char *pnt2;
symbolS *sp1;
if (*pnt == 'p')
{
for (sp1 = symbol_next (sp); sp1; sp1 = symbol_next (sp1))
@ -2011,8 +2025,9 @@ VMS_local_stab_Parse (sp)
continue;
if (S_GET_RAW_TYPE (sp1) == N_FUN)
{
char * pnt3=(char*) strchr (S_GET_NAME (sp1), ':') + 1;
if (*pnt3 == 'F' || *pnt3 == 'f') break;
pnt2 = (char *) strchr (S_GET_NAME (sp1), ':') + 1;
if (*pnt2 == 'F' || *pnt2 == 'f')
break;
}
if (S_GET_RAW_TYPE (sp1) != N_RSYM)
continue;
@ -2025,14 +2040,13 @@ VMS_local_stab_Parse (sp)
pnt2++;
str1++;
}
if ((*str1 != ':') || (*pnt2 != ':'))
continue;
return; /* they are the same! lets skip this one */
if (*str1 == ':' && *pnt2 == ':')
return; /* they are the same! lets skip this one */
} /* for */
/* first find the dbx symbol type from list, and then find VMS type */
pnt++; /* skip p in case no register */
} /* if */
} /* p block */
pnt = cvt_integer (pnt, &dbx_type);
spnt = find_symbol (dbx_type);
if (!spnt)
@ -2043,17 +2057,18 @@ VMS_local_stab_Parse (sp)
return;
}
/* This routine parses a stabs entry to find the information required to define
* a variable. It is used for global and static variables.
* Basically we need to know the address of the symbol. With older versions
* of the compiler, const symbols are
* treated differently, in that if they are global they are written into the
* text psect. The global symbol entry for such a const is actually written
* as a program entry point (Yuk!!), so if we cannot find a symbol in the list
* of psects, we must search the entry points as well. static consts are 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.
*/
/* This routine parses a stabs entry to find the information required
to define a variable. It is used for global and static variables.
Basically we need to know the address of the symbol. With older
versions of the compiler, const symbols are treated differently, in
that if they are global they are written into the text psect. The
global symbol entry for such a const is actually written as a program
entry point (Yuk!!), so if we cannot find a symbol in the list of
psects, we must search the entry points as well. static consts are
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
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;
str = S_GET_NAME (sp);
pnt = (char *) strchr (str, ':');
if (pnt == (char *) NULL)
if (!pnt)
return; /* no colon present */
pnt1 = pnt; /* save this for later*/
pnt++;
@ -2080,33 +2095,33 @@ VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect)
{
pnt = cvt_integer (pnt + 1, &dbx_type);
spnt = find_symbol (dbx_type);
if (spnt == (struct VMS_DBG_Symbol *) NULL)
if (!spnt)
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';
vsp = VMS_Symbols;
while (vsp != (struct VMS_Symbol *) NULL)
while (vsp)
{
pnt = S_GET_NAME (vsp->Symbol);
if (pnt != (char *) NULL)
if (*pnt++ == '_')
/* make sure name is the same, and make sure correct symbol type */
if ((strlen (pnt) == strlen (str)) && (strcmp (pnt, str) == 0)
&& ((S_GET_RAW_TYPE (vsp->Symbol) == type1) ||
(S_GET_RAW_TYPE (vsp->Symbol) == type2)))
break;
if (pnt && *pnt++ == '_'
/* make sure name is the same and symbol type matches */
&& strcmp (pnt, str) == 0
&& (S_GET_RAW_TYPE (vsp->Symbol) == type1
|| S_GET_RAW_TYPE (vsp->Symbol) == type2))
break;
vsp = vsp->Next;
}
if (vsp != (struct VMS_Symbol *) NULL)
if (vsp)
{
VMS_DBG_record (spnt, vsp->Psect_Index, vsp->Psect_Offset, str);
*pnt1 = ':'; /* and restore the string */
return;
}
/* the symbol was not in the symbol list, but it may be an "entry point"
if it was a constant */
/* The symbol was not in the symbol list, but it may be an
"entry point" if it was a constant. */
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),
str);
*pnt1 = ':';
*S_GET_NAME (sp1) = 'L';
/* fool assembler to not output this
* as a routine in the TBT */
/* fool assembler to not output this as a routine in the TBT */
pnt1 = S_GET_NAME (sp1);
*pnt1 = 'L';
S_SET_NAME (sp1, pnt1);
return;
}
}
@ -4975,7 +4991,7 @@ local_symbols_DST (s0P, Current_Routine)
char *s0P_name, *pnt0, *pnt1;
s0P_name = S_GET_NAME (s0P);
if (*++s0P_name != '_')
if (*s0P_name++ != '_')
return;
for (s1P = Current_Routine; s1P; s1P = symbol_next (s1P))