diff options
author | Dawn Perchik <dawn@cygnus> | 1997-09-08 00:38:19 +0000 |
---|---|---|
committer | Dawn Perchik <dawn@cygnus> | 1997-09-08 00:38:19 +0000 |
commit | d719efc6d5435a174fc9dfafff1c6f8d2d7e7c04 (patch) | |
tree | 8076bd277ac84a1efdb026686d59c01de6ac4310 /gdb/stabsread.c | |
parent | 60b570d17a8fa5e72665ca8f3a9c98462c66f915 (diff) | |
download | gdb-d719efc6d5435a174fc9dfafff1c6f8d2d7e7c04.zip gdb-d719efc6d5435a174fc9dfafff1c6f8d2d7e7c04.tar.gz gdb-d719efc6d5435a174fc9dfafff1c6f8d2d7e7c04.tar.bz2 |
* 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.
Diffstat (limited to 'gdb/stabsread.c')
-rw-r--r-- | gdb/stabsread.c | 781 |
1 files changed, 601 insertions, 180 deletions
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<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); @@ -752,12 +767,12 @@ read_cfront_baseclasses (fip, pp, type, objfile) */ 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 */ @@ -778,25 +793,25 @@ read_cfront_member_functions(fip, pp, type, objfile) 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 = {"\ @@ -824,129 +839,132 @@ read_cfront_member_functions(fip, pp, type, objfile) 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; + } + + /* 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 "#<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. */ + 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) { |