📄 dbxout.c
字号:
putc (';', asmfile); CHARS (3); } break; case ENUMERAL_TYPE: /* We must use the same test here as we use in the DBX_NO_XREFS case above. We simplify it a bit since an enum will never have a variable size. */ if ((TYPE_NAME (type) != 0 && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && DECL_IGNORED_P (TYPE_NAME (type))) && !full) || TYPE_SIZE (type) == 0) { fprintf (asmfile, "xe"); CHARS (3); dbxout_type_name (type); typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF; fprintf (asmfile, ":"); return; }#ifdef DBX_OUTPUT_ENUM DBX_OUTPUT_ENUM (asmfile, type);#else if (use_gnu_debug_info_extensions && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)) fprintf (asmfile, "@s%d;", TYPE_PRECISION (type)); putc ('e', asmfile); CHARS (1); for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem)) { fprintf (asmfile, "%s:", IDENTIFIER_POINTER (TREE_PURPOSE (tem))); if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == 0) fprintf (asmfile, "%lu", (unsigned long) TREE_INT_CST_LOW (TREE_VALUE (tem))); else if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == -1 && TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0) fprintf (asmfile, "%ld", (long) TREE_INT_CST_LOW (TREE_VALUE (tem))); else print_int_cst_octal (TREE_VALUE (tem)); fprintf (asmfile, ","); CHARS (20 + IDENTIFIER_LENGTH (TREE_PURPOSE (tem))); if (TREE_CHAIN (tem) != 0) CONTIN; } putc (';', asmfile); CHARS (1);#endif break; case POINTER_TYPE: putc ('*', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); break; case METHOD_TYPE: if (use_gnu_debug_info_extensions) { have_used_extensions = 1; putc ('#', asmfile); CHARS (1); if (flag_minimal_debug && !show_arg_types) { /* Normally, just output the return type. The argument types are encoded in the method name. */ putc ('#', asmfile); dbxout_type (TREE_TYPE (type), 0, 0); putc (';', asmfile); CHARS (1); } else { /* When outputting destructors, we need to write the argument types out longhand. */ dbxout_type (TYPE_METHOD_BASETYPE (type), 0, 0); putc (',', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); dbxout_args (TYPE_ARG_TYPES (type)); putc (';', asmfile); CHARS (1); } } else { /* Treat it as a function type. */ dbxout_type (TREE_TYPE (type), 0, 0); } break; case OFFSET_TYPE: if (use_gnu_debug_info_extensions) { have_used_extensions = 1; putc ('@', asmfile); CHARS (1); dbxout_type (TYPE_OFFSET_BASETYPE (type), 0, 0); putc (',', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); } else { /* Should print as an int, because it is really just an offset. */ dbxout_type (integer_type_node, 0, 0); } break; case REFERENCE_TYPE: if (use_gnu_debug_info_extensions) have_used_extensions = 1; putc (use_gnu_debug_info_extensions ? '&' : '*', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); break; case FUNCTION_TYPE: putc ('f', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); break; default: abort (); }}/* Print the value of integer constant C, in octal, handling double precision. */static voidprint_int_cst_octal (c) tree c;{ unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (c); unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (c); int excess = (3 - (HOST_BITS_PER_WIDE_INT % 3)); int width = TYPE_PRECISION (TREE_TYPE (c)); /* GDB wants constants with no extra leading "1" bits, so we need to remove any sign-extension that might be present. */ if (width == HOST_BITS_PER_WIDE_INT * 2) ; else if (width > HOST_BITS_PER_WIDE_INT) high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1); else if (width == HOST_BITS_PER_WIDE_INT) high = 0; else high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1); fprintf (asmfile, "0"); if (excess == 3) { print_octal (high, HOST_BITS_PER_WIDE_INT / 3); print_octal (low, HOST_BITS_PER_WIDE_INT / 3); } else { unsigned HOST_WIDE_INT beg = high >> excess; unsigned HOST_WIDE_INT middle = ((high & (((HOST_WIDE_INT) 1 << excess) - 1)) << (3 - excess) | (low >> (HOST_BITS_PER_WIDE_INT / 3 * 3))); unsigned HOST_WIDE_INT end = low & (((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 3 * 3)) - 1); fprintf (asmfile, "%o%01o", beg, middle); print_octal (end, HOST_BITS_PER_WIDE_INT / 3); }}static voidprint_octal (value, digits) unsigned HOST_WIDE_INT value; int digits;{ int i; for (i = digits - 1; i >= 0; i--) fprintf (asmfile, "%01o", ((value >> (3 * i)) & 7));}/* Output the name of type TYPE, with no punctuation. Such names can be set up either by typedef declarations or by struct, enum and union tags. */static voiddbxout_type_name (type) register tree type;{ tree t; if (TYPE_NAME (type) == 0) abort (); if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) { t = TYPE_NAME (type); } else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) { t = DECL_NAME (TYPE_NAME (type)); } else abort (); fprintf (asmfile, "%s", IDENTIFIER_POINTER (t)); CHARS (IDENTIFIER_LENGTH (t));}/* Output a .stabs for the symbol defined by DECL, which must be a ..._DECL node in the normal namespace. It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL. LOCAL is nonzero if the scope is less than the entire file. */voiddbxout_symbol (decl, local) tree decl; int local;{ tree type = TREE_TYPE (decl); tree context = NULL_TREE; /* Cast avoids warning in old compilers. */ current_sym_code = (STAB_CODE_TYPE) 0; current_sym_value = 0; current_sym_addr = 0; /* Ignore nameless syms, but don't ignore type tags. */ if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL) || DECL_IGNORED_P (decl)) return; dbxout_prepare_symbol (decl); /* The output will always start with the symbol name, so always count that in the length-output-so-far. */ if (DECL_NAME (decl) != 0) current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (decl)); switch (TREE_CODE (decl)) { case CONST_DECL: /* Enum values are defined by defining the enum type. */ break; case FUNCTION_DECL: if (DECL_RTL (decl) == 0) return; if (DECL_EXTERNAL (decl)) break; /* Don't mention a nested function under its parent. */ context = decl_function_context (decl); if (context == current_function_decl) break; if (GET_CODE (DECL_RTL (decl)) != MEM || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF) break; FORCE_TEXT; fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), TREE_PUBLIC (decl) ? 'F' : 'f'); current_sym_code = N_FUN; current_sym_addr = XEXP (DECL_RTL (decl), 0); if (TREE_TYPE (type)) dbxout_type (TREE_TYPE (type), 0, 0); else dbxout_type (void_type_node, 0, 0); /* For a nested function, when that function is compiled, mention the containing function name as well as (since dbx wants it) our own assembler-name. */ if (context != 0) fprintf (asmfile, ",%s,%s", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), IDENTIFIER_POINTER (DECL_NAME (context))); dbxout_finish_symbol (decl); break; case TYPE_DECL:#if 0 /* This seems all wrong. Outputting most kinds of types gives no name at all. A true definition gives no name; a cross-ref for a structure can give the tag name, but not a type name. It seems that no typedef name is defined by outputting a type. */ /* If this typedef name was defined by outputting the type, don't duplicate it. */ if (typevec[TYPE_SYMTAB_ADDRESS (type)] == TYPE_DEFINED && TYPE_NAME (TREE_TYPE (decl)) == decl) return;#endif /* Don't output the same typedef twice. And don't output what language-specific stuff doesn't want output. */ if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl)) return; FORCE_TEXT; { int tag_needed = 1; int did_output = 0; if (DECL_NAME (decl)) { /* Nonzero means we must output a tag as well as a typedef. */ tag_needed = 0; /* Handle the case of a C++ structure or union where the TYPE_NAME is a TYPE_DECL which gives both a typedef name and a tag. */ /* dbx requires the tag first and the typedef second. */ if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == QUAL_UNION_TYPE) && TYPE_NAME (type) == decl && !(use_gnu_debug_info_extensions && have_used_extensions) && !TREE_ASM_WRITTEN (TYPE_NAME (type)) /* Distinguish the implicit typedefs of C++ from explicit ones that might be found in C. */ && (!strcmp (lang_identify (), "cplusplus") /* The following line maybe unnecessary; in 2.6, try removing it. */ || DECL_SOURCE_LINE (decl) == 0)) { tree name = TYPE_NAME (type); if (TREE_CODE (name) == TYPE_DECL) name = DECL_NAME (name); current_sym_code = DBX_TYPE_DECL_STABS_CODE; current_sym_value = 0; current_sym_addr = 0; current_sym_nchars = 2 + IDENTIFIER_LENGTH (name); fprintf (asmfile, "%s \"%s:T", ASM_STABS_OP, IDENTIFIER_POINTER (name)); dbxout_type (type, 1, 0); dbxout_finish_symbol (NULL_TREE); } /* Output typedef name. */ fprintf (asmfile, "%s \"%s:", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (decl))); /* Short cut way to output a tag also. */ if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == QUAL_UNION_TYPE) && TYPE_NAME (type) == decl) { if (use_gnu_debug_info_extensions && have_used_extensions) { putc ('T', asmfile); TREE_ASM_WRITTEN (TYPE_NAME (type)) = 1; }#if 0 /* Now we generate the tag for this case up above. */ else tag_needed = 1;#endif } putc ('t', asmfile); current_sym_code = DBX_TYPE_DECL_STABS_CODE; dbxout_type (type, 1, 0); dbxout_finish_symbol (decl); did_output = 1; } /* Don't output a tag if this is an incomplete type (TYPE_SIZE is zero). This prevents the sun4 Sun OS 4.x dbx from crashing. */ if (tag_needed && TYPE_NAME (type) != 0 && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE || (DECL_NAME (TYPE_NAME (type)) != 0)) && TYPE_SIZE (type) != 0 && !TREE_ASM_WRITTEN (TYPE_NAME (type))) { /* For a TYPE_DECL with no name, but the type has a name, output a tag. This is what represents `struct foo' with no typedef. */ /* In C++, the name of a type is the corresponding typedef. In C, it is an IDENTIFIER_NODE. */ tree name = TYPE_NAME (type); if (TREE_CODE (name) == TYPE_DECL) name = DECL_NAME (name); current_sym_code = DBX_TYPE_DECL_STABS_CODE; current_sym_value = 0; current_sym_addr = 0; current_sym_nchars = 2 + IDENTIFIER_LENGTH (name); fprintf (asmfile, "%s \"%s:T", ASM_STABS_OP, IDENTIFIER_POINTER (name)); dbxout_type (type, 1, 0); dbxout_finish_symbol (NULL_TREE); did_output = 1; } /* If an enum type has no name, it cannot be referred to, but we must output it anyway, since the enumeration constants can be referred to. */ if (!did_output && TREE_CODE (type) == ENUMERAL_TYPE) { current_sym_code = DBX_TYPE_DECL_STABS_CODE; current_sym_value = 0; current_sym_addr = 0; current_sym_nchars = 2; /* Some debuggers fail when given NULL names, so give this a harmless name of ` '. */ fprintf (asmfile, "%s \" :T", ASM_STABS_OP); dbxout_type (type, 1, 0); dbxout_finish_symbol (NULL_TREE); } /* Prevent duplicate output of a typedef. */ TREE_ASM_WRITTEN (decl) = 1; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -