I want to get the return value of malloc, my DTrace command is:
sudo dtrace -n 'pid32519::malloc:return {printf("%p %p %p %p %p %p %p %p %p %p %s\n",arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,probefunc);}'
and the pid of provider is a tiny program as follow:
printf("%d\n",getpid());
getchar();
int cnt=50;
void* a = malloc(1000);
printf("%llx\n",a);
a = malloc(1000);
printf("%llx\n",a);
a = malloc(1000);
printf("%llx\n",a);
a = malloc(1000);
printf("%llx\n",a);
getchar();
return 0;
I found some documentation that say "arg1 holds return value", but the result is:
CPU ID FUNCTION:NAME
8 10499 malloc:return f a 1 0 0 0 0 0 0 60000000a malloc
8 10499 malloc:return f f 1 0 0 0 0 0 f00000000 60000000a malloc
8 10499 malloc:return f 10 1 0 0 0 0 0 f00000010 60000000a malloc
8 10499 malloc:return f 10 1 0 0 0 0 1000000000 f00000010 60000000a malloc
There is none of args equaled the return value of malloc and where is it?
arg0
of the pid provider return probe contains the offset into the function of the particular return site; in this case 0xf
. The return values are suspicious which suggests that malloc
is making a "tail-call" (a shortcut by which a function is called whose value will be returned by the calling function and allows a stack frame to be elided). We can see this in the disassembly output:
libsystem_malloc.dylib`malloc:
0x7ff80c57f4d0 <+0>: movq %rdi, %rsi
0x7ff80c57f4d3 <+3>: leaq 0x41a25b26(%rip), %rdi ; virtual_default_zone
0x7ff80c57f4da <+10>: movl $0x1, %edx
0x7ff80c57f4df <+15>: jmp 0x7ff800152a59 ; _malloc_zone_malloc
Instrumenting pid$target::_malloc_zone_malloc:return
instead seems to produce reasonable return values.
FWIW this behavior is definitely confusing; during the development of DTrace we considered having tail-call returns have a special name, but discarded that as being more confusing.