[Gc] RE: [gclist] GC and Linux IA64

Boehm, Hans hans_boehm@hp.com
Tue, 18 Nov 2003 17:03:30 -0800


This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

------_=_NextPart_000_01C3AE38.F24E2F3C
Content-Type: text/plain;
	charset="iso-8859-1"

You might try the attached patch, which should give you a single level of
callers in leak reports, on IA64, and probably other platforms.  It's bigger
than I had hoped, since in this mode the GC starts addr2line subprocesses.
At least on the machine on which I was testing, those leaked substantially,
and I needed to eliminate the leak testing for those subprocesses to
avoid flooding the output in noise.  (There are other issues with starting
those subprocesses, but usually it should work.  And you don't want to run
production code with LD_PRELOAD leak testing anyway.)

Hans

> -----Original Message-----
> From: gc-admin@napali.hpl.hp.com [mailto:gc-admin@napali.hpl.hp.com]On
> Behalf Of Boehm, Hans
> Sent: Tuesday, November 18, 2003 2:51 PM
> To: 'Sebastien Termeau'
> Cc: gclist@iecc.com; 'gc@linux.hpl.hp.com'
> Subject: [Gc] RE: [gclist] GC and Linux IA64
> 
> 
> The preferred mailing list for discussion specific to this 
> collector is probably
> gc@linux.hpl.hp.com.  Please see the bottom of the page at
> http://www.hpl.hp.com/personal/Hans_Boehm/gc for details.
> 
> Some answers:
> 
> - I believe the reported addresses are correct.  GC_malloc 
> doesn't necessarily allocate
> at addresses similar to malloc.  And you are really replacing 
> malloc in this case.
> 
> - You don't currently get reasonable leak reports on IA64.  
> The information you get
> is correct, but not useful.  You end up with a routine called 
> malloc, which calls
> GC_debug_malloc_replacement.  The only information 
> GC_debug_malloc_replacement has
> access to is its caller's address, which is always "malloc".  
> This needs to be fixed
> in two distinct ways:
> 
> 1) It should be possible to get rid of the extra level of 
> calls, so that at least the
> return address is meaningful.  I'll see if I can do that for 
> the official 6.3 release.
> This should help a number of platforms, provided gcc is used 
> as the compiler.  This part
> of it is really a bug.
> 
> 2) It should be possible to get full call stack traces on 
> ia64 with libunwind
> (http://www.hpl.hp.com/research/linux/libunwind/).  I think 
> this is easy to hack by
> implementing GC_save_callers (bottom of os_dep.c) in terms of 
> libunwind.  It's a little
> harder to get the configuration stuff right, since I don't 
> think libunwind is currently
> in all ia64 Linux distributions, though it's rapidly getting 
> there.   You will probably
> see a more appreciable slowdown with this approach, but I 
> think performance should
> still be acceptable for most purposes.
> 
> Hans
> 
> 
> 
> > -----Original Message-----
> > From: owner-gclist@lists.iecc.com 
> > [mailto:owner-gclist@lists.iecc.com]On
> > Behalf Of Sebastien Termeau
> > Sent: Tuesday, November 18, 2003 1:39 AM
> > To: gclist@iecc.com
> > Subject: [gclist] GC and Linux IA64
> > 
> > 
> > Hello,
> > 
> >  
> > 
> > I am new to GC, and I cannot find the mailing list archive 
> ( ftp site
> > down? ).
> > 
> > I am trying to find memory leaks under Linux IA64.
> > 
> > I get latest GC release (6.3) ( I tried with older version too ).
> > 
> > When I use GC functions in my code, it works fine, even if 
> it returns
> > bad addresses:
> > 
> > Leaked composite object at 0x6000000000045fd0 (testgc.c:18, sz=4)
> > 
> > Intead of
> > 
> > Leaked composite object at 0x4000000000000a30 (testgc.c:18, sz=4)
> > 
> >  
> > 
> > However when I use normal malloc calls and LD_PRELOAD, GC fails to
> > retrieve memory leaks locations (files and line numbers).
> > 
> > Addr2line and GDB returns the correct addresses.
> > 
> > Is it a known problem with IA64?
> > 
> > Do you have a solution?
> > 
> > Regards
> > 
> >  
> > 
> > Termeau Sebastien
> > 
> > 04-76-52-65-67
> > 
> > termeau@tidhom1g.grenoble. <mailto:termeau@tidhom1g.grenoble.hp.com>
> > hp.com
> > 
> > http://155.208.210.70/
> > 
> >  
> > 
> _______________________________________________
> Gc mailing list
> Gc@linux.hpl.hp.com
> http://linux.hpl.hp.com/cgi-bin/mailman/listinfo/gc
> 


------_=_NextPart_000_01C3AE38.F24E2F3C
Content-Type: application/octet-stream;
	name="ia64.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="ia64.diff"

--- os_dep.c.orig	2003-11-18 16:27:11.000000000 -0800=0A=
+++ os_dep.c	2003-11-18 16:35:42.000000000 -0800=0A=
@@ -4062,6 +4062,9 @@=0A=
 #		define RESULT_SZ 200=0A=
 		static char result_buf[RESULT_SZ];=0A=
 		size_t result_len;=0A=
+		char *old_preload;=0A=
+#		define PRELOAD_SZ 200=0A=
+    		char preload_buf[PRELOAD_SZ];=0A=
 		static GC_bool found_exe_name =3D FALSE;=0A=
 		static GC_bool will_fail =3D FALSE;=0A=
 		int ret_code;=0A=
@@ -4083,7 +4086,20 @@=0A=
 		/* isn't time critical.					*/=0A=
 		sprintf(cmd_buf, "/usr/bin/addr2line -f -e %s 0x%lx", exe_name,=0A=
 				 (unsigned long)info[i].ci_pc);=0A=
+		old_preload =3D getenv ("LD_PRELOAD");=0A=
+	        if (0 !=3D old_preload) {=0A=
+		  if (strlen (old_preload) >=3D PRELOAD_SZ) {=0A=
+		    will_fail =3D TRUE;=0A=
+		    goto out;=0A=
+		  }=0A=
+		  strcpy (preload_buf, old_preload);=0A=
+		  unsetenv ("LD_PRELOAD");=0A=
+	        }=0A=
 		pipe =3D popen(cmd_buf, "r");=0A=
+		if (0 !=3D old_preload=0A=
+		    && 0 !=3D setenv ("LD_PRELOAD", preload_buf, 0)) {=0A=
+		  WARN("Failed to reset LD_PRELOAD\n", 0);=0A=
+      		}=0A=
 		if (pipe =3D=3D NULL=0A=
 		    || (result_len =3D fread(result_buf, 1, RESULT_SZ - 1, pipe))=0A=
 		       =3D=3D 0) {=0A=
--- malloc.c.orig	2003-11-18 15:26:01.000000000 -0800=0A=
+++ malloc.c	2003-11-18 15:40:32.000000000 -0800=0A=
@@ -311,6 +311,19 @@=0A=
 }=0A=
 =0A=
 # ifdef REDIRECT_MALLOC=0A=
+=0A=
+/* Avoid unnecessary nested procedure calls here, by #defining some	=
*/=0A=
+/* malloc replacements.  Otherwise we end up saving a 			*/=0A=
+/* meaningless return address in the object.  It also speeds things =
up,	*/=0A=
+/* but it is admittedly quite ugly.					*/=0A=
+# ifdef GC_ADD_CALLER=0A=
+#   define RA GC_RETURN_ADDR,=0A=
+# else=0A=
+#   define RA=0A=
+# endif=0A=
+# define GC_debug_malloc_replacement(lb) \=0A=
+	GC_debug_malloc(lb, RA "unknown", 0)=0A=
+=0A=
 # ifdef __STDC__=0A=
     GC_PTR malloc(size_t lb)=0A=
 # else=0A=
@@ -363,6 +376,8 @@=0A=
  /* and thus the right thing will happen even without overriding it.	 =
*/=0A=
  /* This seems to be true on most Linux systems.			 */=0A=
 =0A=
+#undef GC_debug_malloc_replacement=0A=
+=0A=
 # endif /* REDIRECT_MALLOC */=0A=
 =0A=
 /* Explicitly deallocate an object p.				*/=0A=
--- mallocx.c.orig	2003-11-18 15:26:55.000000000 -0800=0A=
+++ mallocx.c	2003-11-18 15:42:26.000000000 -0800=0A=
@@ -147,6 +147,16 @@=0A=
 # endif=0A=
 =0A=
 # ifdef REDIRECT_REALLOC=0A=
+=0A=
+/* As with malloc, avoid two levels of extra calls here.	*/=0A=
+# ifdef GC_ADD_CALLER=0A=
+#   define RA GC_RETURN_ADDR,=0A=
+# else=0A=
+#   define RA=0A=
+# endif=0A=
+# define GC_debug_realloc_replacement(p, lb) \=0A=
+	GC_debug_realloc(p, lb, RA "unknown", 0)=0A=
+=0A=
 # ifdef __STDC__=0A=
     GC_PTR realloc(GC_PTR p, size_t lb)=0A=
 # else=0A=
@@ -157,6 +167,8 @@=0A=
   {=0A=
     return(REDIRECT_REALLOC(p, lb));=0A=
   }=0A=
+=0A=
+# undef GC_debug_realloc_replacement=0A=
 # endif /* REDIRECT_REALLOC */=0A=
 =0A=
 =0A=

------_=_NextPart_000_01C3AE38.F24E2F3C--