stabs.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,559 行 · 第 1/5 页
C
2,559 行
values[n] = 0; if (**pp == ';') ++*pp; return debug_make_enum_type (dhandle, names, values);}/* Read the description of a structure (or union type) and return an object describing the type. PP points to a character pointer that points to the next unconsumed token in the the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;", *PP will point to "4a:1,0,32;;". */static debug_typeparse_stab_struct_type (dhandle, info, tagname, pp, structp, typenums) PTR dhandle; struct stab_handle *info; const char *tagname; const char **pp; boolean structp; const int *typenums;{ const char *orig; bfd_vma size; debug_baseclass *baseclasses; debug_field *fields; boolean statics; debug_method *methods; debug_type vptrbase; boolean ownvptr; orig = *pp; /* Get the size. */ size = parse_number (pp, (boolean *) NULL); /* Get the other information. */ if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses) || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics) || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods) || ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase, &ownvptr)) return DEBUG_TYPE_NULL; if (! statics && baseclasses == NULL && methods == NULL && vptrbase == DEBUG_TYPE_NULL && ! ownvptr) return debug_make_struct_type (dhandle, structp, size, fields); return debug_make_object_type (dhandle, structp, size, fields, baseclasses, methods, vptrbase, ownvptr);}/* The stabs for C++ derived classes contain baseclass information which is marked by a '!' character after the total size. This function is called when we encounter the baseclass marker, and slurps up all the baseclass information. Immediately following the '!' marker is the number of base classes that the class is derived from, followed by information for each base class. For each base class, there are two visibility specifiers, a bit offset to the base class information within the derived class, a reference to the type for the base class, and a terminating semicolon. A typical example, with two base classes, would be "!2,020,19;0264,21;". ^^ ^ ^ ^ ^ ^ ^ Baseclass information marker __________________|| | | | | | | Number of baseclasses __________________________| | | | | | | Visibility specifiers (2) ________________________| | | | | | Offset in bits from start of class _________________| | | | | Type number for base class ___________________________| | | | Visibility specifiers (2) _______________________________| | | Offset in bits from start of class ________________________| | Type number of base class ____________________________________| Return true for success, false for failure. */static booleanparse_stab_baseclasses (dhandle, info, pp, retp) PTR dhandle; struct stab_handle *info; const char **pp; debug_baseclass **retp;{ const char *orig; unsigned int c, i; debug_baseclass *classes; *retp = NULL; orig = *pp; if (**pp != '!') { /* No base classes. */ return true; } ++*pp; c = (unsigned int) parse_number (pp, (boolean *) NULL); if (**pp != ',') { bad_stab (orig); return false; } ++*pp; classes = (debug_baseclass *) xmalloc ((c + 1) * sizeof (**retp)); for (i = 0; i < c; i++) { boolean virtual; enum debug_visibility visibility; bfd_vma bitpos; debug_type type; switch (**pp) { case '0': virtual = false; break; case '1': virtual = true; break; default: warn_stab (orig, _("unknown virtual character for baseclass")); virtual = false; break; } ++*pp; switch (**pp) { case '0': visibility = DEBUG_VISIBILITY_PRIVATE; break; case '1': visibility = DEBUG_VISIBILITY_PROTECTED; break; case '2': visibility = DEBUG_VISIBILITY_PUBLIC; break; default: warn_stab (orig, _("unknown visibility character for baseclass")); visibility = DEBUG_VISIBILITY_PUBLIC; break; } ++*pp; /* The remaining value is the bit offset of the portion of the object corresponding to this baseclass. Always zero in the absence of multiple inheritance. */ bitpos = parse_number (pp, (boolean *) NULL); if (**pp != ',') { bad_stab (orig); return false; } ++*pp; type = parse_stab_type (dhandle, info, (const char *) NULL, pp, (debug_type **) NULL); if (type == DEBUG_TYPE_NULL) return false; classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual, visibility); if (classes[i] == DEBUG_BASECLASS_NULL) return false; if (**pp != ';') return false; ++*pp; } classes[i] = DEBUG_BASECLASS_NULL; *retp = classes; return true;}/* Read struct or class data fields. They have the form: NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ; At the end, we see a semicolon instead of a field. In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for a static field. The optional VISIBILITY is one of: '/0' (VISIBILITY_PRIVATE) '/1' (VISIBILITY_PROTECTED) '/2' (VISIBILITY_PUBLIC) '/9' (VISIBILITY_IGNORE) or nothing, for C style fields with public visibility. Returns 1 for success, 0 for failure. */static booleanparse_stab_struct_fields (dhandle, info, pp, retp, staticsp) PTR dhandle; struct stab_handle *info; const char **pp; debug_field **retp; boolean *staticsp;{ const char *orig; const char *p; debug_field *fields; unsigned int c; unsigned int alloc; *retp = NULL; *staticsp = false; orig = *pp; c = 0; alloc = 10; fields = (debug_field *) xmalloc (alloc * sizeof *fields); while (**pp != ';') { /* FIXME: gdb checks os9k_stabs here. */ p = *pp; /* Add 1 to c to leave room for NULL pointer at end. */ if (c + 1 >= alloc) { alloc += 10; fields = ((debug_field *) xrealloc ((PTR) fields, alloc * sizeof *fields)); } /* If it starts with CPLUS_MARKER it is a special abbreviation, unless the CPLUS_MARKER is followed by an underscore, in which case it is just the name of an anonymous type, which we should handle like any other type name. We accept either '$' or '.', because a field name can never contain one of these characters except as a CPLUS_MARKER. */ if ((*p == '$' || *p == '.') && p[1] != '_') { ++*pp; if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c)) return false; ++c; continue; } /* Look for the ':' that separates the field name from the field values. Data members are delimited by a single ':', while member functions are delimited by a pair of ':'s. When we hit the member functions (if any), terminate scan loop and return. */ p = strchr (p, ':'); if (p == NULL) { bad_stab (orig); return false; } if (p[1] == ':') break; if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c, staticsp)) return false; ++c; } fields[c] = DEBUG_FIELD_NULL; *retp = fields; return true;}/* Special GNU C++ name. */static booleanparse_stab_cpp_abbrev (dhandle, info, pp, retp) PTR dhandle; struct stab_handle *info; const char **pp; debug_field *retp;{ const char *orig; int cpp_abbrev; debug_type context; const char *name; const char *typename; debug_type type; bfd_vma bitpos; *retp = DEBUG_FIELD_NULL; orig = *pp; if (**pp != 'v') { bad_stab (*pp); return false; } ++*pp; cpp_abbrev = **pp; ++*pp; /* At this point, *pp points to something like "22:23=*22...", where the type number before the ':' is the "context" and everything after is a regular type definition. Lookup the type, find it's name, and construct the field name. */ context = parse_stab_type (dhandle, info, (const char *) NULL, pp, (debug_type **) NULL); if (context == DEBUG_TYPE_NULL) return false; switch (cpp_abbrev) { case 'f': /* $vf -- a virtual function table pointer. */ name = "_vptr$"; break; case 'b': /* $vb -- a virtual bsomethingorother */ typename = debug_get_type_name (dhandle, context); if (typename == NULL) { warn_stab (orig, _("unnamed $vb type")); typename = "FOO"; } name = concat ("_vb$", typename, (const char *) NULL); break; default: warn_stab (orig, _("unrecognized C++ abbreviation")); name = "INVALID_CPLUSPLUS_ABBREV"; break; } if (**pp != ':') { bad_stab (orig); return false; } ++*pp; type = parse_stab_type (dhandle, info, (const char *) NULL, pp, (debug_type **) NULL); if (**pp != ',') { bad_stab (orig); return false; } ++*pp; bitpos = parse_number (pp, (boolean *) NULL); if (**pp != ';') { bad_stab (orig); return false; } ++*pp; *retp = debug_make_field (dhandle, name, type, bitpos, 0, DEBUG_VISIBILITY_PRIVATE); if (*retp == DEBUG_FIELD_NULL) return false; return true;}/* Parse a single field in a struct or union. */static booleanparse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp) PTR dhandle; struct stab_handle *info; const char **pp; const char *p; debug_field *retp; boolean *staticsp;{ const char *orig; char *name; enum debug_visibility visibility; debug_type type; bfd_vma bitpos; bfd_vma bitsize; orig = *pp; /* FIXME: gdb checks ARM_DEMANGLING here. */ name = savestring (*pp, p - *pp); *pp = p + 1; if (**pp != '/') visibility = DEBUG_VISIBILITY_PUBLIC; else { ++*pp; switch (**pp) { case '0': visibility = DEBUG_VISIBILITY_PRIVATE; break; case '1': visibility = DEBUG_VISIBILITY_PROTECTED; break; case '2': visibility = DEBUG_VISIBILITY_PUBLIC; break; default: warn_stab (orig, _("unknown visibility character for field")); visibility = DEBUG_VISIBILITY_PUBLIC; break; } ++*pp; } type = parse_stab_type (dhandle, info, (const char *) NULL, pp, (debug_type **) NULL); if (type == DEBUG_TYPE_NULL) return false; if (**pp == ':') { char *varname; /* This is a static class member. */ ++*pp; p = strchr (*pp, ';'); if (p == NULL) { bad_stab (orig); return false; } varname = savestring (*pp, p - *pp); *pp = p + 1; *retp = debug_make_static_member (dhandle, name, type, varname, visibility); *staticsp = true; return true; } if (**pp != ',') { bad_stab (orig); return false; } ++*pp; bitpos = parse_number (pp, (boolean *) NULL); if (**pp != ',') { bad_stab (orig); return false; } ++*pp; bitsize = parse_number (pp, (boolean *) NULL); if (**pp != ';') { bad_stab (orig); return false; } ++*pp; if (bitpos == 0 && bitsize == 0) { /* This can happen in two cases: (1) at least for gcc 2.4.5 or so, it is a field which has been optimized out. The correct stab for this case is to use VISIBILITY_IGNORE, but that is a recent invention. (2) It is a 0-size array. For example union { int num; char str[0]; } foo. Printing "<no value>" for str in "p foo" is OK, since foo.str (and thus foo.str[3]) will continue to work, and a 0-size array as a whole doesn't have any contents to print. I suspect this probably could also happen with gcc -gstabs (not -gstabs+) for static fields, and perhaps other C++ extensions. Hopefully few people use -gstabs with gdb, since it is intended for dbx compatibility. */ visibility = DEBUG_VISIBILITY_IGNORE; } /* FIXME: gdb does some stuff here to mark fields as unpacked. */ *retp = debug_make_field (dhandle, name, type, bitpos, bitsize, visibility); return true;}/* Read member function stabs info for C++ classes. The form
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?