/* Support routines for decoding "stabs" debugging information format.
- Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 1997
+ Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
Free Software Foundation, Inc.
This file is part of GDB.
static int
copy_cfront_struct_fields PARAMS ((struct field_info *, struct type *,
- struct objfile *));
+ struct objfile *));
static char *
get_cfront_method_physname PARAMS ((char *));
static int
read_cfront_baseclasses PARAMS ((struct field_info *, char **,
- struct type *, struct objfile *));
+ struct type *, struct objfile *));
static int
read_cfront_static_fields PARAMS ((struct field_info *, char**,
- struct type *, struct objfile *));
+ struct type *, struct objfile *));
static int
read_cfront_member_functions PARAMS ((struct field_info *, char **,
- struct type *, struct objfile *));
+ struct type *, struct objfile *));
/* end new functions added for cfront support */
+static void
+add_live_range PARAMS ((struct objfile *, struct symbol *,
+ CORE_ADDR, CORE_ADDR));
+static void
+resolve_live_range PARAMS ((struct objfile *, struct symbol *, char *));
+
+static int
+process_reference PARAMS ((char **string));
+
+static CORE_ADDR
+ref_search_value PARAMS ((int refnum));
+
+static void
+ref_init PARAMS ((void));
+
+static int
+resolve_symbol_reference PARAMS ((struct objfile *, struct symbol *, char *));
static const char vptr_name[] = { '_','v','p','t','r',CPLUS_MARKER,'\0' };
static const char vb_name[] = { '_','v','b',CPLUS_MARKER,'\0' };
/* search ahead to find the start of the mangled suffix */
if (*p == '_' && *(p+1)=='_') /* compiler generated; probably a ctor/dtor */
p += 2;
- while (p && ((p+1) - fname) < strlen (fname) && *(p+1) != '_')
+ while (p && (unsigned) ((p+1) - fname) < strlen (fname) && *(p+1) != '_')
p = strchr (p, '_');
if (!(p && *p == '_' && *(p+1) == '_'))
error ("Invalid mangled function name %s",fname);
char * bname; /* base class name */
struct symbol * bsym; /* base class */
char * p1, * p2;
- p1 = strchr(*pp,' ');
- p2 = strchr(*pp,';');
+ p1 = strchr (*pp,' ');
+ p2 = strchr (*pp,';');
if (p1<p2)
- bname = get_substring(pp,' ');
+ bname = get_substring (pp,' ');
else
- bname = get_substring(pp,';');
+ bname = get_substring (pp,';');
if (!bname || !*bname)
{
complain (&msg_unknown, *pp);
*/
static int
-read_cfront_member_functions(fip, pp, type, objfile)
+read_cfront_member_functions (fip, pp, type, objfile)
struct field_info *fip;
char **pp;
struct type *type;
struct objfile *objfile;
- {
+{
/* This code extracted from read_member_functions
so as to do the similar thing for our funcs */
struct next_fnfield *new_sublist;
char *main_fn_name;
char * fname;
- struct symbol * ref_func=0;
+ struct symbol * ref_func = 0;
- /* Process each list until we find something that is not a member function
- or find the end of the functions. */
+ /* Process each list until we find the end of the member functions.
+ eg: p = "__ct__1AFv foo__1AFv ;;;" */
- /* eg: p = "__ct__1AFv foo__1AFv ;;;" */
STABS_CONTINUE (pp, objfile); /* handle \\ */
- while (**pp!=';' && (fname = get_substring(pp,' '),fname))
+
+ while (**pp != ';' && (fname = get_substring (pp, ' '), fname))
{
- int is_static=0;
- int sublist_count=0;
+ int is_static = 0;
+ int sublist_count = 0;
char * pname;
- if (fname[0]=='*') /* static member */
+ if (fname[0] == '*') /* static member */
{
is_static=1;
sublist_count++;
fname++;
}
- ref_func = lookup_symbol (fname, 0, VAR_NAMESPACE, 0, 0); /*demangled_name*/
+ ref_func = lookup_symbol (fname, 0, VAR_NAMESPACE, 0, 0); /* demangled name */
if (!ref_func)
{
static struct complaint msg = {"\
if (dem != NULL)
{
dem_p = strrchr (dem, ':');
- if (dem_p != 0 && *(dem_p-1)==':')
+ if (dem_p != 0 && *(dem_p-1) == ':')
dem_p++;
/* get rid of args */
dem_args = strchr (dem_p, '(');
if (dem_args == NULL)
- dem_len = strlen(dem_p);
- else
- dem_len = dem_args - dem_p;
- main_fn_name =
+ dem_len = strlen (dem_p);
+ else
+ dem_len = dem_args - dem_p;
+ main_fn_name =
obsavestring (dem_p, dem_len, &objfile -> type_obstack);
- }
- else
- {
- main_fn_name =
- obsavestring (fname, strlen(fname), &objfile -> type_obstack);
- }
- } /* end of code for cfront work around */
-
- new_fnlist -> fn_fieldlist.name = main_fn_name;
+ }
+ else
+ {
+ main_fn_name =
+ obsavestring (fname, strlen (fname), &objfile -> type_obstack);
+ }
+ } /* end of code for cfront work around */
+
+ new_fnlist -> fn_fieldlist.name = main_fn_name;
- /*-------------------------------------------------*/
- /* Set up the sublists
- Sublists are stuff like args, static, visibility, etc.
- so in ARM, we have to set that info some other way.
- Multiple sublists happen if overloading
- eg: foo::26=##1;:;2A.;
- In g++, we'd loop here thru all the sublists... */
- new_sublist =
+ /*-------------------------------------------------*/
+ /* Set up the sublists
+ Sublists are stuff like args, static, visibility, etc.
+ so in ARM, we have to set that info some other way.
+ Multiple sublists happen if overloading
+ eg: foo::26=##1;:;2A.;
+ In g++, we'd loop here thru all the sublists... */
+
+ new_sublist =
(struct next_fnfield *) xmalloc (sizeof (struct next_fnfield));
- make_cleanup (free, new_sublist);
- memset (new_sublist, 0, sizeof (struct next_fnfield));
+ make_cleanup (free, new_sublist);
+ memset (new_sublist, 0, sizeof (struct next_fnfield));
- /* eat 1; from :;2A.; */
- new_sublist -> fn_field.type = SYMBOL_TYPE(ref_func); /* normally takes a read_type */
- /* make this type look like a method stub for gdb */
- TYPE_FLAGS (new_sublist -> fn_field.type) |= TYPE_FLAG_STUB;
- TYPE_CODE (new_sublist -> fn_field.type) = TYPE_CODE_METHOD;
-
- /* If this is just a stub, then we don't have the real name here. */
- if (TYPE_FLAGS (new_sublist -> fn_field.type) & TYPE_FLAG_STUB)
- {
- if (!TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type))
- TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type) = type;
- new_sublist -> fn_field.is_stub = 1;
- }
- /* physname used later in mangling; eg PFs_i,5 for foo__1aFPFs_i
- physname gets strcat'd in order to recreate the onto mangled name */
- pname = get_cfront_method_physname(fname);
- new_sublist -> fn_field.physname = savestring (pname, strlen(pname));
-
+ /* eat 1; from :;2A.; */
+ new_sublist -> fn_field.type = SYMBOL_TYPE(ref_func); /* normally takes a read_type */
+ /* Make this type look like a method stub for gdb */
+ TYPE_FLAGS (new_sublist -> fn_field.type) |= TYPE_FLAG_STUB;
+ TYPE_CODE (new_sublist -> fn_field.type) = TYPE_CODE_METHOD;
+
+ /* If this is just a stub, then we don't have the real name here. */
+ if (TYPE_FLAGS (new_sublist -> fn_field.type) & TYPE_FLAG_STUB)
+ {
+ if (!TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type))
+ TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type) = type;
+ new_sublist -> fn_field.is_stub = 1;
+ }
- /* Set this member function's visibility fields.
- Unable to distinguish access from stabs definition!
- Assuming public for now. FIXME!
- (for private, set new_sublist->fn_field.is_private = 1,
- for public, set new_sublist->fn_field.is_protected = 1) */
+ /* physname used later in mangling; eg PFs_i,5 for foo__1aFPFs_i
+ physname gets strcat'd in order to recreate the onto mangled name */
+ pname = get_cfront_method_physname (fname);
+ new_sublist -> fn_field.physname = savestring (pname, strlen (pname));
+
+
+ /* Set this member function's visibility fields.
+ Unable to distinguish access from stabs definition!
+ Assuming public for now. FIXME!
+ (for private, set new_sublist->fn_field.is_private = 1,
+ for public, set new_sublist->fn_field.is_protected = 1) */
- /* Unable to distinguish const/volatile from stabs definition!
- Assuming normal for now. FIXME! */
+ /* Unable to distinguish const/volatile from stabs definition!
+ Assuming normal for now. FIXME! */
- new_sublist -> fn_field.is_const = 0;
- new_sublist -> fn_field.is_volatile = 0; /* volatile not implemented in cfront */
+ new_sublist -> fn_field.is_const = 0;
+ new_sublist -> fn_field.is_volatile = 0; /* volatile not implemented in cfront */
- /* set virtual/static function info
- How to get vtable offsets ?
- Assuming normal for now FIXME!!
- For vtables, figure out from whence this virtual function came.
- It may belong to virtual function table of
- one of its baseclasses.
- set:
- new_sublist -> fn_field.voffset = vtable offset,
- new_sublist -> fn_field.fcontext = look_ahead_type;
- where look_ahead_type is type of baseclass */
- if (is_static)
- new_sublist -> fn_field.voffset = VOFFSET_STATIC;
- else /* normal member function. */
- new_sublist -> fn_field.voffset = 0;
- new_sublist -> fn_field.fcontext = 0;
+ /* Set virtual/static function info
+ How to get vtable offsets ?
+ Assuming normal for now FIXME!!
+ For vtables, figure out from whence this virtual function came.
+ It may belong to virtual function table of
+ one of its baseclasses.
+ set:
+ new_sublist -> fn_field.voffset = vtable offset,
+ new_sublist -> fn_field.fcontext = look_ahead_type;
+ where look_ahead_type is type of baseclass */
+ if (is_static)
+ new_sublist -> fn_field.voffset = VOFFSET_STATIC;
+ else /* normal member function. */
+ new_sublist -> fn_field.voffset = 0;
+ new_sublist -> fn_field.fcontext = 0;
- /* prepare new sublist */
- new_sublist -> next = sublist;
- sublist = new_sublist;
- length++;
- /* In g++, we loop thu sublists - now we set from function */
-
- new_fnlist -> fn_fieldlist.fn_fields = (struct fn_field *)
- obstack_alloc (&objfile -> type_obstack,
- sizeof (struct fn_field) * length);
- memset (new_fnlist -> fn_fieldlist.fn_fields, 0,
- sizeof (struct fn_field) * length);
- for (i = length; (i--, sublist); sublist = sublist -> next)
- {
- new_fnlist -> fn_fieldlist.fn_fields[i] = sublist -> fn_field;
- }
-
- new_fnlist -> fn_fieldlist.length = length;
- new_fnlist -> next = fip -> fnlist;
- fip -> fnlist = new_fnlist;
- nfn_fields++;
- total_length += length;
- STABS_CONTINUE (pp, objfile); /* handle \\ */
- } /* end of loop */
-
- if (nfn_fields)
+ /* Prepare new sublist */
+ new_sublist -> next = sublist;
+ sublist = new_sublist;
+ length++;
+
+ /* In g++, we loop thu sublists - now we set from functions. */
+ new_fnlist -> fn_fieldlist.fn_fields = (struct fn_field *)
+ obstack_alloc (&objfile -> type_obstack,
+ sizeof (struct fn_field) * length);
+ memset (new_fnlist -> fn_fieldlist.fn_fields, 0,
+ sizeof (struct fn_field) * length);
+ for (i = length; (i--, sublist); sublist = sublist -> next)
{
- /* type should already have space */
- TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
- TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * nfn_fields);
- memset (TYPE_FN_FIELDLISTS (type), 0,
- sizeof (struct fn_fieldlist) * nfn_fields);
- TYPE_NFN_FIELDS (type) = nfn_fields;
- TYPE_NFN_FIELDS_TOTAL (type) = total_length;
+ new_fnlist -> fn_fieldlist.fn_fields[i] = sublist -> fn_field;
}
+
+ new_fnlist -> fn_fieldlist.length = length;
+ new_fnlist -> next = fip -> fnlist;
+ fip -> fnlist = new_fnlist;
+ nfn_fields++;
+ total_length += length;
+ STABS_CONTINUE (pp, objfile); /* handle \\ */
+ } /* end of loop */
- /* end of scope for reading member func */
+ if (nfn_fields)
+ {
+ /* type should already have space */
+ TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
+ TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * nfn_fields);
+ memset (TYPE_FN_FIELDLISTS (type), 0,
+ sizeof (struct fn_fieldlist) * nfn_fields);
+ TYPE_NFN_FIELDS (type) = nfn_fields;
+ TYPE_NFN_FIELDS_TOTAL (type) = total_length;
+ }
- /* eg: ";;" */
- /* skip trailing ';' and bump count of number of fields seen */
- if (**pp == ';')
- (*pp)++;
- else
- return 0;
+ /* end of scope for reading member func */
+
+ /* eg: ";;" */
+
+ /* Skip trailing ';' and bump count of number of fields seen */
+ if (**pp == ';')
+ (*pp)++;
+ else
+ return 0;
return 1;
}
while parsing the stabs. The main need for this function is
to add information such as methods to classes.
Examples of "p": "sA;;__ct__1AFv foo__1AFv ;;;" */
-void
-resolve_cfront_continuation(objfile, sym, p)
+int
+resolve_cfront_continuation (objfile, sym, p)
struct objfile * objfile;
struct symbol * sym;
char * p;
struct type *type;
struct cleanup *back_to;
- /* need to make sure that fi isn't gunna conflict with struct
+ /* Need to make sure that fi isn't gunna conflict with struct
in case struct already had some fnfs */
fi.list = NULL;
fi.fnlist = NULL;
back_to = make_cleanup (null_cleanup, 0);
- /* we only accept structs, classes and unions at the moment.
+ /* We only accept structs, classes and unions at the moment.
Other continuation types include t (typedef), r (long dbl), ...
We may want to add support for them as well;
right now they are handled by duplicating the symbol information
if (*p != 's' /* structs */
&& *p != 'c' /* class */
&& *p != 'u') /* union */
- return; /* only handle C++ types */
+ return 0; /* only handle C++ types */
p++;
- /* get symbol typs name and validate
+ /* Get symbol typs name and validate
eg: p = "A;;__ct__1AFv foo__1AFv ;;;" */
- sname = get_substring(&p,';');
- if (!sname || strcmp(sname,SYMBOL_NAME(sym)))
- error("Internal error: base symbol type name does not match\n");
+ sname = get_substring (&p, ';');
+ if (!sname || strcmp (sname, SYMBOL_NAME(sym)))
+ error ("Internal error: base symbol type name does not match\n");
- /* find symbol's internal gdb reference */
- ref_sym = lookup_symbol (SYMBOL_NAME(sym), 0, STRUCT_NAMESPACE, 0, 0); /*demangled_name*/
- /* This is the real sym that we want;
+ /* Find symbol's internal gdb reference using demangled_name.
+ This is the real sym that we want;
sym was a temp hack to make debugger happy */
- /* ref_sym should already have space */
+ ref_sym = lookup_symbol (SYMBOL_NAME(sym), 0, STRUCT_NAMESPACE, 0, 0);
type = SYMBOL_TYPE(ref_sym);
|| !read_struct_fields (&fi, &p, type, objfile) */
|| !copy_cfront_struct_fields (&fi, type, objfile)
|| !read_cfront_member_functions (&fi, &p, type, objfile)
- || !read_cfront_static_fields(&fi, &p, type, objfile)
+ || !read_cfront_static_fields (&fi, &p, type, objfile)
|| !attach_fields_to_type (&fi, type, objfile)
|| !attach_fn_fields_to_type (&fi, type)
/* g++ does this next, but cfront doesn't seem to have this:
}
do_cleanups (back_to);
+ return 0;
}
/* End of code added to support parsing of ARM/Cfront stabs strings */
+/* This routine fixes up symbol references/aliases to point to the original
+ symbol definition. */
+
+static int
+resolve_symbol_reference (objfile, sym, p)
+ struct objfile *objfile;
+ struct symbol *sym;
+ char *p;
+{
+ int refnum;
+ struct symbol *ref_sym=0;
+ struct alias_list *alias;
+
+ /* If this is not a symbol reference return now. */
+ if (*p != '#')
+ return 0;
+
+ /* Use "#<num>" as the name; we'll fix the name later.
+ We stored the original symbol name as "#<id>=<name>"
+ so we can now search for "#<id>" to resolving the reference.
+ We'll fix the names later by removing the "#<id>" or "#<id>=" */
+
+ /*---------------------------------------------------------*/
+ /* Get the reference id number, and
+ advance p past the names so we can parse the rest.
+ eg: id=2 for p : "2=", "2=z:r(0,1)" "2:r(0,1);l(#5,#6),l(#7,#4)" */
+ /*---------------------------------------------------------*/
+
+ /* This gets reference name from string. sym may not have a name. */
+
+ /* Get the reference number associated with the reference id in the
+ gdb stab string. From that reference number, get the main/primary
+ symbol for this alias. */
+ refnum = process_reference (&p);
+ ref_sym = ref_search (refnum);
+ if (!ref_sym)
+ error ("error: symbol for reference not found.\n");
+
+
+ /* Parse the stab of the referencing symbol
+ now that we have the referenced symbol.
+ Add it as a new symbol and a link back to the referenced symbol.
+ eg: p : "=", "=z:r(0,1)" ":r(0,1);l(#5,#6),l(#7,#4)" */
+
+
+ /* If the stab symbol table and string contain:
+ RSYM 0 5 00000000 868 #15=z:r(0,1)
+ LBRAC 0 0 00000000 899 #5=
+ SLINE 0 16 00000003 923 #6=
+ Then the same symbols can be later referenced by:
+ RSYM 0 5 00000000 927 #15:r(0,1);l(#5,#6)
+ This is used in live range splitting to:
+ 1) specify that a symbol (#15) is actually just a new storage
+ class for a symbol (#15=z) which was previously defined.
+ 2) specify that the beginning and ending ranges for a symbol
+ (#15) are the values of the beginning (#5) and ending (#6)
+ symbols. */
+
+ /* Read number as reference id.
+ eg: p : "=", "=z:r(0,1)" ":r(0,1);l(#5,#6),l(#7,#4)" */
+ /* FIXME! Might I want to use SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+ in case of "l(0,0)"? */
+
+ /*--------------------------------------------------*/
+ /* Add this symbol to the reference list. */
+ /*--------------------------------------------------*/
+
+ alias = (struct alias_list *) obstack_alloc (&objfile->type_obstack,
+ sizeof (struct alias_list));
+ if (!alias)
+ error ("Unable to allocate alias list memory");
+
+ alias->next = 0;
+ alias->sym = sym;
+
+ if (!SYMBOL_ALIASES (ref_sym))
+ {
+ SYMBOL_ALIASES (ref_sym) = alias;
+ }
+ else
+ {
+ struct alias_list *temp;
+
+ /* Get to the end of the list. */
+ for (temp = SYMBOL_ALIASES (ref_sym);
+ temp->next;
+ temp = temp->next);
+ ;
+ temp->next = alias;
+ }
+
+ /* Want to fix up name so that other functions (eg. valops)
+ will correctly print the name.
+ Don't add_symbol_to_list so that lookup_symbol won't find it.
+ nope... needed for fixups. */
+ SYMBOL_NAME (sym) = SYMBOL_NAME (ref_sym);
+
+ /* Done! */
+ return 0;
+}
+
+#define MAX_CHUNK_REFS 100
+#define REF_CHUNK_SIZE \
+ MAX_CHUNK_REFS * sizeof (struct ref_map_s)
+#define REF_MAP_SIZE(ref_chunk) \
+ ref_chunk * REF_CHUNK_SIZE
+
+/* Structure for storing pointers to reference definitions for fast lookup
+ during "process_later". */
+static struct ref_map_s
+{
+ char *stabs;
+ CORE_ADDR value;
+ struct symbol *sym;
+} *ref_map;
+
+/* Ptr to free cell in chunk's linked list. */
+static int ref_count = 0;
+
+/* Number of chunks malloced. */
+static int ref_chunk = 0;
+
+/* Initialize our list of references.
+ This should be called before any symbol table is read. */
+
+static void
+ref_init ()
+{
+ ref_count = 0;
+ ref_chunk = 0;
+}
+
+/* Create array of pointers mapping refids to symbols and stab strings.
+ Add pointers to reference definition symbols and/or their values as we
+ find them, using their reference numbers as our index.
+ These will be used later when we resolve references. */
+void
+ref_add (refnum, sym, stabs, value)
+ int refnum;
+ struct symbol *sym;
+ char *stabs;
+ CORE_ADDR value;
+{
+ if (ref_count == 0)
+ ref_init ();
+ if (refnum >= ref_count)
+ ref_count = refnum + 1;
+ if (ref_count > ref_chunk * MAX_CHUNK_REFS)
+ {
+ int new_slots = ref_count - ref_chunk * MAX_CHUNK_REFS;
+ int new_chunks = new_slots / MAX_CHUNK_REFS + 1;
+ ref_map = (struct ref_map_s *)
+ xrealloc (ref_map, REF_MAP_SIZE(ref_chunk + new_chunks));
+ if (!ref_map)
+ error ("no more free slots in chain\n");
+ memset (ref_map + REF_MAP_SIZE(ref_chunk), 0, new_chunks * REF_CHUNK_SIZE);
+ ref_chunk += new_chunks;
+ }
+ ref_map[refnum].stabs = stabs;
+ ref_map[refnum].sym = sym;
+ ref_map[refnum].value = value;
+}
+
+/* Return defined sym for the reference REFNUM. */
+struct symbol *
+ref_search (refnum)
+ int refnum;
+{
+ if (refnum < 0 || refnum > ref_count)
+ return 0;
+ return ref_map[refnum].sym;
+}
+
+/* Return value for the reference REFNUM. */
+
+static CORE_ADDR
+ref_search_value (refnum)
+ int refnum;
+{
+ if (refnum < 0 || refnum > ref_count)
+ return 0;
+ return ref_map[refnum].value;
+}
+
+/* Parse a reference id in STRING and return the resulting
+ reference number. Move STRING beyond the reference id. */
+
+static int
+process_reference (string)
+ char **string;
+{
+ char *p;
+ int refnum = 0;
+
+ if (**string != '#')
+ return 0;
+
+ /* Advance beyond the initial '#'. */
+ p = *string + 1;
+
+ /* Read number as reference id. */
+ while (*p && isdigit (*p))
+ {
+ refnum = refnum * 10 + *p - '0';
+ p++;
+ }
+ *string = p;
+ return refnum;
+}
+
+/* If STRING defines a reference, store away a pointer to the reference
+ definition for later use. Return the reference number. */
+
+int
+symbol_reference_defined (string)
+ char **string;
+{
+ char *p = *string;
+ int refnum = 0;
+
+ refnum = process_reference (&p);
+
+ /* Defining symbols end in '=' */
+ if (*p == '=')
+ {
+ /* Symbol is being defined here. */
+ *string = p + 1;
+ return refnum;
+ }
+ else
+ {
+ /* Must be a reference. Either the symbol has already been defined,
+ or this is a forward reference to it. */
+ *string = p;
+ return -1;
+ }
+}
+
/* ARGSUSED */
struct symbol *
define_symbol (valu, string, desc, type, objfile)
while (p[1] == ':')
{
p += 2;
- p = strchr(p, ':');
+ p = strchr (p, ':');
}
/* If a nameless stab entry, all we need is the type, not the symbol.
goto normal; /* Do *something* with it */
}
}
+ else if (string[0] == '#')
+ {
+ /* Special GNU C extension for referencing symbols. */
+ char *s;
+ int refnum, nlen;
+
+ /* If STRING defines a new reference id, then add it to the
+ reference map. Else it must be referring to a previously
+ defined symbol, so add it to the alias list of the previously
+ defined symbol. */
+ s = string;
+ refnum = symbol_reference_defined (&s);
+ if (refnum >= 0)
+ ref_add (refnum, sym, string, SYMBOL_VALUE (sym));
+ else
+ resolve_symbol_reference (objfile, sym, string);
+
+ /* S..P contains the name of the symbol. We need to store
+ the correct name into SYMBOL_NAME. */
+ nlen = p - s;
+ if (refnum >= 0)
+ {
+ if (nlen > 0)
+ {
+ SYMBOL_NAME (sym) = (char *)
+ obstack_alloc (&objfile -> symbol_obstack, nlen);
+ strncpy (SYMBOL_NAME (sym), s, nlen);
+ SYMBOL_NAME (sym)[nlen] = '\0';
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
+ }
+ else
+ /* FIXME! Want SYMBOL_NAME (sym) = 0;
+ Get error if leave name 0. So give it something. */
+ {
+ nlen = p - string;
+ SYMBOL_NAME (sym) = (char *)
+ obstack_alloc (&objfile -> symbol_obstack, nlen);
+ strncpy (SYMBOL_NAME (sym), string, nlen);
+ SYMBOL_NAME (sym)[nlen] = '\0';
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
+ }
+ }
+ /* Advance STRING beyond the reference id. */
+ string = s;
+ }
else
{
normal:
in GDB. E.g. "int" is converted to "function returning int". */
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_FUNC)
SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym));
+
+ /* All functions in C++ have prototypes. */
+ if (SYMBOL_LANGUAGE (sym) == language_cplus)
+ TYPE_FLAGS (SYMBOL_TYPE (sym)) |= TYPE_FLAG_PROTOTYPED;
+
/* fall into process_prototype_types */
process_prototype_types:
- /* Sun acc puts declared types of arguments here. We don't care
- about their actual types (FIXME -- we should remember the whole
- function prototype), but the list may define some new types
- that we have to remember, so we must scan it now. */
- while (*p == ';') {
- p++;
- read_type (&p, objfile);
- }
+ /* Sun acc puts declared types of arguments here. */
+ if (*p == ';')
+ {
+ struct type *ftype = SYMBOL_TYPE (sym);
+ int nsemi = 0;
+ int nparams = 0;
+ char *p1 = p;
+
+ /* Obtain a worst case guess for the number of arguments
+ by counting the semicolons. */
+ while (*p1)
+ {
+ if (*p1++ == ';')
+ nsemi++;
+ }
+
+ /* Allocate parameter information fields and fill them in. */
+ TYPE_FIELDS (ftype) = (struct field *)
+ TYPE_ALLOC (ftype, nsemi * sizeof (struct field));
+ while (*p++ == ';')
+ {
+ struct type *ptype;
+
+ /* A type number of zero indicates the start of varargs.
+ FIXME: GDB currently ignores vararg functions. */
+ if (p[0] == '0' && p[1] == '\0')
+ break;
+ ptype = read_type (&p, objfile);
+
+ /* The Sun compilers mark integer arguments, which should
+ be promoted to the width of the calling conventions, with
+ a type which references itself. This type is turned into
+ a TYPE_CODE_VOID type by read_type, and we have to turn
+ it back into builtin_type_int here.
+ FIXME: Do we need a new builtin_type_promoted_int_arg ? */
+ if (TYPE_CODE (ptype) == TYPE_CODE_VOID)
+ ptype = builtin_type_int;
+ TYPE_FIELD_TYPE (ftype, nparams++) = ptype;
+ }
+ TYPE_NFIELDS (ftype) = nparams;
+ TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
+ }
break;
case 'F':
corresponding linker definition to find the value.
These definitions appear at the end of the namelist. */
SYMBOL_TYPE (sym) = read_type (&p, objfile);
- i = hashname (SYMBOL_NAME (sym));
- SYMBOL_VALUE_CHAIN (sym) = global_sym_chain[i];
- global_sym_chain[i] = sym;
SYMBOL_CLASS (sym) = LOC_STATIC;
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ /* Don't add symbol references to global_sym_chain.
+ Symbol references don't have valid names and wont't match up with
+ minimal symbols when the global_sym_chain is relocated.
+ We'll fixup symbol references when we fixup the defining symbol. */
+ if (SYMBOL_NAME (sym) && SYMBOL_NAME (sym)[0] != '#')
+ {
+ i = hashname (SYMBOL_NAME (sym));
+ SYMBOL_VALUE_CHAIN (sym) = global_sym_chain[i];
+ global_sym_chain[i] = sym;
+ }
add_symbol_to_list (sym, &global_symbols);
break;
SYMBOL_CLASS (sym) = LOC_STATIC;
SYMBOL_VALUE_ADDRESS (sym) = valu;
#ifdef STATIC_TRANSFORM_NAME
- if (SYMBOL_NAME (sym)[0] == '$')
+ if (IS_STATIC_TRANSFORM_NAME (SYMBOL_NAME (sym)))
{
struct minimal_symbol *msym;
msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, objfile);
SYMBOL_CLASS (sym) = LOC_STATIC;
SYMBOL_VALUE_ADDRESS (sym) = valu;
#ifdef STATIC_TRANSFORM_NAME
- if (SYMBOL_NAME (sym)[0] == '$')
+ if (IS_STATIC_TRANSFORM_NAME (SYMBOL_NAME (sym)))
{
struct minimal_symbol *msym;
msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, objfile);
add_symbol_to_list (sym, &local_symbols);
break;
- /* New code added to support cfront stabs strings */
- /* Note: case 'P' already handled above */
+ /* New code added to support cfront stabs strings.
+ Note: case 'P' already handled above */
case 'Z':
/* Cfront type continuation coming up!
- find the original definition and add to it.
- We'll have to do this for the typedef too,
- since we clloned the symbol to define a type in read_type.
- Stabs info examples:
- __1C :Ztl
- foo__1CFv :ZtF (first def foo__1CFv:F(0,3);(0,24))
- C:ZsC;;__ct__1CFv func1__1CFv func2__1CFv ... ;;;
- where C is the name of the class. */
- /* can't lookup symbol yet 'cuz symbols not read yet
- so we save it for processing later */
- process_later(sym,p);
+ Find the original definition and add to it.
+ We'll have to do this for the typedef too,
+ since we cloned the symbol to define a type in read_type.
+ Stabs info examples:
+ __1C :Ztl
+ foo__1CFv :ZtF (first def foo__1CFv:F(0,3);(0,24))
+ C:ZsC;;__ct__1CFv func1__1CFv func2__1CFv ... ;;;
+ where C is the name of the class.
+ Unfortunately, we can't lookup the original symbol yet 'cuz
+ we haven't finished reading all the symbols.
+ Instead, we save it for processing later */
+ process_later (sym, p, resolve_cfront_continuation);
SYMBOL_TYPE (sym) = error_type (&p, objfile); /* FIXME! change later */
- SYMBOL_CLASS (sym) = LOC_CONST;
- SYMBOL_VALUE (sym) = 0;
- SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
- /* don't add to list - we'll delete it later when
- we add the continuation to the real sym */
- return sym;
- /* End of new code added to support cfront stabs strings */
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_VALUE (sym) = 0;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ /* Don't add to list - we'll delete it later when
+ we add the continuation to the real sym */
+ return sym;
+ /* End of new code added to support cfront stabs strings */
default:
SYMBOL_TYPE (sym) = error_type (&p, objfile);
}
}
+ /* Is there more to parse? For example LRS/alias information? */
+ while (*p && *p == ';')
+ {
+ p++;
+ if (*p && *p == 'l')
+ {
+ /* GNU extensions for live range splitting may be appended to
+ the end of the stab string. eg. "l(#1,#2);l(#3,#5)" */
+
+ /* Resolve the live range and add it to SYM's live range list. */
+ resolve_live_range (objfile, sym, p);
+
+ /* Find end of live range info. */
+ p = strchr (p, ')');
+ if (!*p || *p != ')')
+ error ("Internal error: live range format not recognized.\n");
+ p++;
+ }
+ }
return sym;
}
+/* Add the live range found in P to the symbol SYM in objfile OBJFILE. */
+
+static void
+resolve_live_range (objfile, sym, p)
+ struct objfile * objfile;
+ struct symbol *sym;
+ char *p;
+{
+ int refnum;
+ CORE_ADDR start, end;
+
+ /* Sanity check the beginning of the stabs string. */
+ if (!*p || *p != 'l')
+ error ("Internal error: live range string.\n");
+ p++;
+
+ if (!*p || *p != '(')
+ error ("Internal error: live range string.\n");
+ p++;
+
+ /* Get starting value of range and advance P past the reference id.
+
+ ?!? In theory, the process_reference should never fail, but we should
+ catch that case just in case the compiler scrogged the stabs. */
+ refnum = process_reference (&p);
+ start = ref_search_value (refnum);
+ if (!start)
+ error ("Internal error: live range symbol not found.\n");
+
+ if (!*p || *p != ',')
+ error ("Internal error: live range string.\n");
+ p++;
+
+ /* Get ending value of range and advance P past the reference id.
+
+ ?!? In theory, the process_reference should never fail, but we should
+ catch that case just in case the compiler scrogged the stabs. */
+ refnum = process_reference (&p);
+ end = ref_search_value (refnum);
+ if (!end)
+ error ("Internal error: live range symbol not found.\n");
+
+ if (!*p || *p != ')')
+ error ("Internal error: live range string.\n");
+
+ /* Now that we know the bounds of the range, add it to the
+ symbol. */
+ add_live_range (objfile, sym, start, end);
+}
+
+/* Add a new live range defined by START and END to the symbol SYM
+ in objfile OBJFILE. */
+
+static void
+add_live_range (objfile, sym, start, end)
+ struct objfile *objfile;
+ struct symbol *sym;
+ CORE_ADDR start, end;
+{
+ struct range_list *r, *rs;
+
+ if (start >= end)
+ error ("Internal error: end of live range follows start.\n");
+
+ /* Alloc new live range structure. */
+ r = (struct range_list *)
+ obstack_alloc (&objfile->type_obstack,
+ sizeof (struct range_list));
+ r->start = start;
+ r->end = end;
+ r->next = 0;
+
+ /* Append this range to the symbol's range list. */
+ if (!SYMBOL_RANGES (sym))
+ {
+ SYMBOL_RANGES (sym) = r;
+ }
+ else
+ {
+ /* Get the last range for the symbol. */
+ for (rs = SYMBOL_RANGES (sym); rs->next; rs = rs->next)
+ ;
+ rs->next = r;
+ }
+}
+
\f
/* Skip rest of this symbol and return an error type.
}
}
- q1 = strchr(*pp, '<');
- p = strchr(*pp, ':');
+ q1 = strchr (*pp, '<');
+ p = strchr (*pp, ':');
if (p == NULL)
return error_type (pp, objfile);
if (q1 && p > q1 && p[1] == ':')
++*pp;
while (**pp != ')')
{
- t = read_type(pp, objfile);
+ t = read_type (pp, objfile);
if (**pp == ',') ++*pp;
}
}
if (dem_p != 0 && *(dem_p-1)==':')
dem_p++;
FIELD_NAME (fip->list->field) =
- obsavestring (dem_p, strlen(dem_p), &objfile -> type_obstack);
+ obsavestring (dem_p, strlen (dem_p), &objfile -> type_obstack);
}
else
{
Note that forward refs cannot be packed,
and treat enums as if they had the width of ints. */
- if (TYPE_CODE (FIELD_TYPE (fip->list->field)) != TYPE_CODE_INT
- && TYPE_CODE (FIELD_TYPE (fip->list->field)) != TYPE_CODE_BOOL
- && TYPE_CODE (FIELD_TYPE (fip->list->field)) != TYPE_CODE_ENUM)
+ struct type *field_type = check_typedef (FIELD_TYPE (fip->list->field));
+
+ if (TYPE_CODE (field_type) != TYPE_CODE_INT
+ && TYPE_CODE (field_type) != TYPE_CODE_RANGE
+ && TYPE_CODE (field_type) != TYPE_CODE_BOOL
+ && TYPE_CODE (field_type) != TYPE_CODE_ENUM)
{
FIELD_BITSIZE (fip->list->field) = 0;
}
if ((FIELD_BITSIZE (fip->list->field)
- == TARGET_CHAR_BIT * TYPE_LENGTH (FIELD_TYPE (fip->list->field))
- || (TYPE_CODE (FIELD_TYPE (fip->list->field)) == TYPE_CODE_ENUM
+ == TARGET_CHAR_BIT * TYPE_LENGTH (field_type)
+ || (TYPE_CODE (field_type) == TYPE_CODE_ENUM
&& FIELD_BITSIZE (fip->list->field) == TARGET_INT_BIT )
)
&&
*/
static int
-read_cfront_static_fields(fip, pp, type, objfile)
+read_cfront_static_fields (fip, pp, type, objfile)
struct field_info *fip;
char **pp;
struct type *type;
/* eg: p = "as__1A ;;;" */
STABS_CONTINUE (pp, objfile); /* handle \\ */
- while (**pp!=';' && (sname = get_substring(pp,' '),sname))
+ while (**pp!=';' && (sname = get_substring (pp, ' '), sname))
{
ref_static = lookup_symbol (sname, 0, VAR_NAMESPACE, 0, 0); /*demangled_name*/
if (!ref_static)
fip -> list -> field.type = stype;
/* set bitpos & bitsize */
- SET_FIELD_PHYSNAME (fip->list->field, savestring (sname, strlen(sname)));
+ SET_FIELD_PHYSNAME (fip->list->field, savestring (sname, strlen (sname)));
/* set name field */
/* The following is code to work around cfront generated stabs.
if (dem_p != 0 && *(dem_p-1)==':')
dem_p++;
fip->list->field.name =
- obsavestring (dem_p, strlen(dem_p), &objfile -> type_obstack);
+ obsavestring (dem_p, strlen (dem_p), &objfile -> type_obstack);
}
else
{
fip->list->field.name =
- obsavestring (sname, strlen(sname), &objfile -> type_obstack);
+ obsavestring (sname, strlen (sname), &objfile -> type_obstack);
}
} /* end of code for cfront work around */
} /* loop again for next static field */
once we have collected all the class members. */
static int
-copy_cfront_struct_fields(fip, type, objfile)
+copy_cfront_struct_fields (fip, type, objfile)
struct field_info *fip;
struct type *type;
struct objfile *objfile;
{
int hash;
struct minimal_symbol *msymbol;
- struct symbol *sym, *prev;
+ struct symbol *sym, *prev, *rsym;
struct objfile *resolve_objfile;
/* SVR4 based linkers copy referenced global symbols from shared
if (SYMBOL_NAME (msymbol)[0] == SYMBOL_NAME (sym)[0] &&
STREQ(SYMBOL_NAME (msymbol) + 1, SYMBOL_NAME (sym) + 1))
{
+
+ struct alias_list *aliases;
+
/* Splice this symbol out of the hash chain and
assign the value we have to it. */
if (prev)
/* Note: this code might be executed several times for
the same symbol if there are multiple references. */
- if (SYMBOL_CLASS (sym) == LOC_BLOCK)
- {
- fix_common_block (sym, SYMBOL_VALUE_ADDRESS (msymbol));
- }
- else
+ /* If symbol has aliases, do minimal symbol fixups for each.
+ These live aliases/references weren't added to
+ global_sym_chain hash but may also need to be fixed up. */
+ /* FIXME: Maybe should have added aliases to the global chain, resolved symbol name, then treated aliases as normal
+ symbols? Still, we wouldn't want to add_to_list. */
+ /* Now do the same for each alias of this symbol */
+ rsym = sym;
+ aliases = SYMBOL_ALIASES (sym);
+ while (rsym)
{
- SYMBOL_VALUE_ADDRESS (sym)
- = SYMBOL_VALUE_ADDRESS (msymbol);
+ if (SYMBOL_CLASS (rsym) == LOC_BLOCK)
+ {
+ fix_common_block (rsym,
+ SYMBOL_VALUE_ADDRESS (msymbol));
+ }
+ else
+ {
+ SYMBOL_VALUE_ADDRESS (rsym)
+ = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+ SYMBOL_SECTION (rsym) = SYMBOL_SECTION (msymbol);
+ if (aliases)
+ {
+ rsym = aliases->sym;
+ aliases = aliases->next;
+ }
+ else
+ rsym = NULL;
}
- SYMBOL_SECTION (sym) = SYMBOL_SECTION (msymbol);
if (prev)
{