Re: tracing malloc/free call
On 1/15/2015 10:34 AM, Corinna Vinschen wrote: Hi Marco, On Jan 14 23:30, Marco Atzeri wrote: Debugging a program I am trying to catch where this call is happening 17 1499678 [main] ncview 1484 free: (0x6000D7961), called by 0x180115A0B unfortunately the 0x180115A0B address is not real caller address No, the return address is the address of the _sigbe function defined in the gendef script... [cut] Bottom line, you should be able to fetch the original return address by printing the value at *(void*)_my_tls->stackptr which points to the uppermost entry on the stack. Hi Corinna, in reality I found it is "*(_my_tls.stackptr-1)" - malloc_printf ("(%p), called by %p", p, __builtin_return_address (0)); + malloc_printf ("(%p), called by %p", p, *(_my_tls.stackptr-1)); Attached patch that allows tracking of original caller, for the 4 memory allocation calls. Tested on 64 bit. $ grep 0x6000D6AA1 ncview.strace4 20 1605112 [main] ncview 4408 free: (0x6000D6AA1), called by 0x10040E744 $ addr2line.exe -a 0x10040E744 -e /usr/bin/ncview.exe 0x00010040e744 /usr/src/debug/ncview-2.1.4-2/src/file_netcdf.c:271 Regards Marco --- src_new/winsup/cygwin/malloc_wrapper.cc 2014-06-26 23:52:46.537847400 +0200 +++ src/winsup/cygwin/malloc_wrapper.cc 2015-01-16 14:41:15.766384600 +0100 @@ -17,6 +17,7 @@ #include "dtable.h" #include "perprocess.h" #include "miscfuncs.h" +#include "cygtls.h" #include "cygmalloc.h" #ifndef MALLOC_DEBUG #include @@ -38,7 +39,7 @@ extern "C" void free (void *p) { - malloc_printf ("(%p), called by %p", p, __builtin_return_address (0)); + malloc_printf ("(%p), called by %p", p, *(_my_tls.stackptr-1)); if (!use_internal) user_data->free (p); else @@ -61,7 +62,7 @@ res = dlmalloc (size); __malloc_unlock (); } - malloc_printf ("(%ld) = %p, called by %p", size, res, __builtin_return_address (0)); + malloc_printf ("(%ld) = %p, called by %p", size, res, *(_my_tls.stackptr-1)); return res; } @@ -77,7 +78,7 @@ res = dlrealloc (p, size); __malloc_unlock (); } - malloc_printf ("(%p, %ld) = %p, called by %p", p, size, res, __builtin_return_address (0)); + malloc_printf ("(%p, %ld) = %p, called by %p", p, size, res, *(_my_tls.stackptr-1)); return res; } @@ -104,7 +105,7 @@ res = dlcalloc (nmemb, size); __malloc_unlock (); } - malloc_printf ("(%ld, %ld) = %p, called by %p", nmemb, size, res, __builtin_return_address (0)); + malloc_printf ("(%ld, %ld) = %p, called by %p", nmemb, size, res, *(_my_tls.stackptr-1)); return res; }
Re: tracing malloc/free call
Hi Marco, On Jan 16 15:23, Marco Atzeri wrote: > On 1/15/2015 10:34 AM, Corinna Vinschen wrote: > >Bottom line, you should be able to fetch the original return address by > >printing the value at > > > > *(void*)_my_tls->stackptr > > > >which points to the uppermost entry on the stack. > > Hi Corinna, > > in reality I found it is "*(_my_tls.stackptr-1)" Oh, right! Sorry about that. I missed to take the behavior of xadd into account. > - malloc_printf ("(%p), called by %p", p, __builtin_return_address (0)); > + malloc_printf ("(%p), called by %p", p, *(_my_tls.stackptr-1)); > > Attached patch that allows tracking of original caller, > for the 4 memory allocation calls. > > Tested on 64 bit. > > $ grep 0x6000D6AA1 ncview.strace4 >20 1605112 [main] ncview 4408 free: (0x6000D6AA1), called by 0x10040E744 > > > $ addr2line.exe -a 0x10040E744 -e /usr/bin/ncview.exe > 0x00010040e744 > /usr/src/debug/ncview-2.1.4-2/src/file_netcdf.c:271 Thanks for the patch, but it won't work nicely either this way. The problem is that, in theory, the code has to differ between internal and external callers. Internal callers (that is, Cygwin functions itself) don't hop into the function via _sigfe/_sigbe. Thus the output for internal callers of malloc/free is now wrong with your patch. The solution for this problem would be a test which checks if the return address is the _sigbe function and if so, returns *(_my_tls.stackptr-1), otherwise __builtin_return_address(0). However, the symbol _sigbe is not exported since, so far, it was only used inside _sigfe. This needs a bit of tweaking. I'll have a look. Btw., when sending a patch, a matching ChangeLog entry would be quite helpful :} Thanks, Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat pgpJFB4pS4ZB1.pgp Description: PGP signature
Re: tracing malloc/free call
On Jan 16 16:44, Corinna Vinschen wrote: > Hi Marco, > > On Jan 16 15:23, Marco Atzeri wrote: > > On 1/15/2015 10:34 AM, Corinna Vinschen wrote: > > >Bottom line, you should be able to fetch the original return address by > > >printing the value at > > > > > > *(void*)_my_tls->stackptr > > > > > >which points to the uppermost entry on the stack. > > > > Hi Corinna, > > > > in reality I found it is "*(_my_tls.stackptr-1)" > > Oh, right! Sorry about that. I missed to take the behavior of xadd > into account. Worse, I missed the fact that _my_tls.retaddr() already provides the correct return address. Sorry again. Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat pgpRoKw5SQH0W.pgp Description: PGP signature
Re: tracing malloc/free call
On Jan 16 16:44, Corinna Vinschen wrote: > On Jan 16 15:23, Marco Atzeri wrote: > > Attached patch that allows tracking of original caller, > > for the 4 memory allocation calls. > > Thanks for the patch, but it won't work nicely either this way. The > problem is that, in theory, the code has to differ between internal and > external callers. Internal callers (that is, Cygwin functions itself) > don't hop into the function via _sigfe/_sigbe. Thus the output for > internal callers of malloc/free is now wrong with your patch. > > The solution for this problem would be a test which checks if the return > address is the _sigbe function and if so, returns *(_my_tls.stackptr-1), > otherwise __builtin_return_address(0). However, the symbol _sigbe is > not exported since, so far, it was only used inside _sigfe. This needs > a bit of tweaking. I'll have a look. I applied a patch to print the right caller address. I created a new macro caller_return_address() for reuse, should we have a desire to print the caller address in other parts of the code. I'm going to create a snapshot with this change. Please give it a try. Thanks, Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat pgpy_ZUTk5piS.pgp Description: PGP signature
Re: tracing malloc/free call
On 1/16/2015 5:22 PM, Corinna Vinschen wrote: On Jan 16 16:44, Corinna Vinschen wrote: On Jan 16 15:23, Marco Atzeri wrote: Attached patch that allows tracking of original caller, for the 4 memory allocation calls. Thanks for the patch, but it won't work nicely either this way. The problem is that, in theory, the code has to differ between internal and external callers. Internal callers (that is, Cygwin functions itself) don't hop into the function via _sigfe/_sigbe. Thus the output for internal callers of malloc/free is now wrong with your patch. I missed that point. ;-) First time I look at these inside details of cygwin The solution for this problem would be a test which checks if the return address is the _sigbe function and if so, returns *(_my_tls.stackptr-1), otherwise __builtin_return_address(0). However, the symbol _sigbe is not exported since, so far, it was only used inside _sigfe. This needs a bit of tweaking. I'll have a look. I applied a patch to print the right caller address. I created a new macro caller_return_address() for reuse, should we have a desire to print the caller address in other parts of the code. I'm going to create a snapshot with this change. Please give it a try. It works like charm. Much more easy to find misalignment between malloc/calloc/realloc and free calls Thanks, Corinna
Re: tracing malloc/free call
On Jan 16 18:33, Marco Atzeri wrote: > On 1/16/2015 5:22 PM, Corinna Vinschen wrote: > >On Jan 16 16:44, Corinna Vinschen wrote: > >>On Jan 16 15:23, Marco Atzeri wrote: > >>>Attached patch that allows tracking of original caller, > >>>for the 4 memory allocation calls. > >> > >>Thanks for the patch, but it won't work nicely either this way. The > >>problem is that, in theory, the code has to differ between internal and > >>external callers. Internal callers (that is, Cygwin functions itself) > >>don't hop into the function via _sigfe/_sigbe. Thus the output for > >>internal callers of malloc/free is now wrong with your patch. > > I missed that point. ;-) > First time I look at these inside details of cygwin Hopefully not your last :) Feel free to ask on the devs list if you have questions about the code. > >>The solution for this problem would be a test which checks if the return > >>address is the _sigbe function and if so, returns *(_my_tls.stackptr-1), > >>otherwise __builtin_return_address(0). However, the symbol _sigbe is > >>not exported since, so far, it was only used inside _sigfe. This needs > >>a bit of tweaking. I'll have a look. > > > >I applied a patch to print the right caller address. I created a new > >macro caller_return_address() for reuse, should we have a desire to > >print the caller address in other parts of the code. > > > >I'm going to create a snapshot with this change. Please give it > >a try. > > It works like charm. > Much more easy to find misalignment between > malloc/calloc/realloc and free calls I'm glad it works for you, too. Btw., did you see my PM? Thanks, Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat pgpE9DKIv0uEK.pgp Description: PGP signature