This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC objdump new feature to generate debug info using ctags style


Hi All!

I managed to modify prdbg.c to print the information in a format compatible with Exuberant Ctags (plus some fileds not available in E.Ctags). I just added some arguments to print_debugging_info and created a new debug_write_fns structure with pointers to the replacements needed to generate the data using this format.
The code seems to be working and I tested it for a medium weight project that generated more than 10 MB of tags (6 MB after sorting and discarding repeated entries).
My question is: should it be accepted?
I also patched objdump to use it with a new command line option.
The patch is 34 KB, mostly additions to prdbg.c.
I attached it to this mail but I think it should be passed by indent before applying it.


SET

--
Salvador Eduardo Tropea (SET). (Electronics Engineer)
Visit my home page: http://welcome.to/SetSoft or
http://www.geocities.com/SiliconValley/Vista/6552/
Alternative e-mail: set@computer.org set@ieee.org
Address: Curapaligue 2124, Caseros, 3 de Febrero
Buenos Aires, (1678), ARGENTINA Phone: +(5411) 4759 0013

Index: objdump.c
===================================================================
RCS file: /cvs/src/src/binutils/objdump.c,v
retrieving revision 1.66
diff -u -r1.66 objdump.c
--- objdump.c	1 May 2003 00:40:41 -0000	1.66
+++ objdump.c	2 May 2003 15:46:39 -0000
@@ -74,6 +74,7 @@
 static bfd_vma start_address = (bfd_vma) -1; /* --start-address */
 static bfd_vma stop_address = (bfd_vma) -1;  /* --stop-address */
 static int dump_debugging;		/* --debugging */
+static int dump_debugging_tags;		/* --debugging-tags */
 static bfd_vma adjust_section_vma = 0;	/* --adjust-vma */
 static int file_start_context = 0;      /* --file-start-context */
 
@@ -208,6 +209,7 @@
   -S, --source             Intermix source code with disassembly\n\
   -s, --full-contents      Display the full contents of all sections requested\n\
   -g, --debugging          Display debug information in object file\n\
+  -e, --debugging-tags     Display debug information using ctags style\n\
   -G, --stabs              Display (in raw form) any STABS info in the file\n\
   -t, --syms               Display the contents of the symbol table(s)\n\
   -T, --dynamic-syms       Display the contents of the dynamic symbol table\n\
@@ -266,6 +268,7 @@
   {"architecture", required_argument, NULL, 'm'},
   {"archive-headers", no_argument, NULL, 'a'},
   {"debugging", no_argument, NULL, 'g'},
+  {"debugging-tags", no_argument, NULL, 'e'},
   {"demangle", optional_argument, NULL, 'C'},
   {"disassemble", no_argument, NULL, 'd'},
   {"disassemble-all", no_argument, NULL, 'D'},
@@ -2068,7 +2071,8 @@
 	}
     }
 
