Description: Aligned memory allocation
 Changes to the allocators, to allow for aligned 
 allocation. Not very well tested. May not be portable.
 Also changed GET_RET_ADDR macro. 
 .
 dmalloc (5.5.2-2) unstable; urgency=low
 .
   * Added posix_memalign
   * changed GET_RET_ADDR() to use __builtin_return_address
Author: Johann Klammer <klammerj@a1.net>
Bug-Debian: http://bugs.debian.org/676585
Bug-Debian: http://bugs.debian.org/676587

--- dmalloc-5.5.2.orig/malloc.c
+++ dmalloc-5.5.2/malloc.c
@@ -38,6 +38,20 @@
 # include <unistd.h>				/* for write */
 #endif
 
+#if HAVE_ERRNO_H
+# include <errno.h>				/* for ENOMEM EINVAL */
+#else
+
+#ifndef ENOMEM
+#define ENOMEM 1
+#endif /*ENOMEM*/
+
+#ifndef EINVAL
+#define EINVAL 2
+#endif /*EINVAL*/
+
+#endif /*HAVE_ERRNO_H*/
+
 /*
  * cygwin includes
  */
@@ -719,6 +733,12 @@ void	__fini_dmalloc(void)
 }
 #endif
 
+
+static int is_aligned_to(const char * rv,const DMALLOC_SIZE alignment)
+{
+	return 0==(((DMALLOC_SIZE)rv)%alignment);//alignment must not be zero
+}
+
 /*
  * DMALLOC_PNT dmalloc_malloc
  *
@@ -754,6 +774,41 @@ DMALLOC_PNT	dmalloc_malloc(const char *f
 			       const DMALLOC_SIZE alignment,
 			       const int xalloc_b)
 {
+	DMALLOC_SIZE align=(alignment==0)?1:alignment;//0==bad
+	DMALLOC_SIZE overhead=align-1+sizeof(DMALLOC_SIZE);
+	DMALLOC_SIZE offset=0,sz;
+	DMALLOC_PNT base;
+	char * rv;
+
+	sz=size+overhead;
+#if ALLOW_ALLOC_ZERO_SIZE == 0
+	if (size == 0) {
+		sz=0;
+	}
+#endif
+
+	base=dmalloc_malloc_real(file, line, sz,  func_id, 0, xalloc_b);
+	rv=base;
+
+	if(NULL==rv)
+		return NULL;
+	/*byte addressable?*/
+	while(! is_aligned_to(rv+sizeof(offset),align))
+	{
+		offset++;
+		rv++;
+	}
+	
+	memmove(rv,&offset,sizeof(offset));
+	rv+=sizeof(offset);
+	return rv;
+}
+
+DMALLOC_PNT	dmalloc_malloc_real(const char *file, const int line,
+			       const DMALLOC_SIZE size, const int func_id,
+			       const DMALLOC_SIZE alignment,
+			       const int xalloc_b)
+{
   void		*new_p;
   DMALLOC_SIZE	align;
   
@@ -825,12 +880,79 @@ DMALLOC_PNT	dmalloc_malloc(const char *f
   return new_p;
 }
 
+
+static int power_of_two(DMALLOC_SIZE v)
+{
+	unsigned i;
+	for(i=0;i<(sizeof(v)*8);i++) {
+		if((((DMALLOC_SIZE)1)<<i)==v)
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * int dmalloc_posix_memalign
+ *
+ * DESCRIPTION:
+ *
+ * Overloading the posix_memalign(3) function.  Allocate and return a memory
+ * block of a certain size which has been aligned to a certain
+ * alignment.
+ *
+ * RETURNS:
+ *
+ * Success - zero.
+ * EINVAL The alignment argument was not a power of two, or was not a multiple of sizeof(void *).
+ * ENOMEM There was insufficient memory to fulfill the allocation request.
+ *
+ * ARGUMENTS:
+ * memptr -> pointer will be returned here on success
+ *
+ * alignment -> Value to which the allocation must be aligned.  This
+ * should probably be a multiple of 2 with a maximum value equivalent
+ * to the block-size which is often 1k or 4k.
+ *
+ * size -> Number of bytes requested.
+ *
+ * file -> File-name or return-address of the caller.
+ *
+ * line -> Line-number of the caller.
+ *
+ * func_id -> Function-id to identify the type of call.  See
+ * dmalloc.h.
+ *
+ * xalloc_b -> If set to 1 then print an error and exit if we run out
+ * of memory.
+ */
+extern
+int	dmalloc_posix_memalign(const char *file, const int line, DMALLOC_PNT *memptr,
+			       const DMALLOC_SIZE size, const int func_id,
+			       const DMALLOC_SIZE alignment,
+			       const int xalloc_b)
+{
+	DMALLOC_PNT rv;
+  if((NULL==memptr)||(!power_of_two(alignment))||(alignment<sizeof(void*)))
+    return EINVAL;
+  
+	rv=dmalloc_malloc(file, line,size, func_id, alignment, xalloc_b);
+	if(NULL==rv)
+		return ENOMEM;
+	*memptr=rv;
+	return 0;
+}
+
+extern
+DMALLOC_PNT _dmalloc_chunk_get_baseptr(DMALLOC_PNT p);
+
+
 /*
  * DMALLOC_PNT dmalloc_realloc
  *
  * DESCRIPTION:
  *
  * Resizes and old pointer to a new number of bytes.
+ * Will destroy previous alignment.
  *
  * RETURNS:
  *
@@ -855,7 +977,69 @@ DMALLOC_PNT	dmalloc_malloc(const char *f
  * xalloc_b -> If set to 1 then print an error and exit if we run out
  * of memory.
  */
+
 DMALLOC_PNT	dmalloc_realloc(const char *file, const int line,
+				DMALLOC_PNT old_p, DMALLOC_SIZE new_size,
+				const int func_id, const int xalloc_b)
+{
+	DMALLOC_PNT old_pnt=NULL;
+	DMALLOC_PNT new_pnt=NULL;
+	DMALLOC_SIZE old_offs=0,offs=0,nsz=0;//no alignment
+
+	if(NULL!=old_p) {
+		old_pnt=_dmalloc_chunk_get_baseptr(old_p);
+		memmove(&old_offs,old_p-sizeof(old_offs),sizeof(old_offs));
+	}
+	
+	nsz=new_size+sizeof(offs)+old_offs;
+
+	//hope I got those right now..
+	if(0==new_size) {
+
+#if ALLOW_REALLOC_SIZE_ZERO
+		nsz=0;
+#else
+#if ALLOW_ALLOC_ZERO_SIZE == 0
+		nsz=0;
+#else
+		nsz=sizeof(offs);
+#endif
+#endif
+	}
+	/*
+	something like this..
+	if((0==ALLOW_ALLOC_ZERO_SIZE)&&(1==ALLOW_REALLOC_SIZE_ZERO)&&(0==new_size))
+	{
+	//dmalloc_chunk_free
+	}
+	if((1==ALLOW_ALLOC_ZERO_SIZE)&&(1==ALLOW_REALLOC_SIZE_ZERO)&&(0==new_size))
+	{
+	//dmalloc_chunk_free
+	}
+	if((0==ALLOW_ALLOC_ZERO_SIZE)&&(0==ALLOW_REALLOC_SIZE_ZERO)&&(0==new_size))
+	{
+	//should generate error (and we get a NULL back)... the same as dmalloc_chunk_free, but no free
+	}
+	if((1==ALLOW_ALLOC_ZERO_SIZE)&&(0==ALLOW_REALLOC_SIZE_ZERO)&&(0==new_size))
+	{
+	//allocate a min sized block(offset should fit)
+	}
+	*/
+	
+
+
+	new_pnt=dmalloc_realloc_real(file, line, old_pnt, nsz,
+				func_id, xalloc_b);
+	if(NULL==new_pnt)
+		return NULL;
+	
+	memmove(new_pnt,&offs,sizeof(offs));
+	if((0!=old_offs)&&(0!=new_size))
+		memmove(new_pnt+sizeof(offs),new_pnt+sizeof(offs)+old_offs,new_size);
+	return new_pnt+sizeof(offs);
+}
+
+DMALLOC_PNT	dmalloc_realloc_real(const char *file, const int line,
 				DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size,
 				const int func_id, const int xalloc_b)
 {
@@ -932,6 +1116,7 @@ DMALLOC_PNT	dmalloc_realloc(const char *
   return new_p;
 }
 
+
 /*
  * int dmalloc_free
  *
@@ -962,6 +1147,14 @@ DMALLOC_PNT	dmalloc_realloc(const char *
 int	dmalloc_free(const char *file, const int line, DMALLOC_PNT pnt,
 		     const int func_id)
 {
+	DMALLOC_PNT p;
+	p=_dmalloc_chunk_get_baseptr(pnt);
+	return dmalloc_free_real(file,line,p,func_id);
+}
+
+int	dmalloc_free_real(const char *file, const int line, DMALLOC_PNT pnt,
+		     const int func_id)
+{
   int		ret;
   
   if (! dmalloc_in(file, line, 1)) {
@@ -1209,6 +1402,40 @@ DMALLOC_PNT	memalign(DMALLOC_SIZE alignm
 			0 /* no xalloc messages */);
 }
 
+
+/*
+ * int posix_memalign
+ *
+ * DESCRIPTION:
+ *
+ * Overloading the posix_memalign(3) function.  Allocate and return a memory
+ * block of a certain size which has been aligned to a certain
+ * alignment.
+ *
+ * RETURNS:
+ *
+ * Success - zero.
+ * EINVAL The alignment argument was not a power of two, or was not a multiple of sizeof(void *).
+ * ENOMEM There was insufficient memory to fulfill the allocation request.
+ * 
+ *
+ * ARGUMENTS:
+ * memptr -> pointer will be returned here on success
+ * alignment -> Value to which the allocation must be aligned.  This
+ * should probably be a multiple of 2 with a maximum value equivalent
+ * to the block-size which is often 1k or 4k.
+ *
+ * size -> Number of bytes requested.
+ */
+#undef posix_memalign
+int	posix_memalign(DMALLOC_PNT *memptr, DMALLOC_SIZE alignment, DMALLOC_SIZE size)
+{
+  char		*file;
+  GET_RET_ADDR(file);
+	return dmalloc_posix_memalign(file, DMALLOC_DEFAULT_LINE, memptr,
+			       size, DMALLOC_FUNC_POSIX_MEMALIGN, alignment,
+			       0);
+}
 /*
  * DMALLOC_PNT valloc
  *
@@ -1428,6 +1655,13 @@ DMALLOC_FREE_RET	cfree(DMALLOC_PNT pnt)
  */
 int	dmalloc_verify(const DMALLOC_PNT pnt)
 {
+	DMALLOC_PNT p;
+	p=_dmalloc_chunk_get_baseptr((DMALLOC_PNT)pnt);
+	return dmalloc_verify_real(p);
+}
+
+int	dmalloc_verify_real(const DMALLOC_PNT pnt)
+{
   int	ret;
   
   if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 0)) {
@@ -1526,6 +1760,9 @@ int	dmalloc_verify_pnt_strsize(const cha
   if (! dmalloc_in(file, line, 0)) {
     return MALLOC_VERIFY_NOERROR;
   }
+
+  if(exact_b)/* we need the exact ptr... may weaken checks... */
+	  pnt=_dmalloc_chunk_get_baseptr((DMALLOC_PNT)pnt);
   
   /* call the pnt checking chunk code */
   ret = _dmalloc_chunk_pnt_check(func, pnt, exact_b, strlen_b, min_size);
@@ -1737,6 +1974,34 @@ int	dmalloc_examine(const DMALLOC_PNT pn
 			unsigned int *line_p, DMALLOC_PNT *ret_attr_p,
 			unsigned long *used_mark_p, unsigned long *seen_p)
 {
+	DMALLOC_PNT p;
+	int rv;
+	DMALLOC_SIZE s,offs,u_s;
+	if(NULL!=user_size_p)
+		s=*user_size_p;
+	
+	p=_dmalloc_chunk_get_baseptr((DMALLOC_PNT)pnt);
+	rv=dmalloc_examine_real(p, &s,
+			total_size_p, file_p,line_p, ret_attr_p,used_mark_p, seen_p);
+	if(NULL!=p)
+	{
+		memmove(&offs,((char *)pnt)-sizeof(offs),sizeof(offs));
+		u_s=s-sizeof(offs)-offs;
+	}
+	else
+	{
+		u_s=s;
+	}
+	if(NULL!=user_size_p)
+		*user_size_p=u_s;
+	return rv;
+}
+
+int	dmalloc_examine_real(const DMALLOC_PNT pnt, DMALLOC_SIZE *user_size_p,
+			DMALLOC_SIZE *total_size_p, char **file_p,
+			unsigned int *line_p, DMALLOC_PNT *ret_attr_p,
+			unsigned long *used_mark_p, unsigned long *seen_p)
+{
   int		ret;
   unsigned int	user_size_map, tot_size_map;
   unsigned long	*loc_seen_p;
--- dmalloc-5.5.2.orig/chunk.c
+++ dmalloc-5.5.2/chunk.c
@@ -2463,6 +2463,9 @@ void	*_dmalloc_chunk_malloc(const char *
     case DMALLOC_FUNC_MEMALIGN:
       trans_log = "memalign";
       break;
+    case DMALLOC_FUNC_POSIX_MEMALIGN:
+      trans_log = "posix_memalign";
+      break;
     case DMALLOC_FUNC_VALLOC:
       trans_log = "valloc";
       break;
@@ -3130,6 +3133,19 @@ void	_dmalloc_chunk_log_changed(const un
   }
 }
 
+DMALLOC_PNT _dmalloc_chunk_get_baseptr(DMALLOC_PNT p)
+{
+	char * rv=p;
+	DMALLOC_SIZE offset=0;
+	if(NULL==p)
+		return NULL;
+	rv-=sizeof(offset);
+	memmove(&offset,rv,sizeof(offset));
+	rv-=offset;
+	return rv;
+}
+
+
 /*
  * unsigned long _dmalloc_chunk_count_changed
  *
@@ -3207,6 +3223,7 @@ unsigned long	_dmalloc_chunk_count_chang
       mem_count += slot_p->sa_user_size;
     }
     else if (count_freed_b && freed_b) {
+      char * a,*b;
       mem_count += slot_p->sa_user_size;
     }
   }
--- dmalloc-5.5.2.orig/dmalloc.h.3
+++ dmalloc-5.5.2/dmalloc.h.3
@@ -41,15 +41,16 @@
 #define DMALLOC_FUNC_REALLOC	12	/* realloc function called */
 #define DMALLOC_FUNC_RECALLOC	13	/* recalloc called */
 #define DMALLOC_FUNC_MEMALIGN	14	/* memalign function called */
-#define DMALLOC_FUNC_VALLOC	15	/* valloc function called */
-#define DMALLOC_FUNC_STRDUP	16	/* strdup function called */
-#define DMALLOC_FUNC_FREE	17	/* free function called */
-#define DMALLOC_FUNC_CFREE	18	/* cfree function called */
-
-#define DMALLOC_FUNC_NEW	20	/* new function called */
-#define DMALLOC_FUNC_NEW_ARRAY	21	/* new[] function called */
-#define DMALLOC_FUNC_DELETE	22	/* delete function called */
-#define DMALLOC_FUNC_DELETE_ARRAY 23	/* delete[] function called */
+#define DMALLOC_FUNC_POSIX_MEMALIGN	15	/* memalign function called */
+#define DMALLOC_FUNC_VALLOC	16	/* valloc function called */
+#define DMALLOC_FUNC_STRDUP	17	/* strdup function called */
+#define DMALLOC_FUNC_FREE	18	/* free function called */
+#define DMALLOC_FUNC_CFREE	19	/* cfree function called */
+
+#define DMALLOC_FUNC_NEW	21	/* new function called */
+#define DMALLOC_FUNC_NEW_ARRAY	22	/* new[] function called */
+#define DMALLOC_FUNC_DELETE	23	/* delete function called */
+#define DMALLOC_FUNC_DELETE_ARRAY 24	/* delete[] function called */
 
 #ifdef __cplusplus
 extern "C" {
@@ -148,6 +149,52 @@ DMALLOC_PNT	dmalloc_malloc(const char *f
 			       const DMALLOC_SIZE alignment,
 			       const int xalloc_b);
 
+extern
+DMALLOC_PNT	dmalloc_malloc_real(const char *file, const int line,
+			       const DMALLOC_SIZE size, const int func_id,
+			       const DMALLOC_SIZE alignment,
+			       const int xalloc_b);
+
+/*
+ * int dmalloc_posix_memalign
+ *
+ * DESCRIPTION:
+ *
+ * Overloading the posix_memalign(3) function.  Allocate and return a memory
+ * block of a certain size which has been aligned to a certain
+ * alignment.
+ *
+ * RETURNS:
+ *
+ * Success - zero.
+ * EINVAL The alignment argument was not a power of two, or was not a multiple of sizeof(void *).
+ * ENOMEM There was insufficient memory to fulfill the allocation request.
+ * 
+ *
+ * ARGUMENTS:
+ * memptr -> pointer will be returned here on success
+ *
+ * alignment -> Value to which the allocation must be aligned.  This
+ * should probably be a multiple of 2 with a maximum value equivalent
+ * to the block-size which is often 1k or 4k.
+ *
+ * size -> Number of bytes requested.
+ *
+ * file -> File-name or return-address of the caller.
+ *
+ * line -> Line-number of the caller.
+ *
+ * func_id -> Function-id to identify the type of call.  See
+ * dmalloc.h.
+ *
+ * xalloc_b -> If set to 1 then print an error and exit if we run out
+ * of memory.
+ */
+extern
+int	dmalloc_posix_memalign(const char *file, const int line, DMALLOC_PNT *memptr,
+			       const DMALLOC_SIZE size, const int func_id,
+			       const DMALLOC_SIZE alignment,
+			       const int xalloc_b);
 /*
  * DMALLOC_PNT dmalloc_realloc
  *
@@ -182,6 +229,10 @@ extern
 DMALLOC_PNT	dmalloc_realloc(const char *file, const int line,
 				DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size,
 				const int func_id, const int xalloc_b);
+extern
+DMALLOC_PNT	dmalloc_realloc_real(const char *file, const int line,
+				DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size,
+				const int func_id, const int xalloc_b);
 
 /*
  * int dmalloc_free
@@ -213,6 +264,9 @@ DMALLOC_PNT	dmalloc_realloc(const char *
 extern
 int	dmalloc_free(const char *file, const int line, DMALLOC_PNT pnt,
 		     const int func_id);
+extern
+int	dmalloc_free_real(const char *file, const int line, DMALLOC_PNT pnt,
+		     const int func_id);
 
 /*
  * DMALLOC_PNT dmalloc_strndup
@@ -1030,10 +1084,14 @@ const char	*dmalloc_strerror(const int e
 #define memalign(alignment, size) \
   dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MEMALIGN, \
 		 (alignment), 0 /* no xalloc */)
+#undef posix_memalign
+#define posix_memalign(memptr,alignment, size) \
+  dmalloc_posix_memalign(__FILE__, __LINE__, (memptr), (size), DMALLOC_FUNC_POSIX_MEMALIGN, \
+		 (alignment), 0 /* no xalloc */)
 #undef valloc
 #define valloc(size) \
   dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_VALLOC, \
-		0 /* special case */, 0 /* no xalloc */)
+		BLOCK_SIZE, 0 /* no xalloc */)
 #ifndef DMALLOC_STRDUP_MACRO
 #undef strdup
 #define strdup(str) \
--- dmalloc-5.5.2.orig/configure.ac
+++ dmalloc-5.5.2/configure.ac
@@ -79,6 +79,9 @@ AC_CHECK_HEADER([string.h],
 AC_CHECK_HEADER([unistd.h],
 		[AC_DEFINE(HAVE_UNISTD_H,1) AC_SUBST([HAVE_UNISTD_H],1)],
 		[AC_DEFINE(HAVE_UNISTD_H,0) AC_SUBST([HAVE_UNISTD_H],0)])
+AC_CHECK_HEADER([errno.h],
+		[AC_DEFINE(HAVE_ERRNO_H,1) AC_SUBST([HAVE_ERRNO_H],1)],
+		[AC_DEFINE(HAVE_ERRNO_H,0) AC_SUBST([HAVE_ERRNO_H],0)])
 AC_CHECK_HEADER([sys/types.h],
 		[AC_DEFINE(HAVE_SYS_TYPES_H,1) AC_SUBST([HAVE_SYS_TYPES_H],1)],
 		[AC_DEFINE(HAVE_SYS_TYPES_H,0) AC_SUBST([HAVE_SYS_TYPES_H],0)])
--- dmalloc-5.5.2.orig/dmalloc_t.c
+++ dmalloc-5.5.2/dmalloc_t.c
@@ -3945,6 +3945,10 @@ static	void	track_alloc_trxn(const char 
     (void)printf("%s memalign %d bytes alignment %d got %#lx\n",
 		 file_line, byte_size, alignment, (long)new_addr);
     break;
+  case DMALLOC_FUNC_POSIX_MEMALIGN:
+    (void)printf("%s posix_memalign %d bytes alignment %d got %#lx\n",
+		 file_line, byte_size, alignment, (long)new_addr);
+    break;
   case DMALLOC_FUNC_VALLOC:
     (void)printf("%s valloc %d bytes alignment %d got %#lx\n",
 		 file_line, byte_size, alignment, (long)new_addr);
--- dmalloc-5.5.2.orig/Makefile.in
+++ dmalloc-5.5.2/Makefile.in
@@ -25,6 +25,7 @@ DEFS = -DHAVE_STDARG_H=@HAVE_STDARG_H@ \
 	-DHAVE_STDLIB_H=@HAVE_STDLIB_H@ \
 	-DHAVE_STRING_H=@HAVE_STRING_H@ \
 	-DHAVE_UNISTD_H=@HAVE_UNISTD_H@ \
+	-DHAVE_ERRNO_H=@HAVE_ERRNO_H@ \
 	-DHAVE_SYS_MMAN_H=@HAVE_SYS_MMAN_H@ \
 	-DHAVE_SYS_TYPES_H=@HAVE_SYS_TYPES_H@ \
 	-DHAVE_W32API_WINBASE_H=@HAVE_W32API_WINBASE_H@ \
--- dmalloc-5.5.2.orig/return.h
+++ dmalloc-5.5.2/return.h
@@ -94,7 +94,50 @@
 /*************************************/
 
 /* for i[34]86 machines with GCC */
-#if __i386 && __GNUC__ > 1
+/*assembly... blechhh.. the first opcode segfaults dmalloc_fc_t -s... somewhere in the argument checking*/
+/*
+Dump of assembler code for function malloc:
+   0x08053870 <+0>:     sub    esp,0x2c
+=> 0x08053873 <+3>:     mov    eax,DWORD PTR [ebp+0x4]
+   0x08053876 <+6>:     mov    edx,eax
+   
+   
+
+(gdb) backtrace
+#0  malloc (size=8) at malloc.c:1226
+#1  0x0804f906 in argv_process_no_env (args=0x805f120, arg_n=2, 
+    argv=0xbffffcc4) at dmalloc_argv.c:3201
+#2  0x0804fc61 in argv_process (args=0x805f120, argc=2, argv=0xbffffcc4)
+    at dmalloc_argv.c:3290
+#3  0x080496e6 in main (argc=2, argv=0xbffffcc4) at dmalloc_fc_t.c:1078
+
+(gdb) info registers
+eax            0x8      8
+ecx            0x805f770        134608752
+edx            0x7b     123
+ebx            0x0      0
+esp            0xbffffb20       0xbffffb20
+ebp            0x14     0x14
+esi            0xf7fa0ee0       -134607136
+edi            0x805f138        134607160
+eip            0x8053873        0x8053873 <malloc+3>
+eflags         0x10282  [ SF IF RF ]
+cs             0x73     115
+ss             0x7b     123
+ds             0x7b     123
+es             0x7b     123
+fs             0x0      0
+gs             0x33     51
+
+turns out ebp is never written...
+I wonder if it might be that -fstack_protector
+gcc version  (Debian 4.6.2-11)
+changing to use __builtin_
+*/
+#if __i386 && __GNUC__ > 3
+#define GET_RET_ADDR(file)	((file)=(char *)__builtin_return_address(0))
+
+#elif __i386 && __GNUC__ > 1
 
 #define GET_RET_ADDR(file)	asm("movl 4(%%ebp),%%eax ; movl %%eax,%0" : \
 				    "=g" (file) : \
