📄 dbxout.c
字号:
We want the value of that CONST_INT. */ current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (XEXP (DECL_RTL (decl), 0), 0)); } /* Effectively do build_pointer_type, but don't cache this type, since it might be temporary whereas the type it points to might have been saved for inlining. */ /* Don't use REFERENCE_TYPE because dbx can't handle that. */ type = make_node (POINTER_TYPE); TREE_TYPE (type) = TREE_TYPE (decl); } else if (GET_CODE (DECL_RTL (decl)) == MEM && GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG) { current_sym_code = N_LSYM; current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (decl), 0)); } else if (GET_CODE (DECL_RTL (decl)) == MEM && GET_CODE (XEXP (DECL_RTL (decl), 0)) == PLUS && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 1)) == CONST_INT) { current_sym_code = N_LSYM; /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))) We want the value of that CONST_INT. */ current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (decl), 0)); } else if (GET_CODE (DECL_RTL (decl)) == MEM && GET_CODE (XEXP (DECL_RTL (decl), 0)) == CONST) { /* Handle an obscure case which can arise when optimizing and when there are few available registers. (This is *always* the case for i386/i486 targets). The DECL_RTL looks like (MEM (CONST ...)) even though this variable is a local `auto' or a local `register' variable. In effect, what has happened is that the reload pass has seen that all assignments and references for one such a local variable can be replaced by equivalent assignments and references to some static storage variable, thereby avoiding the need for a register. In such cases we're forced to lie to debuggers and tell them that this variable was itself `static'. */ current_sym_code = N_LCSYM; letter = 'V'; current_sym_addr = XEXP (XEXP (DECL_RTL (decl), 0), 0); } else /* Address might be a MEM, when DECL is a variable-sized object. Or it might be const0_rtx, meaning previous passes want us to ignore this variable. */ break; /* Ok, start a symtab entry and output the variable name. */ FORCE_TEXT;#ifdef DBX_STATIC_BLOCK_START DBX_STATIC_BLOCK_START (asmfile, current_sym_code);#endif /* One slight hitch: if this is a VAR_DECL which is a static class member, we must put out the mangled name instead of the DECL_NAME. */ { char *name; /* Note also that static member (variable) names DO NOT begin with underscores in .stabs directives. */ if (DECL_LANG_SPECIFIC (decl)) name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); else name = IDENTIFIER_POINTER (DECL_NAME (decl)); fprintf (asmfile, "%s \"%s:", ASM_STABS_OP, name); } if (letter) putc (letter, asmfile); dbxout_type (type, 0, 0); dbxout_finish_symbol (decl);#ifdef DBX_STATIC_BLOCK_END DBX_STATIC_BLOCK_END (asmfile, current_sym_code);#endif break; }}static voiddbxout_prepare_symbol (decl) tree decl;{#ifdef WINNING_GDB char *filename = DECL_SOURCE_FILE (decl); dbxout_source_file (asmfile, filename);#endif}static voiddbxout_finish_symbol (sym) tree sym;{#ifdef DBX_FINISH_SYMBOL DBX_FINISH_SYMBOL (sym);#else int line = 0;#ifdef WINNING_GDB if (sym != 0) line = DECL_SOURCE_LINE (sym);#endif fprintf (asmfile, "\",%d,0,%d,", current_sym_code, line); if (current_sym_addr) output_addr_const (asmfile, current_sym_addr); else fprintf (asmfile, "%d", current_sym_value); putc ('\n', asmfile);#endif}/* Output definitions of all the decls in a chain. */voiddbxout_syms (syms) tree syms;{ while (syms) { dbxout_symbol (syms, 1); syms = TREE_CHAIN (syms); }}/* The following two functions output definitions of function parameters. Each parameter gets a definition locating it in the parameter list. Each parameter that is a register variable gets a second definition locating it in the register. Printing or argument lists in gdb uses the definitions that locate in the parameter list. But reference to the variable in expressions uses preferentially the definition as a register. *//* Output definitions, referring to storage in the parmlist, of all the parms in PARMS, which is a chain of PARM_DECL nodes. */voiddbxout_parms (parms) tree parms;{ for (; parms; parms = TREE_CHAIN (parms)) if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node) { dbxout_prepare_symbol (parms); /* Perform any necessary register eliminations on the parameter's rtl, so that the debugging output will be accurate. */ DECL_INCOMING_RTL (parms) = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX); DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);#ifdef LEAF_REG_REMAP if (leaf_function) { leaf_renumber_regs_insn (DECL_INCOMING_RTL (parms)); leaf_renumber_regs_insn (DECL_RTL (parms)); }#endif if (PARM_PASSED_IN_MEMORY (parms)) { rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0); /* ??? Here we assume that the parm address is indexed off the frame pointer or arg pointer. If that is not true, we produce meaningless results, but do not crash. */ if (GET_CODE (addr) == PLUS && GET_CODE (XEXP (addr, 1)) == CONST_INT) current_sym_value = INTVAL (XEXP (addr, 1)); else current_sym_value = 0; current_sym_code = N_PSYM; current_sym_addr = 0; FORCE_TEXT; if (DECL_NAME (parms)) { current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms)); fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (parms)), DBX_MEMPARM_STABS_LETTER); } else { current_sym_nchars = 8; fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP, DBX_MEMPARM_STABS_LETTER); } if (GET_CODE (DECL_RTL (parms)) == REG && REGNO (DECL_RTL (parms)) >= 0 && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) dbxout_type (DECL_ARG_TYPE (parms), 0, 0); else { int original_value = current_sym_value; /* This is the case where the parm is passed as an int or double and it is converted to a char, short or float and stored back in the parmlist. In this case, describe the parm with the variable's declared type, and adjust the address if the least significant bytes (which we are using) are not the first ones. */#if BYTES_BIG_ENDIAN if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms)) current_sym_value += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms))) - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));#endif if (GET_CODE (DECL_RTL (parms)) == MEM && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == current_sym_value) dbxout_type (TREE_TYPE (parms), 0, 0); else { current_sym_value = original_value; dbxout_type (DECL_ARG_TYPE (parms), 0, 0); } } current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr); dbxout_finish_symbol (parms); } else if (GET_CODE (DECL_RTL (parms)) == REG) { rtx best_rtl; char regparm_letter; /* Parm passed in registers and lives in registers or nowhere. */ current_sym_code = DBX_REGPARM_STABS_CODE; regparm_letter = DBX_REGPARM_STABS_LETTER; current_sym_addr = 0; /* If parm lives in a register, use that register; pretend the parm was passed there. It would be more consistent to describe the register where the parm was passed, but in practice that register usually holds something else. */ if (REGNO (DECL_RTL (parms)) >= 0 && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) best_rtl = DECL_RTL (parms); /* If the parm lives nowhere, use the register where it was passed. */ else best_rtl = DECL_INCOMING_RTL (parms); current_sym_value = DBX_REGISTER_NUMBER (REGNO (best_rtl)); FORCE_TEXT; if (DECL_NAME (parms)) { current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms)); fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (parms)), regparm_letter); } else { current_sym_nchars = 8; fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP, regparm_letter); } dbxout_type (DECL_ARG_TYPE (parms), 0, 0); dbxout_finish_symbol (parms); } else if (GET_CODE (DECL_RTL (parms)) == MEM && GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG)/* && rtx_equal_p (XEXP (DECL_RTL (parms), 0), DECL_INCOMING_RTL (parms))) */ { /* Parm was passed via invisible reference. That is, its address was passed in a register. Output it as if it lived in that register. The debugger will know from the type that it was actually passed by invisible reference. */ char regparm_letter; /* Parm passed in registers and lives in registers or nowhere. */ current_sym_code = DBX_REGPARM_STABS_CODE; regparm_letter = DBX_REGPARM_STABS_LETTER; /* DECL_RTL looks like (MEM (REG...). Get the register number. */ current_sym_value = REGNO (XEXP (DECL_RTL (parms), 0)); current_sym_addr = 0; FORCE_TEXT; if (DECL_NAME (parms)) { current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms))); fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (parms)), DBX_REGPARM_STABS_LETTER); } else { current_sym_nchars = 8; fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP, DBX_REGPARM_STABS_LETTER); } dbxout_type (TREE_TYPE (parms), 0, 0); dbxout_finish_symbol (parms); } else if (GET_CODE (DECL_RTL (parms)) == MEM && XEXP (DECL_RTL (parms), 0) != const0_rtx) { /* Parm was passed in registers but lives on the stack. */ current_sym_code = N_PSYM; /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))), in which case we want the value of that CONST_INT, or (MEM (REG ...)) or (MEM (MEM ...)), in which case we use a value of zero. */ if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG || GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM) current_sym_value = 0; else current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)); current_sym_addr = 0; FORCE_TEXT; if (DECL_NAME (parms)) { current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms))); fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (parms)), DBX_MEMPARM_STABS_LETTER); } else { current_sym_nchars = 8; fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP, DBX_MEMPARM_STABS_LETTER); } current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, XEXP (DECL_RTL (parms), 0)); dbxout_type (TREE_TYPE (parms), 0, 0); dbxout_finish_symbol (parms); } }}/* Output definitions for the places where parms live during the function, when different from where they were passed, when the parms were passed in memory. It is not useful to do this for parms passed in registers that live during the function in different registers, because it is impossible to look in the passed register for the passed value, so we use the within-the-function register to begin with. PARMS is a chain of PARM_DECL nodes. */voiddbxout_reg_parms (parms) tree parms;{ for (; parms; parms = TREE_CHAIN (parms)) if (DECL_NAME (parms)) { dbxout_prepare_symbol (parms); /* Report parms that live in registers during the function but were passed in memory. */ if (GET_CODE (DECL_RTL (parms)) == REG && REGNO (DECL_RTL (parms)) >= 0 && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER && PARM_PASSED_IN_MEMORY (parms)) { current_sym_code = N_RSYM; current_sym_value = DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms))); current_sym_addr = 0; FORCE_TEXT; if (DECL_NAME (parms)) { current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms)); fprintf (asmfile, "%s \"%s:r", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (parms))); } else { current_sym_nchars = 8; fprintf (asmfile, "%s \"(anon):r", ASM_STABS_OP); } dbxout_type (TREE_TYPE (parms), 0, 0); dbxout_finish_symbol (parms); } /* Report parms that live in memory but not where they were passed. */ else if (GET_CODE (DECL_RTL (parms)) == MEM && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT && PARM_PASSED_IN_MEMORY (parms) && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms))) {#if 0 /* ??? It is not clear yet what should replace this. */ int offset = DECL_OFFSET (parms) / BITS_PER_UNIT; /* A parm declared char is really passed as an int, so it occupies the least significant bytes. On a big-endian machine those are not the low-numbered ones. */#if BYTES_BIG_ENDIAN if (offset != -1 && TREE_TYPE (parms) != DECL_ARG_TYPE (parms)) offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms))) - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));#endif if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...}#endif current_sym_code = N_LSYM; current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (parms), 0)); current_sym_addr = 0; FORCE_TEXT; if (DECL_NAME (parms)) { current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms)); fprintf (asmfile, "%s \"%s:", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (parms))); } e
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -