mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-28 07:08:01 +08:00
vms updates
This commit is contained in:
@ -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))
|
||||
|
Reference in New Issue
Block a user