dwarf2out.c

来自「GCC编译器源代码」· C语言 代码 · 共 2,259 行 · 第 1/5 页

C
2,259
字号
/* Output Dwarf2 format symbol table information from the GNU C compiler.   Copyright (C) 1992, 1993, 1995, 1996, 1997 Free Software Foundation, Inc.   Contributed by Gary Funck (gary@intrepid.com).   Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).   Extensively modified by Jason Merrill (jason@cygnus.com).This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *//* The first part of this file deals with the DWARF 2 frame unwind   information, which is also used by the GCC efficient exception handling   mechanism.  The second part, controlled only by an #ifdef   DWARF2_DEBUGGING_INFO, deals with the other DWARF 2 debugging   information.  */#include "config.h"#include "defaults.h"#include <stdio.h>#include "tree.h"#include "flags.h"#include "rtl.h"#include "hard-reg-set.h"#include "regs.h"#include "insn-config.h"#include "reload.h"#include "output.h"#include "expr.h"#include "except.h"#include "dwarf2.h"/* We cannot use <assert.h> in GCC source, since that would include   GCC's assert.h, which may not be compatible with the host compiler.  */#undef assert#ifdef NDEBUG# define assert(e)#else# define assert(e) do { if (! (e)) abort (); } while (0)#endif/* Decide whether we want to emit frame unwind information for the current   translation unit.  */intdwarf2out_do_frame (){  return (write_symbols == DWARF2_DEBUG#ifdef DWARF2_UNWIND_INFO	  || (flag_exceptions && ! exceptions_via_longjmp)#endif	  );}#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)#ifndef __GNUC__#define inline#endif/* How to start an assembler comment.  */#ifndef ASM_COMMENT_START#define ASM_COMMENT_START ";#"#endiftypedef struct dw_cfi_struct *dw_cfi_ref;typedef struct dw_fde_struct *dw_fde_ref;typedef union  dw_cfi_oprnd_struct *dw_cfi_oprnd_ref;/* Call frames are described using a sequence of Call Frame   Information instructions.  The register number, offset   and address fields are provided as possible operands;   their use is selected by the opcode field.  */typedef union dw_cfi_oprnd_struct{  unsigned long dw_cfi_reg_num;  long int dw_cfi_offset;  char *dw_cfi_addr;}dw_cfi_oprnd;typedef struct dw_cfi_struct{  dw_cfi_ref dw_cfi_next;  enum dwarf_call_frame_info dw_cfi_opc;  dw_cfi_oprnd dw_cfi_oprnd1;  dw_cfi_oprnd dw_cfi_oprnd2;}dw_cfi_node;/* All call frame descriptions (FDE's) in the GCC generated DWARF   refer to a single Common Information Entry (CIE), defined at   the beginning of the .debug_frame section.  This used of a single   CIE obviates the need to keep track of multiple CIE's   in the DWARF generation routines below.  */typedef struct dw_fde_struct{  char *dw_fde_begin;  char *dw_fde_current_label;  char *dw_fde_end;  dw_cfi_ref dw_fde_cfi;}dw_fde_node;/* Maximum size (in bytes) of an artificially generated label.   */#define MAX_ARTIFICIAL_LABEL_BYTES	30/* Make sure we know the sizes of the various types dwarf can describe. These   are only defaults.  If the sizes are different for your target, you should   override these values by defining the appropriate symbols in your tm.h   file.  */#ifndef CHAR_TYPE_SIZE#define CHAR_TYPE_SIZE BITS_PER_UNIT#endif#ifndef PTR_SIZE#define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)#endif/* The size in bytes of a DWARF field indicating an offset or length   relative to a debug info section, specified to be 4 bytes in the DWARF-2   specification.  The SGI/MIPS ABI defines it to be the same as PTR_SIZE.  */#ifndef DWARF_OFFSET_SIZE#define DWARF_OFFSET_SIZE 4#endif#define DWARF_VERSION 2/* Round SIZE up to the nearest BOUNDARY.  */#define DWARF_ROUND(SIZE,BOUNDARY) \  (((SIZE) + (BOUNDARY) - 1) & ~((BOUNDARY) - 1))/* Offsets recorded in opcodes are a multiple of this alignment factor.  */#ifdef STACK_GROWS_DOWNWARD#define DWARF_CIE_DATA_ALIGNMENT (-UNITS_PER_WORD)#else#define DWARF_CIE_DATA_ALIGNMENT UNITS_PER_WORD#endif/* A pointer to the base of a table that contains frame description   information for each routine.  */static dw_fde_ref fde_table;/* Number of elements currently allocated for fde_table.  */static unsigned fde_table_allocated;/* Number of elements in fde_table currently in use.  */static unsigned fde_table_in_use;/* Size (in elements) of increments by which we may expand the   fde_table.  */#define FDE_TABLE_INCREMENT 256/* A list of call frame insns for the CIE.  */static dw_cfi_ref cie_cfi_head;/* The number of the current function definition for which debugging   information is being generated.  These numbers range from 1 up to the   maximum number of function definitions contained within the current   compilation unit.  These numbers are used to create unique label id's   unique to each function definition.  */static unsigned current_funcdef_number = 0;/* Some DWARF extensions (e.g., MIPS/SGI) implement a subprogram   attribute that accelerates the lookup of the FDE associated   with the subprogram.  This variable holds the table index of the FDE    associated with the current function (body) definition.  */static unsigned current_funcdef_fde;/* Forward declarations for functions defined in this file.  */static char *stripattributes		PROTO((char *));static char *dwarf_cfi_name		PROTO((unsigned));static dw_cfi_ref new_cfi		PROTO((void));static void add_cfi			PROTO((dw_cfi_ref *, dw_cfi_ref));static unsigned long size_of_uleb128	PROTO((unsigned long));static unsigned long size_of_sleb128	PROTO((long));static void output_uleb128		PROTO((unsigned long));static void output_sleb128		PROTO((long));static void add_fde_cfi			PROTO((char *, dw_cfi_ref));static void lookup_cfa_1		PROTO((dw_cfi_ref, unsigned long *,					       long *));static void lookup_cfa			PROTO((unsigned long *, long *));static void reg_save			PROTO((char *, unsigned, unsigned,					       long));static void initial_return_save		PROTO((rtx));static void output_cfi			PROTO((dw_cfi_ref, dw_fde_ref));static void output_call_frame_info	PROTO((int));static unsigned reg_number		PROTO((rtx));/* Definitions of defaults for assembler-dependent names of various   pseudo-ops and section names.   Theses may be overridden in the tm.h file (if necessary) for a particular   assembler.  */#ifdef OBJECT_FORMAT_ELF#ifndef UNALIGNED_SHORT_ASM_OP#define UNALIGNED_SHORT_ASM_OP	".2byte"#endif#ifndef UNALIGNED_INT_ASM_OP#define UNALIGNED_INT_ASM_OP	".4byte"#endif#ifndef UNALIGNED_DOUBLE_INT_ASM_OP#define UNALIGNED_DOUBLE_INT_ASM_OP	".8byte"#endif#endif /* OBJECT_FORMAT_ELF */#ifndef ASM_BYTE_OP#define ASM_BYTE_OP		".byte"#endif/* Data and reference forms for relocatable data.  */#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)/* Pseudo-op for defining a new section.  */#ifndef SECTION_ASM_OP#define SECTION_ASM_OP	".section"#endif/* The default format used by the ASM_OUTPUT_SECTION macro (see below) to   print the SECTION_ASM_OP and the section name.  The default here works for   almost all svr4 assemblers, except for the sparc, where the section name   must be enclosed in double quotes.  (See sparcv4.h).  */#ifndef SECTION_FORMAT#ifdef PUSHSECTION_FORMAT#define SECTION_FORMAT PUSHSECTION_FORMAT#else#define SECTION_FORMAT		"\t%s\t%s\n"#endif#endif#ifndef FRAME_SECTION#define FRAME_SECTION		".debug_frame"#endif#ifndef FUNC_BEGIN_LABEL#define FUNC_BEGIN_LABEL	"LFB"#endif#ifndef FUNC_END_LABEL#define FUNC_END_LABEL		"LFE"#endif#define CIE_AFTER_SIZE_LABEL	"LSCIE"#define CIE_END_LABEL		"LECIE"#define CIE_LENGTH_LABEL	"LLCIE"#define FDE_AFTER_SIZE_LABEL	"LSFDE"#define FDE_END_LABEL		"LEFDE"#define FDE_LENGTH_LABEL	"LLFDE"/* Definitions of defaults for various types of primitive assembly language   output operations.  These may be overridden from within the tm.h file,   but typically, that is unnecessary.  */#ifndef ASM_OUTPUT_SECTION#define ASM_OUTPUT_SECTION(FILE, SECTION) \  fprintf ((FILE), SECTION_FORMAT, SECTION_ASM_OP, SECTION)#endif#ifndef ASM_OUTPUT_DWARF_DATA1#define ASM_OUTPUT_DWARF_DATA1(FILE,VALUE) \  fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, VALUE)#endif#ifdef UNALIGNED_INT_ASM_OP#ifndef UNALIGNED_OFFSET_ASM_OP#define UNALIGNED_OFFSET_ASM_OP \  (DWARF_OFFSET_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)#endif#ifndef UNALIGNED_WORD_ASM_OP#define UNALIGNED_WORD_ASM_OP \  (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)#endif#ifndef ASM_OUTPUT_DWARF_DELTA2#define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2)			\ do {	fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP);		\	assemble_name (FILE, LABEL1);					\	fprintf (FILE, "-");						\	assemble_name (FILE, LABEL2);					\  } while (0)#endif#ifndef ASM_OUTPUT_DWARF_DELTA4#define ASM_OUTPUT_DWARF_DELTA4(FILE,LABEL1,LABEL2)			\ do {	fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP);		\	assemble_name (FILE, LABEL1);					\	fprintf (FILE, "-");						\	assemble_name (FILE, LABEL2);					\  } while (0)#endif#ifndef ASM_OUTPUT_DWARF_DELTA#define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2)			\ do {	fprintf ((FILE), "\t%s\t", UNALIGNED_OFFSET_ASM_OP);		\	assemble_name (FILE, LABEL1);					\	fprintf (FILE, "-");						\	assemble_name (FILE, LABEL2);					\  } while (0)#endif#ifndef ASM_OUTPUT_DWARF_ADDR_DELTA#define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE,LABEL1,LABEL2)			\ do {	fprintf ((FILE), "\t%s\t", UNALIGNED_WORD_ASM_OP);		\	assemble_name (FILE, LABEL1);					\	fprintf (FILE, "-");						\	assemble_name (FILE, LABEL2);					\  } while (0)#endif#ifndef ASM_OUTPUT_DWARF_ADDR#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL)				\ do {	fprintf ((FILE), "\t%s\t", UNALIGNED_WORD_ASM_OP);		\	assemble_name (FILE, LABEL);					\  } while (0)#endif#ifndef ASM_OUTPUT_DWARF_ADDR_CONST#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,ADDR)				\  fprintf ((FILE), "\t%s\t%s", UNALIGNED_WORD_ASM_OP, (ADDR))#endif#ifndef ASM_OUTPUT_DWARF_OFFSET#define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL)				\ do {	fprintf ((FILE), "\t%s\t", UNALIGNED_OFFSET_ASM_OP);		\	assemble_name (FILE, LABEL);					\  } while (0)#endif#ifndef ASM_OUTPUT_DWARF_DATA2#define ASM_OUTPUT_DWARF_DATA2(FILE,VALUE) \  fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, (unsigned) VALUE)#endif#ifndef ASM_OUTPUT_DWARF_DATA4#define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \  fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_INT_ASM_OP, (unsigned) VALUE)#endif#ifndef ASM_OUTPUT_DWARF_DATA#define ASM_OUTPUT_DWARF_DATA(FILE,VALUE) \  fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP, \	   (unsigned long) VALUE)#endif#ifndef ASM_OUTPUT_DWARF_ADDR_DATA#define ASM_OUTPUT_DWARF_ADDR_DATA(FILE,VALUE) \  fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_WORD_ASM_OP, \	   (unsigned long) VALUE)#endif#ifndef ASM_OUTPUT_DWARF_DATA8#define ASM_OUTPUT_DWARF_DATA8(FILE,HIGH_VALUE,LOW_VALUE)		\  do {									\    if (WORDS_BIG_ENDIAN)						\      {									\	fprintf ((FILE), "\t%s\t0x%x\n", UNALIGNED_INT_ASM_OP, HIGH_VALUE); \	fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_INT_ASM_OP, LOW_VALUE);\      }									\    else								\      {									\	fprintf ((FILE), "\t%s\t0x%x\n", UNALIGNED_INT_ASM_OP, LOW_VALUE);\	fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_INT_ASM_OP, HIGH_VALUE); \      }									\  } while (0)#endif#ifndef ASM_OUTPUT_DWARF_VALUE4#define ASM_OUTPUT_DWARF_VALUE4(FILE,LABEL) \  do {	fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP);		\	assemble_name (FILE, LABEL);					\  } while (0)#endif#else /* UNALIGNED_INT_ASM_OP *//* We don't have unaligned support, let's hope the normal output works for   .debug_frame.  */#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \  assemble_integer (gen_rtx (SYMBOL_REF, Pmode, LABEL), PTR_SIZE, 1)#define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL) \  assemble_integer (gen_rtx (SYMBOL_REF, SImode, LABEL), 4, 1)#define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2)			\  assemble_integer (gen_rtx (MINUS, HImode,			      	\			     gen_rtx (SYMBOL_REF, Pmode, LABEL1),   	\			     gen_rtx (SYMBOL_REF, Pmode, LABEL2)),	\		    2, 1)  #define ASM_OUTPUT_DWARF_DELTA4(FILE,LABEL1,LABEL2)			\  assemble_integer (gen_rtx (MINUS, SImode,			      	\			     gen_rtx (SYMBOL_REF, Pmode, LABEL1),   	\			     gen_rtx (SYMBOL_REF, Pmode, LABEL2)),	\		    4, 1)#define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE,LABEL1,LABEL2)			\  assemble_integer (gen_rtx (MINUS, Pmode,				\			     gen_rtx (SYMBOL_REF, Pmode, LABEL1),	\			     gen_rtx (SYMBOL_REF, Pmode, LABEL2)),	\		    PTR_SIZE, 1)#define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \  ASM_OUTPUT_DWARF_DELTA4 (FILE,LABEL1,LABEL2)#define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \  assemble_integer (GEN_INT (VALUE), 4, 1)#define ASM_OUTPUT_DWARF_VALUE4(FILE,LABEL) \  assemble_integer (gen_rtx (SYMBOL_REF, Pmode, LABEL), 4, 1)#endif /* UNALIGNED_INT_ASM_OP */#ifdef SET_ASM_OP#ifndef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO)	\  do {	fprintf ((FILE), "\t%s\t", SET_ASM_OP);				\	assemble_name (FILE, SY);					\	fprintf ((FILE), ",");						\	assemble_name (FILE, HI);					\	fprintf ((FILE), "-");						\	assemble_name (FILE, LO);					\	fprintf ((FILE), "\n");						\  } while (0)#endif#endif /* SET_ASM_OP *//* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing   newline is produced.  When flag_debug_asm is asserted, we add commentary   at the end of the line, so we must avoid output of a newline here.  */#ifndef ASM_OUTPUT_DWARF_STRING#define ASM_OUTPUT_DWARF_STRING(FILE,P) \  do {									      \    register int slen = strlen(P);                                            \    register char *p = (P);  	                                              \    register int i;					                      \

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?