[PATCH] Use directory table to squeeze some bytes from .debug_line section

Jakub Jelinek jakub@redhat.com
Thu Jan 23 20:23:00 GMT 2003


Hi!

I have noticed that when gas creates .debug_line section (and not gcc)
the directory table is never used and all filenames in the file table
include both directory names and basenames.  The following patch fixes
this.  Ok to commit?

2003-01-23  Jakub Jelinek  <jakub@redhat.com>

	* dwarf2dbg.c: Include filenames.h.
	(struct file_entry): Make filename const char *.
	(dirs, dirs_in_use, dirs_allocated): New variables.
	(get_filenum): Add NUM argument.  Build directory table.
	(dwarf2_where): Adjust caller.
	(dwarf2_directive_file): Use get_filenum to allocate
	slot in file and directory tables.
	(dwarf2_directive_loc): Recreate full filename from
	directory and filename part if needed for listing.
	(out_file_list): Output directory table.
	Output main source file dirname before its filename.

--- gas/dwarf2dbg.c.jj	2002-12-28 23:19:13.000000000 +0100
+++ gas/dwarf2dbg.c	2003-01-23 17:07:44.000000000 +0100
@@ -1,5 +1,5 @@
 /* dwarf2dbg.c - DWARF2 debug support
-   Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
    This file is part of GAS, the GNU Assembler.
@@ -42,6 +42,7 @@
 #endif
 
 #include "dwarf2dbg.h"
+#include <filenames.h>
 
 #ifndef DWARF2_FORMAT
 # define DWARF2_FORMAT() dwarf2_format_32bit
@@ -132,7 +133,7 @@ struct line_seg {
 static struct line_seg *all_segs;
 
 struct file_entry {
-  char *filename;
+  const char *filename;
   unsigned int dir;
 };
 
@@ -141,6 +142,11 @@ static struct file_entry *files;
 static unsigned int files_in_use;
 static unsigned int files_allocated;
 
+/* Table of directories used by .debug_line.  */
+static char **dirs;
+static unsigned int dirs_in_use;
+static unsigned int dirs_allocated;
+
 /* TRUE when we've seen a .loc directive recently.  Used to avoid
    doing work when there's nothing to do.  */
 static bfd_boolean loc_directive_seen;
@@ -155,7 +161,7 @@ static char const fake_label_name[] = ".
 static unsigned int sizeof_address;
 
 static struct line_subseg *get_line_subseg PARAMS ((segT, subsegT));
-static unsigned int get_filenum PARAMS ((const char *));
+static unsigned int get_filenum PARAMS ((const char *, unsigned int));
 static struct frag *first_frag_for_seg PARAMS ((segT));
 static struct frag *last_frag_for_seg PARAMS ((segT));
 static void out_byte PARAMS ((int));
@@ -277,7 +283,7 @@ dwarf2_where (line)
     {
       char *filename;
       as_where (&filename, &line->line);
-      line->filenum = get_filenum (filename);
+      line->filenum = get_filenum (filename, 0);
       line->column = 0;
       line->flags = DWARF2_FLAG_BEGIN_STMT;
     }
@@ -318,22 +324,83 @@ dwarf2_emit_insn (size)
   dwarf2_gen_line_info (frag_now_fix () - size, &loc);
 }
 
-/* Get a .debug_line file number for FILENAME.  */
+/* Get a .debug_line file number for FILENAME.  If NUM is nonzero,
+   allocate it on that file table slot, otherwise return the first
+   empty one.  */
 
 static unsigned int
-get_filenum (filename)
+get_filenum (filename, num)
      const char *filename;
