⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 symout.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Output GDB-format symbol table information from GNU compiler.   Copyright (C) 1987, 1988 Free Software Foundation, Inc.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 1, 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.  */#include "config.h"#include "tree.h"#include "symseg.h"#include "rtl.h"#include "gdbfiles.h"#include <stdio.h>#undef NULL/* <...> used here so one can prevent use of ./stddef.h   by changing the -I options used.  */#include <stddef.h>/* Get N_SO from stab.h if we can expect the file to exist.  */#ifdef DBX_DEBUGGING_INFO#ifdef USG#include "gstab.h"  /* If doing DBX on sysV, use our own stab.h.  */#else#include <stab.h>  /* On BSD, use the system's stab.h.  */#endif /* not USG */#endif/* .stabs code for source file name.  */#ifndef N_SO#define	N_SO 0x64#endif/* Unix maximum on file name length.  Needed for getwd.  */#define MAXNAMLEN 1024/* Get the number to output for a reference to type TYPE.  */#define TYPE_OUTPUT_ADDRESS(TYPE) \  TYPE_SYMTAB_ADDRESS (TYPE_MAIN_VARIANT (TYPE))/* Stream for writing symbol table file.  */static FILE *symfile;/* Name of symbol table file.  */static char *symfile_name;/* Stream for writing to assembler file.  */static FILE *asmfile;/* Address for allocating space in symbol table file.   Changes in this variable are paired globally with writes to symfile,   but often we allocate many structures, advancing next_address,   before writing any of them.  */static int next_address;/* Chain recording all the types that have been output,   giving the address-in-the-symseg of each one.  */struct typevec_elt{  int address;  struct typevec_elt *next;};static struct typevec_elt *typevec;/* Number of types recorded so far in the chain.  */static int total_types;/* Lists of types to which forward references have been made.   Separate lists for temporary and permanent types.  */static tree temporary_fwd_refs;static tree permanent_fwd_refs;/* `blockvec' is a chain recording all the symbol-blocks that have been output,   giving the address-in-the-symseg of each one.  */struct blockvec_elt{  int address;  struct blockvec_elt *next;};static struct blockvec_elt *blockvec;/* Number of blocks recorded so far in the chain.  */static int total_blocks;static void symout_range_bounds ();static void symout_array_domain ();static void symout_record_fields ();static void symout_enum_values ();static void symout_record_field_names ();static void symout_enum_value_names ();static int subrange_p ();static void symout_strings_skip ();static void symout_strings_print ();/* At the beginning of compilation, start writing the symbol table.   Initialize the type and block chain.   Also open and initialize the symseg file.  */voidsymout_init (filename, asm_file, sourcename)     char *filename;     FILE *asm_file;     char *sourcename;{  struct symbol_root buffer;#ifdef VMS  fatal ("Cannot write GDB debugging format on VMS");#endif  asmfile = asm_file;  fprintf (asmfile, ".text 0\n.gdbbeg 0\n.gdbbeg 1\n");  fprintf (asmfile,	   "Ltext:\t.stabs \"%s\",%d,0,0,Ltext\n",	   sourcename, N_SO);  fprintf (asmfile, ".data 0\nLdata:\n");  ASM_OUTPUT_LOCAL (asmfile, "Lbss", 0, 0);  fprintf (asmfile, ".gdbsym Ldata,%d\n",	   (char *) &buffer.databeg - (char *) &buffer);  fprintf (asmfile, ".gdbsym Lbss,%d\n",	   (char *) &buffer.bssbeg - (char *) &buffer);  symfile = fopen (filename, "w");  if (symfile == 0)    pfatal_with_name (filename);  symfile_name = (char *) malloc (strlen (filename) + 1);  strcpy (symfile_name, filename);  typevec = 0;  blockvec = 0;  total_types = 0;  total_blocks = 0;  permanent_fwd_refs = 0;  temporary_fwd_refs = 0;  bzero (&buffer, sizeof buffer);  fwrite (&buffer, sizeof buffer, 1, symfile);  next_address = sizeof buffer;}/* Functions for outputting strings into the symbol table.   The string to be output is effectively the concatenation of   the two strings P1 and P2.  Their lengths are given as S1 and S2.   If P1 or P2 is zero, that string is not used.   A null character is output to terminate the string,   and it is followed by more nulls as padding to a word boundary.  */static voidsymout_strings (p1, s1, p2, s2)     char *p1;     int s1;     char *p2;     int s2;{  symout_strings_print (p1, s1, p2, s2);  symout_strings_skip (p1, s1, p2, s2);}/* Like symout_strings but only output; do not update next_address.  */static voidsymout_strings_print (p1, s1, p2, s2)     char *p1;     int s1;     char *p2;     int s2;{  register int total;  if (p1 && s1 == 0)    s1 = strlen (p1);  if (p2 && s2 == 0)    s2 = strlen (p2);  if (p1)    fwrite (p1, s1, 1, symfile);  if (p2)    fwrite (p2, s2, 1, symfile);  putc (0, symfile);  total = s1 + s2 + 1;  while (total % sizeof (int))    {      putc (0, symfile);      total++;    }}/* Like symout_strings but just update next_address; do not output.  */static voidsymout_strings_skip (p1, s1, p2, s2)     char *p1;     int s1;     char *p2;     int s2;{  register int total;  if (p1 && s1 == 0)    s1 = strlen (p1);  if (p2 && s2 == 0)    s2 = strlen (p2);  total = s1 + s2 + 1;  while (total % sizeof (int))    total++;  next_address += total;}/* Call here to output a chain of types.   After each function, this is done first for the chain of permanent types   made during the function, and then for the chain of temporary types.   This must be done before outputting the symbols and blocks of the function.   At the end of compilation, this is done for all the permanent types   made since the last function.   Each permanent type is done once, at the beginning of the next function,   or at the end of the compilation if no functions follow.   Once a type has been processed here, its TYPE_SYMTAB_ADDRESS remains   set up.  */voidsymout_types (types)     tree types;{  struct typerec  {    int number;    int address;    int nfields;    int fields_address;    int name_address;    char *name;    char *name_prefix;  };  register int n_types, i;  register struct typerec *records;  register tree next;  struct type buffer;  int this_run_address = next_address;  /* Count the number of types to be handled here.  */  for (next = types, n_types = 0;       next;       next = TREE_CHAIN (next), n_types++);  records = (struct typerec *) alloca (n_types * sizeof (struct typerec));  /* Compute the amount of space each type needs, updating next_address     and storing the address of the data for each type.  */  for (next = types, i = 0;       next;       next = TREE_CHAIN (next), i++)    {      register struct typevec_elt *velt	= (struct typevec_elt *) xmalloc (sizeof (struct typevec_elt));      velt->next = typevec;      typevec = velt;      total_types++;      if (TYPE_NAME (next))	{	  records[i].name_address = next_address;	  if (TREE_CODE (TYPE_NAME (next)) == IDENTIFIER_NODE)	    {	      records[i].name = IDENTIFIER_POINTER (TYPE_NAME (next));	      switch (TREE_CODE (next))		{		case RECORD_TYPE:		  records[i].name_prefix = "struct ";		  break;		case UNION_TYPE:		  records[i].name_prefix = "union ";		  break;		case ENUMERAL_TYPE:		  records[i].name_prefix = "enum ";		  break;		}	    }	  else	    {	      records[i].name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (next)));	      records[i].name_prefix = 0;	    }	  symout_strings_skip (records[i].name_prefix, 0,			       records[i].name, 0);	}      else	{	  records[i].name = 0;	  records[i].name_address = 0;	  records[i].name_prefix = 0;	}      /* If this type was forward-referenced from a previous call	 to symout_types, store this type's address into the reference.  */      if (TYPE_POINTER_TO (next) != 0	  && TYPE_SYMTAB_ADDRESS (TYPE_POINTER_TO (next)) != 0	  && TYPE_SYMTAB_ADDRESS (TYPE_POINTER_TO (next)) < this_run_address)	{	  int pos = ftell (symfile);	  int myaddr = next_address;	  fflush (symfile);	  fseek (symfile,		 (TYPE_SYMTAB_ADDRESS (TYPE_POINTER_TO (next))		  + offsetof (struct type, target_type)),		 0);	  fwrite (&myaddr, sizeof (int), 1, symfile);	  fflush (symfile);	  fseek (symfile, pos, 0);	}      records[i].address = next_address;      TYPE_SYMTAB_ADDRESS (next) = next_address;      velt->address = next_address;      next_address += sizeof (struct type);      records[i].nfields = 0;      records[i].fields_address = 0;      switch (TREE_CODE (next))	{	case ARRAY_TYPE:	  records[i].nfields	    = (TYPE_DOMAIN(next)	       ? ! integer_zerop (TYPE_MIN_VALUE (TYPE_DOMAIN (next)))	       : 0 );	  break;	case INTEGER_TYPE:	  if (subrange_p (next))	    buffer.nfields = 2;	  break;	case RECORD_TYPE:	case UNION_TYPE:	case ENUMERAL_TYPE:	  records[i].nfields = list_length (TYPE_FIELDS (next));	}      if (records[i].nfields)	records[i].fields_address = next_address;      next_address += records[i].nfields * sizeof (struct field);    }  /* Now write the data whose space we have assigned.     First fill the data into BUFFER, then write BUFFER.  */  for (next = types, i = 0;       next;       next = TREE_CHAIN (next), i++)    {      if (records[i].name)	symout_strings_print (records[i].name_prefix, 0,			      records[i].name, 0);      if (TREE_TYPE (next) != 0 && TYPE_OUTPUT_ADDRESS (TREE_TYPE (next)) == 0)	{	  /* We are making a forward-reference to our target type.	     Make a list of all of these.  */	  if (TREE_PERMANENT (next))	    permanent_fwd_refs	      = perm_tree_cons (TREE_TYPE (next), 0, permanent_fwd_refs);	  else	    temporary_fwd_refs	      = tree_cons (TREE_TYPE (next), 0, temporary_fwd_refs);	}      if (TYPE_SIZE (next) == 0)	buffer.length = 0;      else	buffer.length	  = (TREE_INT_CST_LOW (TYPE_SIZE (next))	     * TYPE_SIZE_UNIT (next) / BITS_PER_UNIT);      buffer.name = (char *) records[i].name_address;      buffer.target_type = (struct type *) (TREE_TYPE (next) ? TYPE_OUTPUT_ADDRESS (TREE_TYPE (next)) : 0);      buffer.pointer_type = 0;      buffer.function_type = 0;      buffer.flags	= ((TREE_CODE (next) == INTEGER_TYPE || TREE_CODE (next) == ENUMERAL_TYPE)	   && TREE_UNSIGNED (next))	  ? TYPE_FLAG_UNSIGNED : 0;      buffer.nfields = records[i].nfields;      buffer.fields = (struct field *) records[i].fields_address;      switch (TREE_CODE (next))	{	case INTEGER_TYPE:	  buffer.code = TYPE_CODE_INT;	  if (buffer.nfields)	    buffer.code = TYPE_CODE_RANGE;

⌨️ 快捷键说明

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