-  printf (_("\n%s:     file format %s\n"), bfd_get_filename (abfd),
+  if (! dump_debugging_tags)
+    printf (_("\n%s:     file format %s\n"), bfd_get_filename (abfd),
 	  abfd->xvec->name);
   if (dump_ar_hdrs)
     print_arelt_descr (stdout, abfd, TRUE);
@@ -2076,7 +2080,8 @@
     dump_bfd_header (abfd);
   if (dump_private_headers)
     dump_bfd_private_header (abfd);
-  putchar ('\n');
+  if (! dump_debugging_tags)
+    putchar ('\n');
   if (dump_section_headers)
     dump_headers (abfd);
 
@@ -2106,7 +2111,8 @@
       dhandle = read_debugging_info (abfd, syms, symcount);
       if (dhandle != NULL)
 	{
-	  if (! print_debugging_info (stdout, dhandle))
+	  if (! print_debugging_info (stdout, dhandle, abfd, syms, demangle,
+	      dump_debugging_tags ? TRUE : FALSE))
 	    {
 	      non_fatal (_("%s: printing debugging information failed"),
 			 bfd_get_filename (abfd));
@@ -2648,7 +2654,7 @@
   bfd_init ();
   set_default_bfd_target ();
 
-  while ((c = getopt_long (argc, argv, "pib:m:M:VvCdDlfaHhrRtTxsSj:wE:zgG",
+  while ((c = getopt_long (argc, argv, "pib:m:M:VvCdDlfaHhrRtTxsSj:wE:zgeG",
 			   long_options, (int *) 0))
 	 != EOF)
     {
@@ -2779,6 +2785,12 @@
 	  break;
 	case 'g':
 	  dump_debugging = 1;
+	  seenflag = TRUE;
+	  break;
+	case 'e':
+	  dump_debugging = 1;
+	  dump_debugging_tags = 1;
+	  do_demangle = TRUE;
 	  seenflag = TRUE;
 	  break;
 	case 'G':
Index: budbg.h
===================================================================
RCS file: /cvs/src/src/binutils/budbg.h,v
retrieving revision 1.3
diff -u -r1.3 budbg.h
--- budbg.h	30 Nov 2002 08:39:41 -0000	1.3
+++ budbg.h	2 May 2003 15:46:39 -0000
@@ -32,8 +32,8 @@
 /* Routine used to print generic debugging information.  */
 
 extern bfd_boolean print_debugging_info
-  PARAMS ((FILE *, PTR));
-
+  PARAMS ((FILE *, PTR, bfd *, asymbol **, PTR, bfd_boolean));
+  
 /* Routines used to read and write stabs information.  */
 
 extern PTR start_stab
Index: prdbg.c
===================================================================
RCS file: /cvs/src/src/binutils/prdbg.c,v
retrieving revision 1.6
diff -u -r1.6 prdbg.c
--- prdbg.c	30 Nov 2002 08:39:41 -0000	1.6
+++ prdbg.c	2 May 2003 15:46:40 -0000
@@ -1,6 +1,7 @@
 /* prdbg.c -- Print out generic debugging information.
-   Copyright 1995, 1996, 2002 Free Software Foundation, Inc.
+   Copyright 1995, 1996, 2002, 2003 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@cygnus.com>.
+   Tags style generation written by Salvador E. Tropea <set@computer.org>
 
    This file is part of GNU Binutils.
 
@@ -43,6 +44,15 @@
   struct pr_stack *stack;
   /* Parameter number we are about to output.  */
   int parameter;
+  /* The following are used only by the tags code (tg_) */
+  /* Name of the file we are using */
+  char *filename;
+  /* The BFD */
+  bfd *abfd;
+  /* The symbols table for this BFD */
+  asymbol **syms;
+  /* Pointer to a function to demangle symbols */
+  char *(*demangler) PARAMS ((bfd *, const char *));
 };
 
 /* The type stack.  */
@@ -57,6 +67,13 @@
   enum debug_visibility visibility;
   /* Name of the current method we are handling.  */
   const char *method;
+  /* The following are used only by the tags code (tg_) */
+  /* Type for the container (struct, union, class, union class) */
+  const char *flavor;
+  /* A comma separated list of parent classes */
+  char *parents;
+  /* How many parents contains parents */
+  int num_parents;
 };
 
 static void indent
@@ -67,6 +84,8 @@
   PARAMS ((struct pr_handle *, const char *));
 static bfd_boolean append_type
   PARAMS ((struct pr_handle *, const char *));
+static bfd_boolean append_parent
+  PARAMS ((struct pr_handle *, const char *));
 static bfd_boolean substitute_type
   PARAMS ((struct pr_handle *, const char *));
 static bfd_boolean indent_type
@@ -77,6 +96,16 @@
   PARAMS ((bfd_vma, char *, bfd_boolean, bfd_boolean));
 static bfd_boolean pr_fix_visibility
   PARAMS ((struct pr_handle *, enum debug_visibility));
+/* Only used by tg_ code */
+static bfd_boolean tg_fix_visibility
+  PARAMS ((struct pr_handle *, enum debug_visibility));
+static void find_address_in_section
+  PARAMS ((bfd *abfd, asection *section, PTR data));
+static void translate_addresses
+  PARAMS ((bfd *abfd, char *addr_hex, FILE *f, asymbol **syms));
+static const char *visibility_name
+  PARAMS ((enum debug_visibility visibility));
+
 static bfd_boolean pr_start_compilation_unit
   PARAMS ((PTR, const char *));
 static bfd_boolean pr_start_source
@@ -169,6 +198,63 @@
 static bfd_boolean pr_lineno
   PARAMS ((PTR, const char *, unsigned long, bfd_vma));
 
+/* Tags style replacements */
+static bfd_boolean tg_start_compilation_unit
+  PARAMS ((PTR, const char *));
+static bfd_boolean tg_start_source
+  PARAMS ((PTR, const char *));
+static bfd_boolean tg_enum_type
+  PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
+static bfd_boolean tg_start_struct_type
+  PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int));
+static bfd_boolean pr_struct_field
+  PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
+static bfd_boolean tg_struct_field
+  PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
+static bfd_boolean tg_struct_field
+  PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
+static bfd_boolean tg_end_struct_type
+  PARAMS ((PTR));
+static bfd_boolean tg_start_class_type
+  PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int,
+	   bfd_boolean, bfd_boolean));
+static bfd_boolean tg_class_static_member
+  PARAMS ((PTR, const char *, const char *, enum debug_visibility));
+static bfd_boolean tg_class_baseclass
+  PARAMS ((PTR, bfd_vma, bfd_boolean, enum debug_visibility));
+static bfd_boolean tg_class_method_variant
+  PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean, bfd_boolean,
+	   bfd_vma, bfd_boolean));
+static bfd_boolean tg_class_static_method_variant
+  PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean,
+	   bfd_boolean));
+static bfd_boolean tg_end_class_type
+  PARAMS ((PTR));
+static bfd_boolean tg_tag_type
+  PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
+static bfd_boolean tg_typdef
+  PARAMS ((PTR, const char *));
+static bfd_boolean tg_tag
+  PARAMS ((PTR, const char *));
+static bfd_boolean tg_int_constant
+  PARAMS ((PTR, const char *, bfd_vma));
+static bfd_boolean tg_float_constant
+  PARAMS ((PTR, const char *, double));
+static bfd_boolean tg_typed_constant
+  PARAMS ((PTR, const char *, bfd_vma));
+static bfd_boolean tg_variable
+  PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
+static bfd_boolean tg_start_function
+  PARAMS ((PTR, const char *, bfd_boolean));
+static bfd_boolean tg_function_parameter
+  PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
+static bfd_boolean tg_start_block
+  PARAMS ((PTR, bfd_vma));
+static bfd_boolean tg_end_block
+  PARAMS ((PTR, bfd_vma));
+static bfd_boolean tg_lineno
+  PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+
 static const struct debug_write_fns pr_fns =
 {
   pr_start_compilation_unit,
@@ -217,12 +303,64 @@
   pr_lineno
 };
 
