stabs.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,559 行 · 第 1/5 页
C
2,559 行
return false; /* End an inner lexical block. */ if (! debug_end_block (dhandle, (value + info->file_start_offset + info->function_start_offset))) return false; --info->block_depth; if (info->block_depth < 0) { fprintf (stderr, _("Too many N_RBRACs\n")); return false; } break; case N_SO: /* This always ends a function. */ if (info->within_function) { bfd_vma endval; endval = value; if (*string != '\0' && info->function_end != (bfd_vma) -1 && info->function_end < endval) endval = info->function_end; if (! stab_emit_pending_vars (dhandle, info) || ! debug_end_function (dhandle, endval)) return false; info->within_function = false; info->function_end = (bfd_vma) -1; } /* An empty string is emitted by gcc at the end of a compilation unit. */ if (*string == '\0') return true; /* Just accumulate strings until we see a non N_SO symbol. If the string starts with a directory separator or some other form of absolute path specification, we discard the previously accumulated strings. */ if (info->so_string == NULL) info->so_string = xstrdup (string); else { char *f; f = info->so_string; if (IS_ABSOLUTE_PATH (string)) info->so_string = xstrdup (string); else info->so_string = concat (info->so_string, string, (const char *) NULL); free (f); } info->so_value = value; break; case N_SOL: /* Start an include file. */ if (! debug_start_source (dhandle, string)) return false; break; case N_BINCL: /* Start an include file which may be replaced. */ push_bincl (info, string, value); if (! debug_start_source (dhandle, string)) return false; break; case N_EINCL: /* End an N_BINCL include. */ if (! debug_start_source (dhandle, pop_bincl (info))) return false; break; case N_EXCL: /* This is a duplicate of a header file named by N_BINCL which was eliminated by the linker. */ if (! find_excl (info, string, value)) return false; break; case N_SLINE: if (! debug_record_line (dhandle, desc, value + info->function_start_offset)) return false; break; case N_BCOMM: if (! debug_start_common_block (dhandle, string)) return false; break; case N_ECOMM: if (! debug_end_common_block (dhandle, string)) return false; break; case N_FUN: if (*string == '\0') { if (info->within_function) { /* This always marks the end of a function; we don't need to worry about info->function_end. */ if (info->sections) value += info->function_start_offset; if (! stab_emit_pending_vars (dhandle, info) || ! debug_end_function (dhandle, value)) return false; info->within_function = false; info->function_end = (bfd_vma) -1; } break; } /* A const static symbol in the .text section will have an N_FUN entry. We need to use these to mark the end of the function, in case we are looking at gcc output before it was changed to always emit an empty N_FUN. We can't call debug_end_function here, because it might be a local static symbol. */ if (info->within_function && (info->function_end == (bfd_vma) -1 || value < info->function_end)) info->function_end = value; /* Fall through. */ /* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM symbols, and if it does not start with :S, gdb relocates the value to the start of the section. gcc always seems to use :S, so we don't worry about this. */ /* Fall through. */ default: { const char *colon; colon = strchr (string, ':'); if (colon != NULL && (colon[1] == 'f' || colon[1] == 'F')) { if (info->within_function) { bfd_vma endval; endval = value; if (info->function_end != (bfd_vma) -1 && info->function_end < endval) endval = info->function_end; if (! stab_emit_pending_vars (dhandle, info) || ! debug_end_function (dhandle, endval)) return false; info->function_end = (bfd_vma) -1; } /* For stabs in sections, line numbers and block addresses are offsets from the start of the function. */ if (info->sections) info->function_start_offset = value; info->within_function = true; } if (! parse_stab_string (dhandle, info, type, desc, value, string)) return false; } break; case N_OPT: if (string != NULL && strcmp (string, "gcc2_compiled.") == 0) info->gcc_compiled = 2; else if (string != NULL && strcmp (string, "gcc_compiled.") == 0) info->gcc_compiled = 1; else info->n_opt_found = true; break; case N_OBJ: case N_ENDM: case N_MAIN: case N_WARNING: break; } return true;}/* Parse the stabs string. */static booleanparse_stab_string (dhandle, info, stabtype, desc, value, string) PTR dhandle; struct stab_handle *info; int stabtype; int desc; bfd_vma value; const char *string;{ const char *p; char *name; int type; debug_type dtype; boolean synonym; boolean self_crossref; unsigned int lineno; debug_type *slot; p = strchr (string, ':'); if (p == NULL) return true; while (p[1] == ':') { p += 2; p = strchr (p, ':'); if (p == NULL) { bad_stab (string); return false; } } /* GCC 2.x puts the line number in desc. SunOS apparently puts in the number of bytes occupied by a type or object, which we ignore. */ if (info->gcc_compiled >= 2) lineno = desc; else lineno = 0; /* FIXME: Sometimes the special C++ names start with '.'. */ name = NULL; if (string[0] == '$') { switch (string[1]) { case 't': name = "this"; break; case 'v': /* Was: name = "vptr"; */ break; case 'e': name = "eh_throw"; break; case '_': /* This was an anonymous type that was never fixed up. */ break; case 'X': /* SunPRO (3.0 at least) static variable encoding. */ break; default: warn_stab (string, _("unknown C++ encoded name")); break; } } if (name == NULL) { if (p == string || (string[0] == ' ' && p == string + 1)) name = NULL; else name = savestring (string, p - string); } ++p; if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-') type = 'l'; else type = *p++; switch (type) { case 'c': /* c is a special case, not followed by a type-number. SYMBOL:c=iVALUE for an integer constant symbol. SYMBOL:c=rVALUE for a floating constant symbol. SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol. e.g. "b:c=e6,0" for "const b = blob1" (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */ if (*p != '=') { bad_stab (string); return false; } ++p; switch (*p++) { case 'r': /* Floating point constant. */ if (! debug_record_float_const (dhandle, name, atof (p))) return false; break; case 'i': /* Integer constant. */ /* Defining integer constants this way is kind of silly, since 'e' constants allows the compiler to give not only the value, but the type as well. C has at least int, long, unsigned int, and long long as constant types; other languages probably should have at least unsigned as well as signed constants. */ if (! debug_record_int_const (dhandle, name, atoi (p))) return false; break; case 'e': /* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value can be represented as integral. e.g. "b:c=e6,0" for "const b = blob1" (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL); if (dtype == DEBUG_TYPE_NULL) return false; if (*p != ',') { bad_stab (string); return false; } if (! debug_record_typed_const (dhandle, name, dtype, atoi (p))) return false; break; default: bad_stab (string); return false; } break; case 'C': /* The name of a caught exception. */ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL); if (dtype == DEBUG_TYPE_NULL) return false; if (! debug_record_label (dhandle, name, dtype, value)) return false; break; case 'f': case 'F': /* A function definition. */ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL); if (dtype == DEBUG_TYPE_NULL) return false; if (! debug_record_function (dhandle, name, dtype, type == 'F', value)) return false; /* Sun acc puts declared types of arguments here. We don't care about their actual types (FIXME -- we should remember the whole function prototype), but the list may define some new types that we have to remember, so we must scan it now. */ while (*p == ';') { ++p; if (parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL) == DEBUG_TYPE_NULL) return false; } break; case 'G': { char leading; long c; asymbol **ps; /* A global symbol. The value must be extracted from the symbol table. */ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL); if (dtype == DEBUG_TYPE_NULL) return false; leading = bfd_get_symbol_leading_char (info->abfd); for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps) { const char *n; n = bfd_asymbol_name (*ps); if (leading != '\0' && *n == leading) ++n; if (*n == *name && strcmp (n, name) == 0) break; } if (c > 0) value = bfd_asymbol_value (*ps); if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL, value)) return false; } break; /* This case is faked by a conditional above, when there is no code letter in the dbx data. Dbx data never actually contains 'l'. */ case 'l': case 's': dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL); if (dtype == DEBUG_TYPE_NULL) return false; if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL, value)) return false; break; case 'p': /* A function parameter. */ if (*p != 'F') dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL); else { /* pF is a two-letter code that means a function parameter in Fortran. The type-number specifies the type of the return value. Translate it into a pointer-to-function type. */ ++p; dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL); if (dtype != DEBUG_TYPE_NULL) { debug_type ftype; ftype = debug_make_function_type (dhandle, dtype, (debug_type *) NULL, false); dtype = debug_make_pointer_type (dhandle, ftype); } } if (dtype == DEBUG_TYPE_NULL) return false; if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK, value)) return false; /* FIXME: At this point gdb considers rearranging the parameter address on a big endian machine if it is smaller than an int. We have no way to do that, since we don't really know much about the target. */ break; case 'P': if (stabtype == N_FUN) { /* Prototype of a function referenced by this file. */ while (*p == ';') { ++p; if (parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL) == DEBUG_TYPE_NULL) return false; } break; } /* Fall through. */ case 'R': /* Parameter which is in a register. */ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL); if (dtype == DEBUG_TYPE_NULL) return false; if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG, value)) return false; break; case 'r': /* Register variable (either global or local). */ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL); if (dtype == DEBUG_TYPE_NULL) return false; if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER, value)) return false; /* FIXME: At this point gdb checks to combine pairs of 'p' and 'r' stabs into a single 'P' stab. */ break; case 'S': /* Static symbol at top level of file */ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, (debug_type **) NULL); if (dtype == DEBUG_TYPE_NULL) return false; if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC, value)) return false; break; case 't': /* A typedef. */ dtype = parse_stab_type (dhandle, info, name, &p, &slot); if (dtype == DEBUG_TYPE_NULL) return false; if (name == NULL) { /* A nameless type. Nothing to do. */ return true; } dtype = debug_name_type (dhandle, name, dtype);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?