+     unsigned int num;
 {
-  static unsigned int last_used;
-  unsigned int i;
+  static unsigned int last_used, last_used_dir_len;
+  const char *file;
+  size_t dir_len;
+  unsigned int i, dir;
+
+  if (num == 0 && last_used)
+    {
+      if (! files[last_used].dir
+	  && strcmp (filename, files[last_used].filename) == 0)
+	return last_used;
+      if (files[last_used].dir
+	  && strncmp (filename, dirs[files[last_used].dir],
+		      last_used_dir_len) == 0
+	  && IS_DIR_SEPARATOR (filename [last_used_dir_len])
+	  && strcmp (filename + last_used_dir_len + 1,
+		     files[last_used].filename) == 0)
+	return last_used;
+    }
+
+  file = lbasename (filename);
+  /* Don't make empty string from / or A: from A:/ .  */
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+  if (file <= filename + 3)
+    file = filename;
+#else
+  if (file == filename + 1)
+    file = filename;
+#endif
+  dir_len = file - filename;
 
-  if (last_used)
-    if (strcmp (filename, files[last_used].filename) == 0)
-      return last_used;
+  dir = 0;
+  if (dir_len)
+    {
+      --dir_len;
+      for (dir = 1; dir < dirs_in_use; ++dir)
+	if (memcmp (filename, dirs[dir], dir_len) == 0
+	    && dirs[dir][dir_len] == '\0')
+	  break;
 
-  for (i = 1; i < files_in_use; ++i)
-    if (strcmp (filename, files[i].filename) == 0)
-      return i;
+      if (dir >= dirs_in_use)
+	{
+	  if (dir >= dirs_allocated)
+	    {
+	      dirs_allocated = dir + 32;
+	      dirs = (char **)
+		     xrealloc (dirs, (dir + 32) * sizeof (const char *));
+	    }
+
+	  dirs[dir] = xmalloc (dir_len + 1);
+	  memcpy (dirs[dir], filename, dir_len);
+	  dirs[dir][dir_len] = '\0';
+	  dirs_in_use = dir + 1;
+	}
+    }
+
+  if (num == 0)
+    {
+      for (i = 1; i < files_in_use; ++i)
+	if (files[i].dir == dir
+	    && strcmp (file, files[i].filename) == 0)
+	  {
+	    last_used = i;
+	    last_used_dir_len = dir_len;
+	    return i;
+	  }
+    }
+  else
+    i = num;
 
   if (i >= files_allocated)
     {
@@ -346,10 +413,11 @@ get_filenum (filename)
       memset (files + old, 0, (i + 32 - old) * sizeof (struct file_entry));
     }
 
-  files[i].filename = xstrdup (filename);
-  files[i].dir = 0;
+  files[i].filename = num ? file : xstrdup (file);
+  files[i].dir = dir;
   files_in_use = i + 1;
   last_used = i;
+  last_used_dir_len = dir_len;
 
   return i;
 }
@@ -392,21 +460,7 @@ dwarf2_directive_file (dummy)
       return NULL;
     }
 
-  if (num >= (int) files_allocated)
-    {
-      unsigned int old = files_allocated;
-
-      files_allocated = num + 16;
-      files = (struct file_entry *)
-	xrealloc (files, (num + 16) * sizeof (struct file_entry));
-
-      /* Zero the new memory.  */
-      memset (files + old, 0, (num + 16 - old) * sizeof (struct file_entry));
-    }
-
-  files[num].filename = filename;
-  files[num].dir = 0;
-  files_in_use = num + 1;
+  get_filenum (filename, num);
 
   return filename;
 }
@@ -445,7 +499,20 @@ dwarf2_directive_loc (dummy)
 #ifndef NO_LISTING
   if (listing)
     {
-      listing_source_file (files[filenum].filename);
+      if (files[filenum].dir)
+	{
+	  size_t dir_len = strlen (dirs[files[filenum].dir]);
+	  size_t file_len = strlen (files[filenum].filename);
+	  char *cp = (char *) alloca (dir_len + 1 + file_len + 1);
+
+	  memcpy (cp, dirs[files[filenum].dir], dir_len);
+	  cp[dir_len] = '/';
+	  memcpy (cp + dir_len + 1, files[filenum].filename, file_len);
+	  cp[dir_len + file_len + 1] = '\0';
+	  listing_source_file (cp);
+	}
+      else
+	listing_source_file (files[filenum].filename);
       listing_source_line (line);
     }
 #endif
@@ -988,7 +1055,14 @@ out_file_list ()
   char *cp;
   unsigned int i;
 
-  /* Terminate directory list.  */
+  /* Emit directory list.  */
+  for (i = 1; i < dirs_in_use; ++i)
+    {
+      size = strlen (dirs[i]) + 1;
+      cp = frag_more (size);
+      memcpy (cp, dirs[i], size);
+    }
+  /* Terminate it.  */
   out_byte ('\0');
 
   for (i = 1; i < files_in_use; ++i)
@@ -1305,6 +1379,13 @@ out_debug_info (info_seg, abbrev_seg, li
      entry was emitted, so this should always be defined.  */
   if (!files || files_in_use < 1)
     abort ();
+  if (files[1].dir)
+    {
+      len = strlen (dirs[files[1].dir]);
+      p = frag_more (len + 1);
+      memcpy (p, dirs[files[1].dir], len);
+      p[len] = '/';
+    }
   len = strlen (files[1].filename) + 1;
   p = frag_more (len);
   memcpy (p, files[1].filename, len);

	Jakub



More information about the Binutils mailing list