+static const struct debug_write_fns tg_fns =
+{
+  tg_start_compilation_unit,
+  tg_start_source,
+  pr_empty_type,                   /* Same, push_type */
+  pr_void_type,                    /* Same, push_type */
+  pr_int_type,                     /* Same, push_type */
+  pr_float_type,                   /* Same, push_type */
+  pr_complex_type,                 /* Same, push_type */
+  pr_bool_type,                    /* Same, push_type */
+  tg_enum_type,
+  pr_pointer_type,                 /* Same, changes to pointer */
+  pr_function_type,                /* Same, push_type */
+  pr_reference_type,               /* Same, changes to reference */
+  pr_range_type,                   /* FIXME: What's that? */
+  pr_array_type,                   /* Same, push_type */
+  pr_set_type,                     /* FIXME: What's that? */
+  pr_offset_type,                  /* FIXME: What's that? */
+  pr_method_type,                  /* Same */
+  pr_const_type,                   /* Same, changes to const */
+  pr_volatile_type,                /* Same, changes to volatile */
+  tg_start_struct_type,
+  tg_struct_field,
+  tg_end_struct_type,
+  tg_start_class_type,
+  tg_class_static_member,
+  tg_class_baseclass,
+  pr_class_start_method,           /* Same, remmembers that's a method */
+  tg_class_method_variant,
+  tg_class_static_method_variant,
+  pr_class_end_method,             /* Same, forgets that's a method */
+  tg_end_class_type,
+  pr_typedef_type,                 /* Same, just push type */
+  tg_tag_type,
+  tg_typdef,
+  tg_tag,
+  tg_int_constant,                 /* Untested */
+  tg_float_constant,               /* Untested */
+  tg_typed_constant,               /* Untested */
+  tg_variable,
+  tg_start_function,
+  tg_function_parameter,
+  tg_start_block,
+  tg_end_block,
+  pr_end_function,                 /* Same, does nothing */
+  tg_lineno
+};
+
 /* Print out the generic debugging information recorded in dhandle.  */
 
 bfd_boolean
-print_debugging_info (f, dhandle)
+print_debugging_info (f, dhandle, abfd, syms, demangler, as_tags)
      FILE *f;
      PTR dhandle;
+     bfd *abfd;
+     asymbol **syms;
+     PTR demangler;
+     bfd_boolean as_tags;
 {
   struct pr_handle info;
 
@@ -230,8 +368,22 @@
   info.indent = 0;
   info.stack = NULL;
   info.parameter = 0;
+  info.filename = NULL;
+  info.abfd = abfd;
+  info.syms = syms;
+  info.demangler = demangler;
+
+  if (as_tags)
+    {
+      fputs("!_TAG_FILE_FORMAT\t2\t/extended format/\n",f);
+      fputs("!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted/\n",f);
+      fputs("!_TAG_PROGRAM_AUTHOR\tIan Lance Taylor, Salvador E. Tropea and others\t//\n",f);
+      fputs("!_TAG_PROGRAM_NAME\tobjdump\t/From GNU binutils/\n",f);
+      /*!_TAG_PROGRAM_VERSION	5.2.2	//*/
+    }
 
-  return debug_write (dhandle, &pr_fns, (PTR) &info);
+  return as_tags ? debug_write (dhandle, &tg_fns, (PTR) &info)
+                 : debug_write (dhandle, &pr_fns, (PTR) &info);
 }
 
 /* Indent to the current indentation level.  */
@@ -311,6 +463,28 @@
   return TRUE;
 }
 
