|
From: <pa...@fr...> - 2017-02-05 19:31:15
|
Hi all
I'm trying to understand how valgrind resolves replacement functions at runtime.
Here's the code that I'm using:
class MyClass
{
int i;
};
int main()
{
MyClass* myClass = new MyClass();
delete myClass;
}
GCC 4.8.2 emits
gnm test64_482 | grep _Z
U _ZdlPv
U _Znwm
Or demangled
gnm -C test64_482 | grep operator
U operator delete(void*)
U operator new(unsigned long)
I see that this corresponds to the following in vg_replace_malloc.c:
FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPv, __builtin_vec_delete );
FREE(SO_SYN_MALLOC, _ZdaPv, __builtin_vec_delete );
At runtime
valgrind --trace-malloc=yes ./test64_482
--7974-- _Znwm(4) = 0x7FF760040
--7974-- _ZdlPv(0x7FF760040)
So far so good.
With GCC built from SVN head (but I'd expect the same for any GCC since version 6) this changes a bit. [see also bz 72347]
GCC emits
gnm test64 | grep _Z
U _ZdlPvm
U _Znwm
demangled
gnm -C test64 | grep operator
U operator delete(void*, unsigned long)
U operator new(unsigned long)
valgrind --trace-malloc=yes ./test64
--9374-- malloc(72704) = 0x7FF680040
--9374-- _Znwm(4) = 0x7FF691C80
--9374-- _ZdlPv(0x7FF691C80)
--9374-- free(0x7FF680040)
The extra malloc/free are, I guess, artefacts of the newer libstdc++; I get them even with an empty main().
I don't see how (and I haven't found in the Vagrind code) how the call to ZdlPvm resolves to _ZdlPv. Can anyone tell me where to look in the Valgrind code for this?
A+
Paul
|
|
From: Ivo R. <iv...@iv...> - 2017-02-07 13:16:34
|
2017-02-05 20:31 GMT+01:00 <pa...@fr...>: > Hi all > > I'm trying to understand how valgrind resolves replacement functions at runtime. Hi Paul, Have a look at pub_tool_redir.h, mechanics and Z-encoding rules are described there. > GCC 4.8.2 emits > gnm test64_482 | grep _Z > U _ZdlPv > U _Znwm > > > Or demangled > > gnm -C test64_482 | grep operator > U operator delete(void*) > U operator new(unsigned long) > > I see that this corresponds to the following in vg_replace_malloc.c: > > FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPv, __builtin_vec_delete ); > FREE(SO_SYN_MALLOC, _ZdaPv, __builtin_vec_delete ); > > > At runtime > > valgrind --trace-malloc=yes ./test64_482 > --7974-- _Znwm(4) = 0x7FF760040 > --7974-- _ZdlPv(0x7FF760040) > > So far so good. > > With GCC built from SVN head (but I'd expect the same for any GCC since version 6) this changes a bit. [see also bz 72347] > > GCC emits > gnm test64 | grep _Z > U _ZdlPvm > U _Znwm > > demangled > > gnm -C test64 | grep operator > U operator delete(void*, unsigned long) > U operator new(unsigned long) > > valgrind --trace-malloc=yes ./test64 > --9374-- malloc(72704) = 0x7FF680040 > --9374-- _Znwm(4) = 0x7FF691C80 > --9374-- _ZdlPv(0x7FF691C80) > --9374-- free(0x7FF680040) I think you've already spotted the difference between: _ZdlPv: operator delete(void*) [which is replaced by _ZdaPv: __builtin_vec_delete] and _ZdlPvm: operator delete(void*, unsigned long) So the remaining task becomes finding a replacer for _ZdlPvm and if there is none, providing one. I. |
|
From: <pa...@fr...> - 2017-02-08 21:12:28
|
----- Original Message -----
> 2017-02-05 20:31 GMT+01:00 <pa...@fr...>:
> > Hi all
> >
> > I'm trying to understand how valgrind resolves replacement
> > functions at runtime.
>
> Hi Paul,
> Have a look at pub_tool_redir.h, mechanics and Z-encoding rules are
> described there.
Hi Ivo
Thanks for the info. What was confusing me the most was why code that called operator delete(void* ptr, std::size_t) was being detected by an unmodified valgrind as operator delete(void* ptr). Looking at the libstdc++ source this is now obvious:
_GLIBCXX_WEAK_DEFINITION void
operator delete(void* ptr, std::size_t) _GLIBCXX_USE_NOEXCEPT
{
::operator delete (ptr);
}
[and libcxx does the same]
So currently this works because the new functions just wrap the old ones.
A+
Paul
|