From: Dawn Perchik Date: Mon, 8 Sep 1997 00:38:19 +0000 (+0000) Subject: * dbxread.c, buildsym.c, symtab.c, stabsread.c: Add support for X-Git-Tag: gdb-4_18~4841 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d719efc6d5435a174fc9dfafff1c6f8d2d7e7c04;p=external%2Fbinutils.git * dbxread.c, buildsym.c, symtab.c, stabsread.c: Add support for reading stabs extensions for live range information. * stabsread.h, partial-stab.h: Add prototypes for new functions. * symtab.h: Add structure for storing live range information. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6789a14..0729c38 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +Sun Sep 7 17:26:30 1997 Dawn Perchik + + * dbxread.c, buildsym.c, symtab.c, stabsread.c: Add support for + reading stabs extensions for live range information. + * stabsread.h, partial-stab.h: Add prototypes for new functions. + * symtab.h: Add structure for storing live range information. + Wed Sep 3 16:39:39 1997 Andrew Cagney * top.c (set_arch): New function, update target_architecture. diff --git a/gdb/buildsym.c b/gdb/buildsym.c index 6c94407..806d700 100644 --- a/gdb/buildsym.c +++ b/gdb/buildsym.c @@ -95,6 +95,11 @@ add_symbol_to_list (symbol, listhead) struct pending **listhead; { register struct pending *link; + + /* If this is a reference to/live alias for another symbol, don't add it. + We don't want to be able to look up the live references directly. */ + if (symbol->ginfo.name && symbol->ginfo.name[0] == '#') + return; /* We keep PENDINGSIZE symbols in each link of the list. If we don't have a link with room in it, add a new link. */ diff --git a/gdb/dbxread.c b/gdb/dbxread.c index 41323ce..6463f27 100644 --- a/gdb/dbxread.c +++ b/gdb/dbxread.c @@ -182,6 +182,9 @@ struct complaint lbrac_mismatch_complaint = struct complaint repeated_header_complaint = {"\"repeated\" header file %s not previously seen, at symtab pos %d", 0, 0}; + +struct complaint unclaimed_bincl_complaint = + {"N_BINCL %s not in entries for any file, at symtab pos %d", 0, 0}; /* During initial symbol readin, we need to have a structure to keep track of which psymtabs have which bincls in them. This structure @@ -770,6 +773,7 @@ struct cont_elem int sym_idx; int sym_end; int symnum; + int (*func) (struct objfile *, struct symbol *, char *); /* other state dependancies include: (assumption is that these will not change since process_now FIXME!!) stringtab_global @@ -777,25 +781,37 @@ struct cont_elem objfile symfile_bfd */ }; -static struct cont_elem cont_list[100]; + +static struct cont_elem *cont_list = 0; +static int cont_limit = 0; static int cont_count = 0; void -process_later(sym,p) +process_later (sym, p, f) struct symbol * sym; char * p; + int (*f) (struct objfile *, struct symbol *, char *); { + if (cont_count >= cont_limit - 1) + { + cont_limit += 32; /* chunk size */ + cont_list = (struct cont_elem *) realloc (cont_list, + cont_limit * sizeof (struct cont_elem)); + if (!cont_list) + error ("Virtual memory exhausted\n"); + } /* save state so we can process these stabs later */ cont_list[cont_count].sym_idx = symbuf_idx; cont_list[cont_count].sym_end = symbuf_end; cont_list[cont_count].symnum = symnum; cont_list[cont_count].sym = sym; cont_list[cont_count].stabs = p; + cont_list[cont_count].func = f; cont_count++; } static void -process_now(objfile) +process_now (objfile) struct objfile * objfile; { int i; @@ -803,14 +819,25 @@ process_now(objfile) int save_symbuf_idx = symbuf_idx; int save_symbuf_end = symbuf_end; int save_symnum = symnum; + struct symbol *sym; + char *stabs; + int err; + int (*func) (struct objfile *, struct symbol *, char *); + for (i=0; iobjfile->md, (char *)bincl_list, bincls_allocated * sizeof (struct header_file_location)); - if (bincl_list == NULL) - fatal ("virtual memory exhausted in add_bincl_to_list ();"); next_bincl = bincl_list + offset; } next_bincl->pst = pst; @@ -1782,8 +1807,9 @@ read_ofile_symtab (pst) pst->symtab = end_symtab (text_offset + text_size, objfile, SECT_OFF_TEXT); - if (ARM_DEMANGLING) /* process incomplete C++ types now */ - process_now(objfile); + /* Process items which we had to "process_later" due to dependancies + on other stabs. */ + process_now (objfile); end_stabs (); } @@ -2337,6 +2363,29 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile) break; } + /* Special GNU C extension for referencing names. */ + if (name[0] == '#') + { + /* Initialize symbol reference names and determine if this is + a definition. If symbol reference is being defined, go + ahead and add it. Otherwise, just return sym. */ + char *s; + int refnum; + extern int symbol_reference_defined (char **); + extern void ref_add (int, struct symbol *, char *, CORE_ADDR); + extern struct symbol * ref_search (int); + + /* If defined, store away a pointer to the symbol; + we'll use it later when we resolve references in + "resolve_symbol_reference". */ + s = name; + if (refnum = symbol_reference_defined (&s), refnum) + if (!ref_search (refnum)) + ref_add (refnum, 0, name, valu); + name = s; /* Advance past refid. */ + } + + previous_stab_code = type; } diff --git a/gdb/partial-stab.h b/gdb/partial-stab.h index 970676f..c494a07 100644 --- a/gdb/partial-stab.h +++ b/gdb/partial-stab.h @@ -666,6 +666,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ case '8': case '9': case '-': + case '#': /* for symbol identification (used in live ranges) */ /* added to support cfront stabs strings */ case 'Z': /* for definition continuations */ case 'P': /* for prototypes */ diff --git a/gdb/stabsread.c b/gdb/stabsread.c index f052a3b..34e4875 100644 --- a/gdb/stabsread.c +++ b/gdb/stabsread.c @@ -169,9 +169,24 @@ read_cfront_static_fields PARAMS ((struct field_info *, char**, static int read_cfront_member_functions PARAMS ((struct field_info *, char **, 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 int +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)); + +struct symbol * +ref_search PARAMS ((int refnum)); + static const char vptr_name[] = { '_','v','p','t','r',CPLUS_MARKER,'\0' }; @@ -576,7 +591,7 @@ get_cfront_method_physname (fname) /* 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); @@ -710,12 +725,12 @@ read_cfront_baseclasses (fip, pp, type, objfile) 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 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; + } + + /* 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) */ + /* 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; } @@ -954,8 +972,8 @@ read_cfront_member_functions(fip, pp, type, objfile) 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; @@ -967,13 +985,13 @@ resolve_cfront_continuation(objfile, sym, 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 @@ -981,20 +999,19 @@ resolve_cfront_continuation(objfile, sym, p) 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); @@ -1008,7 +1025,7 @@ resolve_cfront_continuation(objfile, sym, p) || !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: @@ -1019,10 +1036,239 @@ resolve_cfront_continuation(objfile, sym, p) } do_cleanups (back_to); + return 0; } /* End of code added to support parsing of ARM/Cfront stabs strings */ +/* This routine fixes up symbol references to point to the original + symbol definition. + The main need for this function is to add information for supporting + live range splitting. + eg: p : "#7=", "#2=z:r(0,1)" "#2:r(0,1);l(#5,#6),l(#7,#4)" */ +int +resolve_symbol_reference (objfile, sym, p) + struct objfile * objfile; + struct symbol * sym; + char * p; +{ + int refnum; + struct symbol * ref_sym=0; + struct cleanup *back_to; + + back_to = make_cleanup (null_cleanup, 0); + + if (*p != '#') /* symbol ref id */ + return 0; + + /* Use "#" as the name; we'll fix the name later. + We stored the original symbol name as "#=" + so we can now search for "#" to resolving the reference. + We'll fix the names later by removing the "#" or "#=" */ + + /*---------------------------------------------------------*/ + /* 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. */ + 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. */ + /*--------------------------------------------------*/ + SYMBOL_ALIASES (sym) = SYMBOL_ALIASES (ref_sym); + SYMBOL_ALIASES (ref_sym) = sym; + + /* 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! */ + + do_cleanups (back_to); + return 0; +} + +/* Get range symbol reference. eg. "#2),l(#3,#5)" + postpone resolve_reference until after we're done reading symbols. */ +struct symbol * +resolve_reference (char *p) +{ + char sym_refid[32]; + struct symbol *sym = 0; + char *s = p; + int len; + + if (!s || *s != '#') + return 0; + p = strchr (s, ')'); + if (!p || p == s) + return 0; + len = p - s + 1; + strncpy (sym_refid, s, len); + sym_refid[len] = '\0'; + sym = lookup_symbol (sym_refid, 0, VAR_NAMESPACE, 0, 0); + return sym; +} + +/* Structure for storing pointers to reference definitions for fast lookup + during "process_later". */ +#define MAX_REFS 100 /* FIXME! Change to use heap. */ +static struct ref_map_s +{ + char *stabs; + CORE_ADDR value; + struct symbol *sym; +} ref_map[MAX_REFS]; + +/* Initialize our list of references. + This should be called before any symbol table is read. + FIXME: Will reference numbers be unique only to objects? If so, we may + need to add something to disambiguate the refids. Or, it might be OK to + leave as is, as long as we read and process an object's symbol table all + at once. */ +static int ref_count = 0; /* Ptr to free cell in linked list. */ +static void ref_init () +{ + ref_count = 0; + memset (ref_map, 0, MAX_REFS * sizeof (struct ref_map_s)); +} + +/* 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 (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 > MAX_REFS) + error ("no more free slots in chain\n"); + ref_map[refnum].stabs = stabs; + ref_map[refnum].sym = sym; + ref_map[refnum].value = value; +} + +/* Remove reference at refnum. + This should be called before a new symbol table is read to clear out the + previous symbol's reference information. */ +/* FIXME! not used at the moment. */ +static void ref_rmv (int refnum) +{ + if (ref_count < 0) + error ("slots are empty\n"); + if (refnum < 0 || refnum > ref_count) + error ("No reference for refnum.\n"); + /* Copy last element over the removed element and reduce count. */ + ref_map[refnum].stabs = ref_map[ref_count].stabs; + ref_map[refnum].sym = ref_map[ref_count].sym; + --ref_count; +} + +/* Return defined sym for the reference "refnum" */ +struct symbol * +ref_search (int refnum) +{ + if (refnum < 0 || refnum > ref_count) + return 0; + return ref_map[refnum].sym; +} + +/* Return value for the reference "refnum" */ +CORE_ADDR +ref_search_value (int refnum) +{ + if (refnum < 0 || refnum > ref_count) + return 0; + return ref_map[refnum].value; +} + +/* Parse reference id and advance string to the next character following + the string. + Return the reference number. */ + +static int +process_reference (char **string) +{ + char *p; + int refnum = 0; + + if (**string != '#') + return 0; + + /* Read number as reference id. */ + p = *string + 1; /* Advance beyond '#' */ + 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 fast lookup when we "process_later", + and return the reference number. */ +int +symbol_reference_defined (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 0; /* Not defined here */ + } +} + /* ARGSUSED */ struct symbol * define_symbol (valu, string, desc, type, objfile) @@ -1056,7 +1302,7 @@ 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. @@ -1125,6 +1371,45 @@ define_symbol (valu, string, desc, type, objfile) goto normal; /* Do *something* with it */ } } + else if (string[0] == '#') + { + /* Special GNU C extension for referencing symbols. */ + char *s; + int refnum, nlen; + + /* Initialize symbol references and determine if this is + a definition. If symbol reference is being defined, go + ahead and add it. Otherwise, just return sym. */ + s = string; + if (refnum = symbol_reference_defined (&s), refnum) + ref_add (refnum, sym, string, SYMBOL_VALUE (sym)); + else + process_later (sym, string, resolve_symbol_reference); + + /* s is after refid... advance string there + so that the symbol name will not include the refid. */ + nlen = p - s; + 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); + } + string = s; + } else { normal: @@ -1332,11 +1617,18 @@ define_symbol (valu, string, desc, type, objfile) 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; @@ -1741,29 +2033,30 @@ define_symbol (valu, string, desc, type, 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); @@ -1798,9 +2091,129 @@ define_symbol (valu, string, desc, type, objfile) } } + /* Is there more to parse? eg. ";l(#1,#2);l(#3,#5)" */ + while (*p && (*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)" */ + + /* Fix up ranges later. */ + process_later (sym, p, resolve_live_range); + + /* 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 live range information to symbol. (eg. p is l(#1,#2)...) */ +static int +resolve_live_range (objfile, sym, p) + struct objfile * objfile; + struct symbol *sym; + char *p; +{ + char *s=p; + int refnum; + CORE_ADDR start, end; + + 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 symbol reference. eg. "#1,#2),l(#3,#5)" + and advance p past the refid. */ + 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 symbol reference. eg. "#2),l(#3,#5)" */ + refnum = process_reference (&p); + end = ref_search_value (refnum); + if (!end) + error ("Internal error: live range symbol not found.\n"); + + add_live_range (objfile, sym, start, end); + + if (!*p || *p != ')') + error ("Internal error: live range string.\n"); + p++; + return 0; +} + +void +add_live_range (objfile, sym, start, end) + struct objfile *objfile; + struct symbol *sym; + CORE_ADDR start, end; +{ + struct live_range *r, *rs; + + if (start >= end) + error ("Internal error: end of live range follows start.\n"); + + /* Alloc new live range structure. */ + r = (struct live_range *) + obstack_alloc (&objfile->type_obstack, + sizeof (struct live_range)); + r->start = start; + r->end = end; + r->next = 0; + + /* Append this range to the symbol's range list. */ + if (!SYMBOL_RANGE (sym)) + { + SYMBOL_RANGE (sym) = r; + } + else + { + /* Get the last range for the symbol. */ + for (rs = SYMBOL_RANGE (sym); rs->next; rs = rs->next) + ; + rs->next = r; + } +} + +/* Given addr, Search thu alias list to find the one active. */ +struct symbol * +ref_search_val (sym, addr) + struct symbol *sym; + CORE_ADDR addr; +{ + struct live_range *r; + + while (sym) + { + if (!SYMBOL_RANGE (sym)) + return sym; + for (r = SYMBOL_RANGE (sym); r; r = r->next) + { + if (r->start <= addr + && r->end > addr) + return sym; + } + sym = SYMBOL_ALIASES (sym); + } + return 0; +} + /* Skip rest of this symbol and return an error type. @@ -1953,8 +2366,8 @@ read_type (pp, objfile) } } - 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] == ':') @@ -2094,7 +2507,7 @@ read_type (pp, objfile) ++*pp; while (**pp != ')') { - t = read_type(pp, objfile); + t = read_type (pp, objfile); if (**pp == ',') ++*pp; } } @@ -2876,7 +3289,7 @@ read_one_struct_field (fip, pp, p, type, objfile) 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 { @@ -3350,7 +3763,7 @@ attach_fn_fields_to_type (fip, type) */ 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; @@ -3371,7 +3784,7 @@ read_cfront_static_fields(fip, pp, type, objfile) /* 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) @@ -3399,7 +3812,7 @@ read_cfront_static_fields(fip, pp, type, objfile) 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. @@ -3416,12 +3829,12 @@ read_cfront_static_fields(fip, pp, type, objfile) 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 */ @@ -3435,7 +3848,7 @@ read_cfront_static_fields(fip, pp, type, objfile) 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; @@ -4489,7 +4902,7 @@ scan_file_globals (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 @@ -4558,17 +4971,25 @@ scan_file_globals (objfile) /* Note: this code might be executed several times for the same symbol if there are multiple references. */ - if (SYMBOL_CLASS (sym) == LOC_BLOCK) + /* 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 */ + for (rsym = sym; rsym; rsym = SYMBOL_ALIASES (rsym)) { - fix_common_block (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); } - else - { - SYMBOL_VALUE_ADDRESS (sym) - = SYMBOL_VALUE_ADDRESS (msymbol); - } - - SYMBOL_SECTION (sym) = SYMBOL_SECTION (msymbol); if (prev) { diff --git a/gdb/stabsread.h b/gdb/stabsread.h index c08635f..dcaa6da 100644 --- a/gdb/stabsread.h +++ b/gdb/stabsread.h @@ -168,7 +168,7 @@ end_stabs PARAMS ((void)); extern void finish_global_stabs PARAMS ((struct objfile *objfile)); -extern void +extern int resolve_cfront_continuation PARAMS((struct objfile * objfile, struct symbol * sym, char * p)); @@ -236,6 +236,7 @@ extern void stabsect_build_psymtabs extern void elfstab_offset_sections PARAMS ((struct objfile *, struct partial_symtab *)); -extern void process_later PARAMS ((struct symbol *, char *)); +extern void process_later PARAMS ((struct symbol *, char *, + int (*f) (struct objfile *, struct symbol *, char *))); #undef EXTERN diff --git a/gdb/symtab.c b/gdb/symtab.c index 7edd1a6..9ae6442 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -912,6 +912,7 @@ lookup_block_symbol (block, name, namespace) const char *name; const namespace_enum namespace; { + extern struct symbol *ref_search_val (struct symbol *sym, CORE_ADDR addr); register int bot, top, inc; register struct symbol *sym; register struct symbol *sym_found = NULL; @@ -1017,6 +1018,10 @@ lookup_block_symbol (block, name, namespace) if (SYMBOL_NAMESPACE (sym) == namespace && SYMBOL_MATCHES_NAME (sym, name)) { + /* Given pc, search thu alias list to find the active symbol. */ + if (SYMBOL_ALIASES (sym)) + sym = ref_search_val (sym, read_pc ()); + sym_found = sym; if (SYMBOL_CLASS (sym) != LOC_ARG && SYMBOL_CLASS (sym) != LOC_LOCAL_ARG && @@ -2080,15 +2085,25 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) } if (p[0] == ':' || p[0] == ' ' || p[0] == '\t') break; + if (p[0] == '.' && strchr (p, ':') == NULL) /* Java qualified method. */ + { + /* Find the *last* '.', since the others are package qualifiers. */ + for (p1 = p; *p1; p1++) + { + if (*p1 == '.') + p = p1; + } + break; + } } while (p[0] == ' ' || p[0] == '\t') p++; - if ((p[0] == ':') && !has_parens) + if ((p[0] == ':' || p[0] == '.') && !has_parens) { - /* C++ */ + /* C++ or Java */ if (is_quoted) *argptr = *argptr+1; - if (p[1] ==':') + if (p[0] == '.' || p[1] ==':') { /* Extract the class name. */ p1 = p; @@ -2098,7 +2113,7 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) copy[p - *argptr] = 0; /* Discard the class name from the arg. */ - p = p1 + 2; + p = p1 + (p1[0] == ':' ? 2 : 1); while (*p == ' ' || *p == '\t') p++; *argptr = p; diff --git a/gdb/symtab.h b/gdb/symtab.h index 83c2377..4bf17d7 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -84,7 +84,7 @@ struct general_symbol_info union { - struct cplus_specific /* For C++ */ + struct cplus_specific /* For C++ and Java */ { char *demangled_name; } cplus_specific; @@ -135,7 +135,8 @@ extern CORE_ADDR symbol_overlayed_address PARAMS((CORE_ADDR, asection *)); #define SYMBOL_INIT_LANGUAGE_SPECIFIC(symbol,language) \ do { \ SYMBOL_LANGUAGE (symbol) = language; \ - if (SYMBOL_LANGUAGE (symbol) == language_cplus) \ + if (SYMBOL_LANGUAGE (symbol) == language_cplus \ + || SYMBOL_LANGUAGE (symbol) == language_java) \ { \ SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = NULL; \ } \ @@ -179,6 +180,23 @@ extern CORE_ADDR symbol_overlayed_address PARAMS((CORE_ADDR, asection *)); SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = NULL; \ } \ } \ + if (SYMBOL_LANGUAGE (symbol) == language_java) \ + { \ + demangled = \ + cplus_demangle (SYMBOL_NAME (symbol), \ + DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA); \ + if (demangled != NULL) \ + { \ + SYMBOL_LANGUAGE (symbol) = language_java; \ + SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = \ + obsavestring (demangled, strlen (demangled), (obstack)); \ + free (demangled); \ + } \ + else \ + { \ + SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = NULL; \ + } \ + } \ if (demangled == NULL \ && (SYMBOL_LANGUAGE (symbol) == language_chill \ || SYMBOL_LANGUAGE (symbol) == language_auto)) \ @@ -208,6 +226,7 @@ extern CORE_ADDR symbol_overlayed_address PARAMS((CORE_ADDR, asection *)); #define SYMBOL_DEMANGLED_NAME(symbol) \ (SYMBOL_LANGUAGE (symbol) == language_cplus \ + || SYMBOL_LANGUAGE (symbol) == language_java \ ? SYMBOL_CPLUS_DEMANGLED_NAME (symbol) \ : (SYMBOL_LANGUAGE (symbol) == language_chill \ ? SYMBOL_CHILL_DEMANGLED_NAME (symbol) \ @@ -584,6 +603,15 @@ enum address_class LOC_OPTIMIZED_OUT }; +/* Linked list of symbol's live ranges. */ + +struct live_range +{ + CORE_ADDR start; + CORE_ADDR end; + struct live_range *next; +}; + struct symbol { @@ -623,6 +651,23 @@ struct symbol short basereg; } aux_value; + + /* Live range information (if present) for debugging of optimized code. + Gcc extensions were added to stabs to encode live range information. + The syntax for referencing (defining) symbol aliases is "#n" ("#n=") + where n is a number. The syntax for specifying a range is "l(#,#)", + where m and n are numbers. + aliases - list of other symbols which are lexically the same symbol, + but were optimized into different storage classes (eg. for the + local symbol "x", one symbol contains range information where x + is on the stack, while an alias contains the live ranges where x + is in a register). + range - list of instruction ranges where the symbol is live. */ + struct live_range_info + { + struct symbol *aliases; /* Link to other aliases for this symbol. */ + struct live_range *range; /* Linked list of live ranges. */ + } live; }; #define SYMBOL_NAMESPACE(symbol) (symbol)->namespace @@ -630,6 +675,11 @@ struct symbol #define SYMBOL_TYPE(symbol) (symbol)->type #define SYMBOL_LINE(symbol) (symbol)->line #define SYMBOL_BASEREG(symbol) (symbol)->aux_value.basereg +#define SYMBOL_ALIASES(symbol) (symbol)->live.aliases +#define SYMBOL_RANGE(symbol) (symbol)->live.range +#define SYMBOL_RANGE_START(symbol) (symbol)->live.range->start +#define SYMBOL_RANGE_END(symbol) (symbol)->live.range->end +#define SYMBOL_RANGE_NEXT(symbol) (symbol)->live.range->next /* A partial_symbol records the name, namespace, and address class of symbols whose types we have not parsed yet. For functions, it also