+/* Append a string to the parents on the top of the type stack.  */
+
+static bfd_boolean
+append_parent (info, s)
+     struct pr_handle *info;
+     const char *s;
+{
+  unsigned int len;
+
+  if (s == NULL)
+    return FALSE;
+
+  assert (info->stack != NULL);
+
+  len = info->stack->parents ? strlen (info->stack->parents) : 0;
+  info->stack->parents = (char *) xrealloc (info->stack->parents,
+					 len + strlen (s) + 1);
+  strcpy (info->stack->parents + len, s);
+
+  return TRUE;
+}
+
 /* We use an underscore to indicate where the name should go in a type
    string.  This function substitutes a string for the underscore.  If
    there is no underscore, the name follows the type.  */
@@ -1894,3 +2068,1006 @@
 {
   return TRUE;
 }
+
+/*****************************************************************************
+
+  Tags style generation functions from here
+  
+*****************************************************************************/
+
+/* Variables for address to line translation */
+static bfd_vma pc;
+static const char *filename;
+static const char *functionname;
+static unsigned int line;
+static bfd_boolean found;
+
+/* Look for an address in a section.  This is called via
+   bfd_map_over_sections.  */
+
+static void
+find_address_in_section (abfd, section, data)
+     bfd *abfd;
+     asection *section;
+     PTR data;
+{
+  bfd_vma vma;
+  bfd_size_type size;
+  asymbol **syms = (asymbol **)data;
+
+  if (found)
+    return;
+
+  if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
+    return;
+
+  vma = bfd_get_section_vma (abfd, section);
+  if (pc < vma)
+    return;
+
+  size = bfd_get_section_size_before_reloc (section);
+  if (pc >= vma + size)
+    return;
+
+  found = bfd_find_nearest_line (abfd, section, syms, pc - vma,
+				 &filename, &functionname, &line);
+}
+
+static void
+translate_addresses (abfd, addr_hex, f, syms)
+     bfd *abfd;
+     char *addr_hex;
+     FILE *f;
+     asymbol **syms;
+{
+  pc = bfd_scan_vma (addr_hex, NULL, 16);
+  found = FALSE;
+  bfd_map_over_sections (abfd, find_address_in_section, syms);
+
+  if (! found)
+       fprintf (f, "??");
+  else
+       //fprintf (f, "%u (%s)", line, addr_hex);
+       fprintf (f, "%u", line);
+}
+
+/* Start a new compilation unit.  */
+
+static bfd_boolean
+tg_start_compilation_unit (p, filename)
+     PTR p;
+     const char *filename ATTRIBUTE_UNUSED;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  fprintf(stderr, "New compilation unit: %s\n", filename);
+
+  free (info->filename);
+  /* Should it be relative? best way to do it here? */
+  info->filename = strdup(filename);
+
+  return TRUE;
+}
+
+/* Start a source file within a compilation unit.  */
+
+static bfd_boolean
+tg_start_source (p, filename)
+     PTR p;
+     const char *filename;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  free (info->filename);
+  /* Should it be relative? best way to do it here? */
+  info->filename = strdup(filename);
+
+  return TRUE;
+}
+
+/* Push an enum type onto the type stack.  */
+
+static bfd_boolean
+tg_enum_type (p, tag, names, values)
+     PTR p;
+     const char *tag;
+     const char **names;
+     bfd_signed_vma *values;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  unsigned int i;
+  const char *name;
+  char ab[20];
+
+  if (! pr_enum_type (p, tag, names, values))
+    return FALSE;
+    
+  name = tag ? tag : "unknown";
+  /* Generate an entry for the enum */
+  if (tag)
+    {
+       fprintf(info->f, "%s\t%s\t0;\"\tkind:e\ttype:%s\n", tag,
+               info->filename, info->stack->type);
+    }
+  /* Generate entries for the values */
+  if (names != NULL)
+    {
+      for (i = 0; names[i] != NULL; i++)
+	{
+          print_vma (values[i], ab, FALSE, FALSE);
+          fprintf (info->f, "%s\t%s\t0;\"\tkind:g\tenum:%s\tvalue:%s\n",
+                   names[i], info->filename, name, ab);
+	}
+    }
+
+  return TRUE;
+}
+
+/* Start accumulating a struct type.  */
+
+static bfd_boolean
+tg_start_struct_type (p, tag, id, structp, size)
+     PTR p;
+     const char *tag;
+     unsigned int id;
+     bfd_boolean structp;
+     unsigned int size ATTRIBUTE_UNUSED;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  const char *name;
+  char idbuf[20];
+  
+  if (tag != NULL)
+    {
+      name = tag;
+    }
+  else
+    {
+      name = idbuf;
+      sprintf (idbuf, "%%anon%u", id);
+    }
+  if (! push_type (info, name))
+    return FALSE;
+  info->stack->flavor = structp ? "struct" : "union";
+
+  fprintf (info->f, "%s\t%s\t0;\"\tkind:%c\n", name, info->filename,
+           info->stack->flavor[0]);
+
+  info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
+
+  return indent_type (info);
+}
+
+/* Output the visibility of a field in a struct.  */
+
+static bfd_boolean
+tg_fix_visibility (info, visibility)
+     struct pr_handle *info;
+     enum debug_visibility visibility;
+{
+  assert (info->stack != NULL);
+
+  if (info->stack->visibility == visibility)
+    return TRUE;
+
+  assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE);
+
+  info->stack->visibility = visibility;
+
+  return TRUE;
+}
+
+/* Add a field to a struct type.  */
+
+static bfd_boolean
+tg_struct_field (p, name, bitpos, bitsize, visibility)
+     PTR p;
+     const char *name;
+     bfd_vma bitpos ATTRIBUTE_UNUSED;
+     bfd_vma bitsize ATTRIBUTE_UNUSED;
+     enum debug_visibility visibility;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return FALSE;
+
+  if (! tg_fix_visibility (info, visibility))
+    return FALSE;
+
+  /* It happends, a bug? */
+  if (! name[0])
+    return TRUE;
+    
+  fprintf (info->f, "%s\t%s\t0;\"\tkind:m\ttype:%s\t%s:%s\taccess:%s\n",
+           name, info->filename, t, info->stack->flavor, info->stack->type,
+           visibility_name (visibility));
+
+  return TRUE;
+}
+
+/* Finish a struct type.  */
+
+static bfd_boolean
+tg_end_struct_type (p)
+     PTR p ATTRIBUTE_UNUSED;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  assert (info->stack != NULL);
+
+  return TRUE;
+}
+
+/* Start a class type.  */
+
+static bfd_boolean
+tg_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
+     PTR p;
+     const char *tag;
+     unsigned int id;
+     bfd_boolean structp;
+     unsigned int size;
+     bfd_boolean vptr;
+     bfd_boolean ownvptr;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *tv = NULL;
+  const char *name;
+
+  info->indent += 2;
+
+  if (vptr && ! ownvptr)
+    {
+      tv = pop_type (info);
+      if (tv == NULL)
+	return FALSE;
+    }
+
+  if (tag != NULL)
+    {
+       name=tag;
+    }
+  else
+    {
+      char idbuf[20];
+
+      sprintf (idbuf, "%%anon%u", id);
+      name = idbuf;
+    }
+  if (! push_type (info, name))
+    return FALSE;
+  info->stack->flavor = structp ? "class" : "union class";
+  info->stack->parents = NULL;
+  info->stack->num_parents = 0;
+
+  if (size != 0 || vptr || ownvptr || tag != NULL)
+    {
+      if (vptr)
+	{
+	  if (! append_type (info, " vtable "))
+	    return FALSE;
+	  if (ownvptr)
+	    {
+	      if (! append_type (info, "self "))
+		return FALSE;
+	    }
+	  else
+	    {
+	      if (! append_type (info, tv)
+		  || ! append_type (info, " "))
+		return FALSE;
+	    }
+	}
+    }
+
+  info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
+  
+  return TRUE;
+}
+
+/* Add a static member to a class.  */
+
+static bfd_boolean
+tg_class_static_member (p, name, physname, visibility)
+     PTR p;
+     const char *name;
+     const char *physname ATTRIBUTE_UNUSED;
+     enum debug_visibility visibility;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+  int len_var, len_class;
+  char *full_name;
+
+  len_var = strlen (name);
+  len_class = strlen (info->stack->next->type);
+  full_name = (char *) xmalloc (len_var + len_class + 3);
+  if (! full_name)
+    return FALSE;
+  memcpy (full_name, info->stack->next->type, len_class);
+  memcpy (full_name + len_class, "::", 2);
+  memcpy (full_name + len_class + 2, name, len_var + 1);
+
+  if (! substitute_type (info, full_name))
+    return FALSE;
+
+  if (! prepend_type (info, "static "))
+    return FALSE;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return FALSE;
+
+  if (! tg_fix_visibility (info, visibility))
+    return FALSE;
+
+  fprintf (info->f, "%s\t%s\t0;\"\tkind:x\ttype:%s\tclass:%s\taccess:%s\n",
+           name, info->filename, t, info->stack->type,
+           visibility_name (visibility));
+  free (t);
+  free (full_name);
+
+  return TRUE;
+}
+
+/* Add a base class to a class.  */
+
+static bfd_boolean
+tg_class_baseclass (p, bitpos, virtual, visibility)
+     PTR p;
+     bfd_vma bitpos ATTRIBUTE_UNUSED;
+     bfd_boolean virtual;
+     enum debug_visibility visibility;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+  const char *prefix;
+
+  assert (info->stack != NULL && info->stack->next != NULL);
+
+  t = pop_type (info);
+  if (t == NULL)
+    return FALSE;
+
+  if (strncmp (t, "class ", sizeof "class " - 1) == 0)
+    t += sizeof "class " - 1;
+
+  /* Push it back on to take advantage of the prepend_type and
+     append_type routines.  */
+  if (! push_type (info, t))
+    return FALSE;
+
+  if (virtual)
+    {
+      if (! prepend_type (info, "virtual "))
+	return FALSE;
+    }
+
+  switch (visibility)
+    {
+    case DEBUG_VISIBILITY_PUBLIC:
+      prefix = "public ";
+      break;
+    case DEBUG_VISIBILITY_PROTECTED:
+      prefix = "protected ";
+      break;
+    case DEBUG_VISIBILITY_PRIVATE:
+      prefix = "private ";
+      break;
+    default:
+      prefix = "/* unknown visibility */ ";
+      break;
+    }
+
+  if (! prepend_type (info, prefix))
+    return FALSE;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return FALSE;
+
+  if (info->stack->num_parents && ! append_parent (info, ", "))
+    return FALSE;
+    
+  if (! append_parent (info, t))
+    return FALSE;
+  info->stack->num_parents++;
+    
+  free (t);
+
+  return TRUE;
+}
+
+/* Add a variant to a method.  */
+
+static bfd_boolean
+tg_class_method_variant (p, physname, visibility, constp, volatilep, voffset,
+			 context)
+     PTR p;
+     const char *physname ATTRIBUTE_UNUSED;
+     enum debug_visibility visibility;
+     bfd_boolean constp;
+     bfd_boolean volatilep;
+     bfd_vma voffset ATTRIBUTE_UNUSED;
+     bfd_boolean context;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *method_type;
+  char *context_type;
+  char *method_name;
+
+  assert (info->stack != NULL);
+  assert (info->stack->next != NULL);
+
+  /* Put the const and volatile qualifiers on the type.  */
+  if (volatilep)
+    {
+      if (! append_type (info, " volatile"))
+	return FALSE;
+    }
+  if (constp)
+    {
+      if (! append_type (info, " const"))
+	return FALSE;
+    }
+
+  method_name = strdup(context ? info->stack->next->next->method
+		        : info->stack->next->method);
+  
+  /* Stick the name of the method into its type.  */
+  if (! substitute_type (info, method_name))
+    return FALSE;
+
+  /* Get the type.  */
+  method_type = pop_type (info);
+  if (method_type == NULL)
+    return FALSE;
+
+  /* Pull off the context type if there is one.  */
+  if (! context)
+    context_type = NULL;
+  else
+    {
+      context_type = pop_type (info);
+      if (context_type == NULL)
+	return FALSE;
+    }
+
+  /* Now the top of the stack is the class.  */
+
+  if (! tg_fix_visibility (info, visibility))
+    return FALSE;
+
+  fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\n",
+           method_name, info->filename, method_type, info->stack->type);
+  free(method_type);
+  free(method_name);
+  free(context_type);
+  
+  return TRUE;
+}
+
+/* Add a static variant to a method.  */
+
+static bfd_boolean
+tg_class_static_method_variant (p, physname, visibility, constp, volatilep)
+     PTR p;
+     const char *physname ATTRIBUTE_UNUSED;
+     enum debug_visibility visibility;
+     bfd_boolean constp;
+     bfd_boolean volatilep;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *method_type;
+  char *method_name;
+
+  assert (info->stack != NULL);
+  assert (info->stack->next != NULL);
+  assert (info->stack->next->method != NULL);
+
+  /* Put the const and volatile qualifiers on the type.  */
+  if (volatilep)
+    {
+      if (! append_type (info, " volatile"))
+	return FALSE;
+    }
+  if (constp)
+    {
+      if (! append_type (info, " const"))
+	return FALSE;
+    }
+
+  /* Mark it as static.  */
+  if (! prepend_type (info, "static "))
+    return FALSE;
+
+  method_name = strdup(info->stack->next->method);
+  /* Stick the name of the method into its type.  */
+  if (! substitute_type (info, info->stack->next->method))
+    return FALSE;
+
+  /* Get the type.  */
+  method_type = pop_type (info);
+  if (method_type == NULL)
+    return FALSE;
+
+  /* Now the top of the stack is the class.  */
+
+  if (! tg_fix_visibility (info, visibility))
+    return FALSE;
+
+  fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\taccess:%s\n",
+           method_name, info->filename, method_type, info->stack->type,
+           visibility_name (visibility));
+  free(method_type);
+  free(method_name);
+  
+  return TRUE;
+}
+
+/* Finish up a class.  */
+
+static bfd_boolean
+tg_end_class_type (p)
+     PTR p;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  fprintf (info->f, "%s\t%s\t0;\"\tkind:c\ttype:%s", info->stack->type, info->filename,
+           info->stack->flavor);
+  if (info->stack->num_parents)
+    {
+       fprintf  (info->f, "\tinherits:%s", info->stack->parents);
+       free (info->stack->parents);
+    }
+  fputc ('\n', info->f);
+           
+  return tg_end_struct_type (p);
+}
+
+/* Push a type on the stack using a tag name.  */
+
+static bfd_boolean
+tg_tag_type (p, name, id, kind)
+     PTR p;
+     const char *name;
+     unsigned int id;
+     enum debug_type_kind kind;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  const char *t, *tag;
+  char idbuf[20];
+
+  switch (kind)
+    {
+    case DEBUG_KIND_STRUCT:
+      t = "struct ";
+      break;
+    case DEBUG_KIND_UNION:
+      t = "union ";
+      break;
+    case DEBUG_KIND_ENUM:
+      t = "enum ";
+      break;
+    case DEBUG_KIND_CLASS:
+      t = "class ";
+      break;
+    case DEBUG_KIND_UNION_CLASS:
+      t = "union class ";
+      break;
+    default:
+      abort ();
+      return FALSE;
+    }
+
+  if (! push_type (info, t))
+    return FALSE;
+  if (name != NULL)
+    tag = name;
+  else
+    {
+      sprintf (idbuf, "%%anon%u", id);
+      tag = idbuf;
+    }
+
+  if (! append_type (info, tag))
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Output a typedef.  */
+
+static bfd_boolean
+tg_typdef (p, name)
+     PTR p;
+     const char *name;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *s;
+
+  s = pop_type (info);
+  if (s == NULL)
+    return FALSE;
+
+  fprintf (info->f, "%s\t%s\t0;\"\tkind:t\ttype:%s\n", name,
+           info->filename, s);
+
+  free (s);
+
+  return TRUE;
+}
+
+/* Output a tag.  The tag should already be in the string on the
+   stack, so all we have to do here is print it out.  */
+
+static bfd_boolean
+tg_tag (p, name)
+     PTR p ATTRIBUTE_UNUSED;
+     const char *name ATTRIBUTE_UNUSED;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return FALSE;
+  free (t);
+
+  return TRUE;
+}
+
+/* Output an integer constant.  */
+
+static bfd_boolean
+tg_int_constant (p, name, val)
+     PTR p;
+     const char *name;
+     bfd_vma val;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char ab[20];
+
+  indent (info);
+  print_vma (val, ab, FALSE, FALSE);
+  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const int\tvalue:%s\n",
+           name, info->filename, ab);
+  return TRUE;
+}
+
+/* Output a floating point constant.  */
+
+static bfd_boolean
+tg_float_constant (p, name, val)
+     PTR p;
+     const char *name;
+     double val;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  indent (info);
+  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const double\tvalue:%g\n",
+           name, info->filename, val);
+  return TRUE;
+}
+
+/* Output a typed constant.  */
+
+static bfd_boolean
+tg_typed_constant (p, name, val)
+     PTR p;
+     const char *name;
+     bfd_vma val;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+  char ab[20];
+
+  t = pop_type (info);
+  if (t == NULL)
+    return FALSE;
+
+  indent (info);
+  print_vma (val, ab, FALSE, FALSE);
+  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const %s\tvalue:%s\n",
+           name, info->filename, t, ab);
+
+  free (t);
+
+  return TRUE;
+}
+
+/* Output a variable.  */
+
+static bfd_boolean
+tg_variable (p, name, kind, val)
+     PTR p;
+     const char *name;
+     enum debug_var_kind kind;
+     bfd_vma val ATTRIBUTE_UNUSED;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+  const char *dname, *from_class;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return FALSE;
+
+  dname = name;
+  if (info->demangler)
+    {
+       dname = info->demangler (info->abfd, name);
+       if (strcmp (name, dname) == 0)
+         {
+            free ((char *)dname);
+            dname = name;
+         }
+    }
+    
+  if (dname != name)
+    {
+       char *sep;
+       sep = strstr (dname, "::");
+       if (sep)
+         {
+          *sep = 0;
+          name = sep + 2;
+          from_class = dname;
+         }
+       else
+         {
+          /* Obscure types as vts and type_info nodes */
+          /*fprintf(stderr,"%s => %s\n",name,dname);*/
+          name = dname;
+          from_class = NULL;
+         }
+    }
+  else
+    from_class = NULL;
+    
+  fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:%s",
+           name, info->filename, t);
+           
+  switch (kind)
+    {
+    case DEBUG_STATIC:
+    case DEBUG_LOCAL_STATIC:
+      fprintf (info->f, "\tfile:");
+      break;
+    case DEBUG_REGISTER:
+      fprintf (info->f, "\tregister:");
+      break;
+    default:
+      break;
+    }
+
+  if (from_class)
+    {
+       fprintf (info->f, "\tclass:%s",from_class);
+       free ((char *)dname);
+    }
+    
+  fprintf (info->f, "\n");
+  
+  free (t);
+
+  return TRUE;
+}
+
+/* Start outputting a function.  */
+
+static bfd_boolean
+tg_start_function (p, name, global)
+     PTR p;
+     const char *name;
+     bfd_boolean global;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  const char *dname;
+
+  if (! global)
+    info->stack->flavor = "static";
+  else
+    info->stack->flavor = NULL;
+
+  dname = name;
+  if (info->demangler)
+    {
+       dname = info->demangler (info->abfd, name);
+       if (strcmp (name, dname) == 0)
+         {
+            free ((char *)dname);
+            dname = name;
+         }
+    }
+
+  if (! substitute_type (info, dname))
+    return FALSE;
+    
+  if (dname != name)
+    {
+       char *sep;
+       sep = strstr (dname, "::");
+       if (sep)
+         {
+            info->stack->method = dname;
+            *sep = 0;
+            name = sep + 2;
+         }
+       else
+         {
+            info->stack->method = "";
+            name = dname;
+         }
+       sep = strchr (name, '(');
+       if (sep)
+         *sep = 0;
+       /* Obscure functions as type_info function */
+       /*
+       else
+         fprintf(stderr,"%s => %s\n",name,dname);*/
+    }
+  else
+    info->stack->method = NULL;
+
+  info->stack->parents = strdup (name);
+  //fprintf (info->f, "%s\t%s\t", name, info->filename);
+  
+  if (! info->stack->method && ! append_type (info, "("))
+     return FALSE;
+
+  info->parameter = 1;
+
+  return TRUE;
+}
+
+/* Output a function parameter.  */
+
+static bfd_boolean
+tg_function_parameter (p, name, kind, val)
+     PTR p;
+     const char *name;
+     enum debug_parm_kind kind;
+     bfd_vma val ATTRIBUTE_UNUSED;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+
+  if (kind == DEBUG_PARM_REFERENCE
+      || kind == DEBUG_PARM_REF_REG)
+    {
+      if (! pr_reference_type (p))
+	return FALSE;
+    }
+
+  if (! substitute_type (info, name))
+    return FALSE;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return FALSE;
+
+  if (! info->stack->method)
+    {
+       if (info->parameter != 1 && ! append_type (info, ", "))
+         return FALSE;
+     
+       if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
+         if (! append_type (info, "register "))
+           return FALSE;
+           
+       if (! append_type (info, t))
+         return FALSE;
+    }
+
+  free (t);
+
+  ++info->parameter;
+
+  return TRUE;
+}
+
+/* Start writing out a block.  */
+
+static bfd_boolean
+tg_start_block (p, addr)
+     PTR p;
+     bfd_vma addr;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char ab[20], kind, *partof;
+  char *t;
+  bfd_boolean local;
+
+  if (info->parameter > 0)
+    {
+      info->parameter = 0;
+
+      /* Delayed name */
+      fprintf (info->f, "%s\t%s\t", info->stack->parents, info->filename);
+      free (info->stack->parents);
+      
+      print_vma (addr, ab, TRUE, TRUE);
+      translate_addresses (info->abfd, ab, info->f, info->syms);
+      local = info->stack->flavor != NULL;
+      if (info->stack->method && *info->stack->method)
+        {
+           kind = 'm';
+           partof = (char *)info->stack->method;
+        }
+      else
+        {
+           kind='f';
+           partof = NULL;
+           if (! info->stack->method && ! append_type (info, ")"))
+              return FALSE;
+        }
+      t = pop_type (info);
+      if (t == NULL)
+        return FALSE;
+      fprintf(info->f, ";\"\tkind:%c\ttype:%s", kind, t);
+      if (local)
+        fputs ("\tfile:", info->f);
+      if (partof)
+        {
+           fprintf (info->f, "\tclass:%s", partof);
+           free (partof);
+        }
+      fputc ('\n', info->f);
+    }
+
+  return TRUE;
+}
+
+/* Write out line number information.  */
+
+static bfd_boolean
+tg_lineno (p, filename, lineno, addr)
+     PTR p ATTRIBUTE_UNUSED;
+     const char *filename ATTRIBUTE_UNUSED;
+     unsigned long lineno ATTRIBUTE_UNUSED;
+     bfd_vma addr ATTRIBUTE_UNUSED;
+{
+  return TRUE;
+}
+
+/* Finish writing out a block.  */
+
+static bfd_boolean
+tg_end_block (p, addr)
+     PTR p ATTRIBUTE_UNUSED;
+     bfd_vma addr ATTRIBUTE_UNUSED;
+{
+  return TRUE;
+}
+
+static
+const char *visibility_name (visibility)
+     enum debug_visibility visibility;
+{
+  const char *s;
+  
+  switch (visibility)
+    {
+    case DEBUG_VISIBILITY_PUBLIC:
+      s = "public";
+      break;
+    case DEBUG_VISIBILITY_PRIVATE:
+      s = "private";
+      break;
+    case DEBUG_VISIBILITY_PROTECTED:
+      s = "protected";
+      break;
+    case DEBUG_VISIBILITY_IGNORE:
+      s = "/* ignore */";
+      break;
+    default:
+      abort ();
+      return FALSE;
+    }
+  return s;
+}
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]