[patch ld]: Do some memory cleanup for def-file parsing

Kai Tietz ktietz70@googlemail.com
Sat Apr 16 16:05:00 GMT 2011


Hello,

This patch does some memory optiomiations for def-file parsing. As
this scanner is also used for directives, it can likely happen for big
projects that here a lot of memory gets wasted, which additional
leaked as nobody is releasing it again.
This patch tries to minimize the amount of memory used here.

ChangeLog ld/

2011-04-16  Kai Tietz

	* deffilep.y (def_pool_str): New type.
	(pool_strs): Local static.
	(def_pool_alloc): Local function.
	(def_pool_strdup): Likewise.
	(def_pool_free): Likewise.
	(opt_name): Replace xmalloc/xstrdup by
	def_pool_alloc/def_pool_strdup.
	(dot_name): Likewise.
	(anylang_id): Likewise.
	(def_lex): Likewise.
	(def_file_parse): Call def_pool_free on
	exit and cleanup directives elements.
	(def_file_add_directive): Call def_pool_free.

Tested for x86_64-w64-mingw32, i686-w64-mingw32, and i686-pc-cygwin.
Ok for apply?

Regards,
Kai
-------------- next part --------------
Index: src/ld/deffilep.y
===================================================================
--- src.orig/ld/deffilep.y	2011-04-13 14:52:02.000000000 +0200
+++ src/ld/deffilep.y	2011-04-16 13:41:22.709788500 +0200
@@ -78,6 +78,17 @@
 #define yytable	 def_yytable
 #define yycheck	 def_yycheck
 
+typedef struct def_pool_str {
+  struct def_pool_str *next;
+  char data[1];
+} def_pool_str;
+
+static def_pool_str *pool_strs = NULL;
+
+static char *def_pool_alloc (size_t sz);
+static char *def_pool_strdup (const char *str);
+static void def_pool_free (void);
+
 static void def_description (const char *);
 static void def_exports (const char *, const char *, int, int, const char *);
 static void def_heapsize (int, int);
@@ -226,13 +237,13 @@ attr:
 opt_name: ID		{ $$ = $1; }
 	| '.' ID
 	  {
-	    char *name = xmalloc (strlen ($2) + 2);
+	    char *name = def_pool_alloc (strlen ($2) + 2);
 	    sprintf (name, ".%s", $2);
 	    $$ = name;
 	  }
 	| ID '.' ID	
 	  { 
-	    char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
+	    char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
 	    sprintf (name, "%s.%s", $1, $3);
 	    $$ = name;
 	  }
@@ -260,13 +271,13 @@ opt_base: BASE	'=' NUMBER	{ $$ = $3;}
 dot_name: ID		{ $$ = $1; }
 	| '.' ID
 	  {
-	    char *name = xmalloc (strlen ($2) + 2);
+	    char *name = def_pool_alloc (strlen ($2) + 2);
 	    sprintf (name, ".%s", $2);
 	    $$ = name;
 	  }
 	| dot_name '.' ID	
 	  { 
-	    char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
+	    char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
 	    sprintf (name, "%s.%s", $1, $3);
 	    $$ = name;
 	  }
@@ -275,13 +286,13 @@ dot_name: ID		{ $$ = $1; }
 anylang_id: ID		{ $$ = $1; }
 	| '.' ID
 	  {
-	    char *id = xmalloc (strlen ($2) + 2);
+	    char *id = def_pool_alloc (strlen ($2) + 2);
 	    sprintf (id, ".%s", $2);
 	    $$ = id;
 	  }
 	| anylang_id '.' opt_digits opt_id
 	  {
-	    char *id = xmalloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
+	    char *id = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
 	    sprintf (id, "%s.%s%s", $1, $3, $4);
 	    $$ = id;
 	  }
@@ -358,18 +369,23 @@ def_file_parse (const char *filename, de
     {
       def_file_free (def);
       fclose (the_file);
+      def_pool_free ();
       return 0;
     }
 
   fclose (the_file);
 
-  for (d = directives; d; d = d->next)
+  while ((d = directives) != NULL)
     {
 #if TRACE
       printf ("Adding directive %08x `%s'\n", d->name, d->name);
 #endif
       def_file_add_directive (def, d->name, d->len);
+      directives = d->next;
+      free (d->name);
+      free (d);
     }
+  def_pool_free ();
 
   return def;
 }
@@ -873,6 +889,7 @@ def_file_add_directive (def_file *my_def
     }
 
   def = save_def;
+  def_pool_free ();
 }
 
 /* Parser Callbacks.  */
@@ -1243,7 +1260,7 @@ def_lex (void)
 	}
       if (c != EOF)
 	def_ungetc (c);
-      yylval.digits = xstrdup (buffer);
+      yylval.digits = def_pool_strdup (buffer);
 #if TRACE
       printf ("lex: `%s' returns DIGITS\n", buffer);
 #endif
@@ -1292,7 +1309,7 @@ def_lex (void)
 #if TRACE
       printf ("lex: `%s' returns ID\n", buffer);
 #endif
-      yylval.id = xstrdup (buffer);
+      yylval.id = def_pool_strdup (buffer);
       return ID;
     }
 
@@ -1307,7 +1324,7 @@ def_lex (void)
 	  put_buf (c);
 	  c = def_getc ();
 	}
-      yylval.id = xstrdup (buffer);
+      yylval.id = def_pool_strdup (buffer);
 #if TRACE
       printf ("lex: `%s' returns ID\n", buffer);
 #endif
@@ -1347,3 +1364,40 @@ def_lex (void)
   /*printf ("lex: 0x%02x ignored\n", c); */
   return def_lex ();
 }
+
+static char *
+def_pool_alloc (size_t sz)
+{
+  def_pool_str *e;
+
+  e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
+  if (!e)
+    return NULL;
+  e->next = pool_strs;
+  pool_strs = e;
+  return e->data;
+}
+
+static char *
+def_pool_strdup (const char *str)
+{
+  char *s;
+  size_t len;
+  if (!str)
+    return NULL;
+  len = strlen (str) + 1;
+  s = def_pool_alloc (len);
+  memcpy (s, str, len);
+  return s;
+}
+
+static void
+def_pool_free (void)
+{
+  def_pool_str *p;
+  while ((p = pool_strs) != NULL)
+    {
+      pool_strs = p->next;
+      free (p);
+    }
+}


More information about the Binutils mailing list