📄 stabsread.c
字号:
2.0 language feature. */ int via_virtual; *pp += 1; ALLOCATE_CPLUS_STRUCT_TYPE(type); n_baseclasses = read_number (pp, ','); /* Some stupid compilers have trouble with the following, so break it up into simpler expressions. */#if 0 TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) TYPE_ALLOC (type, B_BYTES (n_baseclasses));#else { int num_bytes = B_BYTES (n_baseclasses); char *pointer; pointer = (char *) TYPE_ALLOC (type, num_bytes); TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer; }#endif /* 0 */ B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), n_baseclasses); for (i = 0; i < n_baseclasses; i++) { if (**pp == '\\') *pp = next_symbol_text (); switch (**pp) { case '0': via_virtual = 0; break; case '1': via_virtual = 1; break; default: /* Bad visibility format. */ return error_type (pp); } ++*pp; switch (**pp) { case '0': via_public = 0; non_public_fields++; break; case '2': via_public = 2; break; default: /* Bad visibility format. */ return error_type (pp); } if (via_virtual) SET_TYPE_FIELD_VIRTUAL (type, i); ++*pp; /* Offset of the portion of the object corresponding to this baseclass. Always zero in the absence of multiple inheritance. */ offset = read_number (pp, ','); baseclass = read_type (pp, objfile); *pp += 1; /* skip trailing ';' */ /* Make this baseclass visible for structure-printing purposes. */ new = (struct nextfield *) alloca (sizeof (struct nextfield)); memset (new, 0, sizeof (struct nextfield)); new->next = list; list = new; list->visibility = via_public; list->field.type = baseclass; list->field.name = type_name_no_tag (baseclass); list->field.bitpos = offset; list->field.bitsize = 0; /* this should be an unpacked field! */ nfields++; } TYPE_N_BASECLASSES (type) = n_baseclasses; } /* Now come the fields, as NAME:?TYPENUM,BITPOS,BITSIZE; for each one. 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 `?' is a placeholder for one of '/2' (public visibility), '/1' (protected visibility), '/0' (private visibility), or nothing (C style symbol table, public visibility). */ /* We better set p right now, in case there are no fields at all... */ p = *pp; while (**pp != ';') { /* Check for and handle cretinous dbx symbol name continuation! */ if (**pp == '\\') *pp = next_symbol_text (); /* Get space to record the next field's data. */ new = (struct nextfield *) alloca (sizeof (struct nextfield)); memset (new, 0, sizeof (struct nextfield)); new->next = list; list = new; /* Get the field name. */ p = *pp; if (*p == CPLUS_MARKER) { if (*p == '_') /* GNU C++ anonymous type. */ ; /* Special GNU C++ name. */ else if (*++p == 'v') { const char *prefix; char *name = 0; struct type *context; switch (*++p) { case 'f': prefix = vptr_name; break; case 'b': prefix = vb_name; break; default: complain (&invalid_cpp_abbrev_complaint, *pp); prefix = "INVALID_C++_ABBREV"; break; } *pp = p + 1; context = read_type (pp, objfile);#ifdef maybe_this_is_fixed /* * Patch from Michael N. Lipp. * 9204021327.AA02196@mailhost.dtro.e-technik.th-darmstadt.de> * XXX - this isn't the right way to fix it, but it will at * least keep gdb from faulting. */ /* if the ommitted type name is the name of the struct being read, the name is not yet in TYPE_NAME(context). Use long_kludge_name as a quick fix. */ if (context == type) name = long_kludge_name; else#endif name = type_name_no_tag (context); if (name == 0) { complain (&invalid_cpp_type_complaint, (char *) symnum); name = "FOO"; } list->field.name = obconcat (&objfile -> type_obstack, prefix, name, ""); p = ++(*pp); if (p[-1] != ':') complain (&invalid_cpp_abbrev_complaint, *pp); list->field.type = read_type (pp, objfile); (*pp)++; /* Skip the comma. */ list->field.bitpos = read_number (pp, ';'); /* This field is unpacked. */ list->field.bitsize = 0; list->visibility = 0; /* private */ non_public_fields++; nfields++; continue; } else complain (&invalid_cpp_abbrev_complaint, *pp); } while (*p != ':') p++; list->field.name = obsavestring (*pp, p - *pp, &objfile -> type_obstack); /* C++: Check to see if we have hit the methods yet. */ if (p[1] == ':') break; *pp = p + 1; /* This means we have a visibility for a field coming. */ if (**pp == '/') { switch (*++*pp) { case '0': list->visibility = 0; /* private */ non_public_fields++; *pp += 1; break; case '1': list->visibility = 1; /* protected */ non_public_fields++; *pp += 1; break; case '2': list->visibility = 2; /* public */ *pp += 1; break; } } else /* normal dbx-style format. */ list->visibility = 2; /* public */ list->field.type = read_type (pp, objfile); if (**pp == ':') { p = ++(*pp);#if 0 /* Possible future hook for nested types. */ if (**pp == '!') { list->field.bitpos = (long)-2; /* nested type */ p = ++(*pp); } else#endif { /* Static class member. */ list->field.bitpos = (long)-1; } while (*p != ';') p++; list->field.bitsize = (long) savestring (*pp, p - *pp); *pp = p + 1; nfields++; continue; } else if (**pp != ',') /* Bad structure-type format. */ return error_type (pp); (*pp)++; /* Skip the comma. */ list->field.bitpos = read_number (pp, ','); list->field.bitsize = read_number (pp, ';');#if 0 /* FIXME-tiemann: Can't the compiler put out something which lets us distinguish these? (or maybe just not put out anything for the field). What is the story here? What does the compiler really do? Also, patch gdb.texinfo for this case; I document it as a possible problem there. Search for "DBX-style". */ /* This is wrong because this is identical to the symbols produced for GCC 0-size arrays. For example: typedef union { int num; char str[0]; } foo; The code which dumped core in such circumstances should be fixed not to dump core. */ /* g++ -g0 can put out bitpos & bitsize zero for a static field. This does not give us any way of getting its class, so we can't know its name. But we can just ignore the field so we don't dump core and other nasty stuff. */ if (list->field.bitpos == 0 && list->field.bitsize == 0) { complain (&dbx_class_complaint, 0); /* Ignore this field. */ list = list->next; } else#endif /* 0 */ { /* Detect an unpacked field and mark it as such. dbx gives a bit size for all fields. Note that forward refs cannot be packed, and treat enums as if they had the width of ints. */ if (TYPE_CODE (list->field.type) != TYPE_CODE_INT && TYPE_CODE (list->field.type) != TYPE_CODE_ENUM) list->field.bitsize = 0; if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type) || (TYPE_CODE (list->field.type) == TYPE_CODE_ENUM && (list->field.bitsize == 8 * TYPE_LENGTH (lookup_fundamental_type (objfile, FT_INTEGER))) ) ) && list->field.bitpos % 8 == 0) list->field.bitsize = 0; nfields++; } } if (p[1] == ':') /* chill the list of fields: the last entry (at the head) is a partially constructed entry which we now scrub. */ list = list->next; /* Now create the vector of fields, and record how big it is. We need this info to record proper virtual function table information for this class's virtual functions. */ TYPE_NFIELDS (type) = nfields; TYPE_FIELDS (type) = (struct field *) TYPE_ALLOC (type, sizeof (struct field) * nfields); memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields); if (non_public_fields) { ALLOCATE_CPLUS_STRUCT_TYPE (type); TYPE_FIELD_PRIVATE_BITS (type) = (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields); TYPE_FIELD_PROTECTED_BITS (type) = (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields); } /* Copy the saved-up fields into the field vector. */ for (n = nfields; list; list = list->next) { n -= 1; TYPE_FIELD (type, n) = list->field; if (list->visibility == 0) SET_TYPE_FIELD_PRIVATE (type, n); else if (list->visibility == 1) SET_TYPE_FIELD_PROTECTED (type, n); } /* Now come the method fields, as NAME::methods where each method is of the form TYPENUM,ARGS,...:PHYSNAME; At the end, we see a semicolon instead of a field. For the case of overloaded operators, the format is op$::*.methods, where $ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator name (such as `+=') and `.' marks the end of the operator name. */ if (p[1] == ':') { /* Now, read in the methods. To simplify matters, we "unread" the name that has been read, so that we can start from the top. */ ALLOCATE_CPLUS_STRUCT_TYPE (type); /* For each list of method lists... */ do { int i; struct next_fnfield *sublist = 0; struct type *look_ahead_type = NULL; int length = 0; struct next_fnfieldlist *new_mainlist; char *main_fn_name; new_mainlist = (struct next_fnfieldlist *) alloca (sizeof (struct next_fnfieldlist)); memset (new_mainlist, 0, sizeof (struct next_fnfieldlist)); p = *pp; /* read in the name. */ while (*p != ':') p++; if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == CPLUS_MARKER) { /* This is a completely wierd case. In order to stuff in the names that might contain colons (the usual name delimiter), Mike Tiemann defined a different name format which is signalled if the identifier is "op$". In that case, the format is "op$::XXXX." where XXXX is the name. This is used for names like "+" or "=". YUUUUUUUK! FIXME! */ /* This lets the user type "break operator+". We could just put in "+" as the name, but that wouldn't work for "*". */ static char opname[32] = {'o', 'p', CPLUS_MARKER}; char *o = opname + 3; /* Skip past '::'. */ *pp = p + 2; if (**pp == '\\') *pp = next_symbol_text (); p = *pp; while (*p != '.') *o++ = *p++; main_fn_name = savestring (opname, o - opname); /* Skip past '.' */ *pp = p + 1; } else { main_fn_name = savestring (*pp, p - *pp); /* Skip past '::'. */ *pp = p + 2; } new_mainlist->fn_fieldlist.name = main_fn_name; do { struct next_fnfield *new_sublist = (struct next_fnfield *) alloca (sizeof (struct next_fnfield)); memset (new_sublist, 0, sizeof (struct next_fnfield)); /* Check for and handle cretinous dbx symbol name continuation! */ if (look_ahead_type == NULL) /* Normal case. */ { if (**pp == '\\') *pp = next_symbol_text (); new_sublist->fn_field.type = read_type (pp, objfile); if (**pp != ':') /* Invalid symtab info for method. */ return error_type (pp); } else { /* g++ version 1 kludge */ new_sublist->fn_field.type = look_ahead_type; look_ahead_type = NULL; } *pp += 1; p = *pp; while (*p != ';') p++; /* 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) new_sublist->fn_field.is_stub = 1; new_sublist->fn_field.physname = savestring (*pp, p - *pp); *pp = p + 1; /* Set this method's visibility fields. */ switch (*(*pp)++ - '0') { case 0: new_sublist->fn_field.is_private = 1; break; case 1: new_sublist->fn_field.is_protected = 1; break; } if (**pp == '\\') *pp = next_symbol_text (); switch (**pp) { case 'A': /* Normal functions. */ new_sublist->fn_field.is_const = 0; new_sublist->fn_field.is_volatile = 0; (*pp)++; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -