|
From: Maynard J. <may...@us...> - 2010-01-04 18:19:54
|
Hi, I posted a message to the valgrind-users mailing list on this topic last month, but got no reply. Probably should have posted it to valgrind-developers list instead. Hopefully someone on this list can point me in the right direction. When running 'make regtest' on an IBM POWER5 using either valgrind 3.4.1 or 3.5, the memcheck/tests/leak-cycle test fails (actually, all of the memcheck leak tests fail similarly). The bad stderr output that was unexpected was: leaked: 192 bytes in 12 blocks dubious: 0 bytes in 0 blocks reachable: 96 bytes in 6 blocks suppressed: 0 bytes in 0 blocks The expected output is: leaked: 288 bytes in 12 blocks dubious: 0 bytes in 0 blocks reachable: 0 bytes in 6 blocks suppressed: 0 bytes in 0 blocks When I ran this testcase without the '-q' option, I get two leak summaries -- they are not the same. The first one is: ==20677== LEAK SUMMARY: ==20677== definitely lost: 48 bytes in 3 blocks ==20677== indirectly lost: 144 bytes in 9 blocks ==20677== possibly lost: 0 bytes in 0 blocks ==20677== still reachable: 96 bytes in 6 blocks ==20677== suppressed: 0 bytes in 0 blocks and the second is: ==20677== LEAK SUMMARY: ==20677== definitely lost: 64 bytes in 4 blocks ==20677== indirectly lost: 224 bytes in 14 blocks ==20677== possibly lost: 0 bytes in 0 blocks ==20677== still reachable: 0 bytes in 0 blocks ==20677== suppressed: 0 bytes in 0 blocks The second leak summary is correct -- at least, it's what is expected in the leak-cycle.stderr.exp. The leak-cycle test on an Intel Xeon with Valgrind 3.5 passes. And when I run it without the '-q' option on Intel, both leak summaries are the same. So apparently, the problem I'm seeing is ppc64-specific. Can anyone give me some guidance on where to start to look for the problem? Thanks. -Maynard |
|
From: Julian S. <js...@ac...> - 2010-01-04 20:57:43
|
> When running 'make regtest' on an IBM POWER5 using either valgrind 3.4.1 or
> 3.5, the memcheck/tests/leak-cycle test fails (actually, all of the
> memcheck leak tests fail similarly). The bad stderr output that was
> unexpected was:
>
> leaked: 192 bytes in 12 blocks
> dubious: 0 bytes in 0 blocks
> reachable: 96 bytes in 6 blocks
> suppressed: 0 bytes in 0 blocks
>
> The expected output is:
>
> leaked: 288 bytes in 12 blocks
> dubious: 0 bytes in 0 blocks
> reachable: 0 bytes in 6 blocks
> suppressed: 0 bytes in 0 blocks
Timely. I was looking at the same problem on arm-linux just this
morning.
At least for leak-cases.c, which is used for the tests leak-cases
full and leak-cases summary, I observed (as above) that the leak
checker reports a few blocks to be reachable, when in fact they
should be reported as leaked. I believe this to be because it
also considers the values in integer registers to be valid pointers
to blocks, even if the value is just junk left over from a previous
computation. Hence a few "lucky" blocks get considered
still-reachable when they should be considered leaked (lost).
It's arguably a portability bug in leak-cases.c. I'd guess a
similar problem afflicts the other tests too.
To verify this, I changed main() in leak-cases.c to zero out the
caller-saved registers after the call to f(), where all the work
is done. This causes the two tests to pass on arm-linux. I did
not try with the other leak tests yet. The revised version of
main is below, w/ explaination w.r.t caller-saved regs in comments.
I would be interested to hear if a similar hack on ppc64 also fixes
it. The set of caller-saved regs on ppc64-ELF is listed in
docs/internals/register-uses.txt if that's helpful.
J
int main(void)
{
DECLARE_LEAK_COUNTERS;
GET_INITIAL_LEAK_COUNTS;
// Originally, this program did all the work in main(), but on some
// platforms (x86/Darwin and AMD64/Linux with --enable-only32bit) stray
// pointers to supposedly-lost heap blocks were being left on the stack,
// thus making them reachable. Doing the allocations in f() and the leak
// counting in main() avoids the problem.
f();
// Zero out all the caller-saved registers, so we don't inadvertantly
// inherit roots in caller-saved registers that were written by f().
// We don't need to zero out the callee-saved registers, because
// by definition they must have the same value they had before the
// call to f(), and so can't hold any pointers created by f().
__asm__ __volatile__(
"mov r0, #0" "\n"
"mov r1, #0" "\n"
"mov r2, #0" "\n"
"mov r3, #0" "\n"
"mov r12, #0" "\n"
: : : /*trash*/"r0", "r1", "r2", "r3", "r12"
);
GET_FINAL_LEAK_COUNTS;
PRINT_LEAK_COUNTS(stderr);
return 0;
}
>
> When I ran this testcase without the '-q' option, I get two leak summaries
> -- they are not the same. The first one is:
>
> ==20677== LEAK SUMMARY:
> ==20677== definitely lost: 48 bytes in 3 blocks
> ==20677== indirectly lost: 144 bytes in 9 blocks
> ==20677== possibly lost: 0 bytes in 0 blocks
> ==20677== still reachable: 96 bytes in 6 blocks
> ==20677== suppressed: 0 bytes in 0 blocks
>
> and the second is:
>
> ==20677== LEAK SUMMARY:
> ==20677== definitely lost: 64 bytes in 4 blocks
> ==20677== indirectly lost: 224 bytes in 14 blocks
> ==20677== possibly lost: 0 bytes in 0 blocks
> ==20677== still reachable: 0 bytes in 0 blocks
> ==20677== suppressed: 0 bytes in 0 blocks
>
> The second leak summary is correct -- at least, it's what is expected in
> the leak-cycle.stderr.exp.
>
> The leak-cycle test on an Intel Xeon with Valgrind 3.5 passes. And when I
> run it without the '-q' option on Intel, both leak summaries are the same.
> So apparently, the problem I'm seeing is ppc64-specific. Can anyone give
> me some guidance on where to start to look for the problem?
>
> Thanks.
> -Maynard
>
>
> ---------------------------------------------------------------------------
>--- This SF.Net email is sponsored by the Verizon Developer Community
> Take advantage of Verizon's best-in-class app development support
> A streamlined, 14 day to market process makes app distribution fast and
> easy Join now and get one step closer to millions of Verizon customers
> http://p.sf.net/sfu/verizon-dev2dev
> _______________________________________________
> Valgrind-developers mailing list
> Val...@li...
> https://lists.sourceforge.net/lists/listinfo/valgrind-developers
|
|
From: Maynard J. <may...@us...> - 2010-01-05 20:27:49
|
Julian Seward wrote:
>> When running 'make regtest' on an IBM POWER5 using either valgrind 3.4.1 or
>> 3.5, the memcheck/tests/leak-cycle test fails (actually, all of the
>> memcheck leak tests fail similarly). The bad stderr output that was
>> unexpected was:
>>
>> leaked: 192 bytes in 12 blocks
>> dubious: 0 bytes in 0 blocks
>> reachable: 96 bytes in 6 blocks
>> suppressed: 0 bytes in 0 blocks
>>
>> The expected output is:
>>
>> leaked: 288 bytes in 12 blocks
>> dubious: 0 bytes in 0 blocks
>> reachable: 0 bytes in 6 blocks
>> suppressed: 0 bytes in 0 blocks
>
> Timely. I was looking at the same problem on arm-linux just this
> morning.
>
> At least for leak-cases.c, which is used for the tests leak-cases
> full and leak-cases summary, I observed (as above) that the leak
> checker reports a few blocks to be reachable, when in fact they
> should be reported as leaked. I believe this to be because it
> also considers the values in integer registers to be valid pointers
> to blocks, even if the value is just junk left over from a previous
> computation. Hence a few "lucky" blocks get considered
> still-reachable when they should be considered leaked (lost).
>
> It's arguably a portability bug in leak-cases.c. I'd guess a
> similar problem afflicts the other tests too.
>
> To verify this, I changed main() in leak-cases.c to zero out the
> caller-saved registers after the call to f(), where all the work
> is done. This causes the two tests to pass on arm-linux. I did
> not try with the other leak tests yet. The revised version of
> main is below, w/ explaination w.r.t caller-saved regs in comments.
>
> I would be interested to hear if a similar hack on ppc64 also fixes
> it. The set of caller-saved regs on ppc64-ELF is listed in
> docs/internals/register-uses.txt if that's helpful.
Julian,
Yes, a similar hack fixed the three leak testcases that I was seeing the problem with. Thank you! Here's the ppc-specific code I used to zero-out the caller-save regs.
__asm__ __volatile__( "li 3, 0" );
__asm__ __volatile__( "li 4, 0" );
__asm__ __volatile__( "li 5, 0" );
__asm__ __volatile__( "li 6, 0" );
__asm__ __volatile__( "li 7, 0" );
__asm__ __volatile__( "li 8, 0" );
__asm__ __volatile__( "li 9, 0" );
__asm__ __volatile__( "li 10, 0" );
__asm__ __volatile__( "li 11, 0" );
__asm__ __volatile__( "li 12, 0" );
We could create arch-specific functions in the testcases to zero-out these regs, and calling the functions would be conditioned by appropriate #ifdefs.
-Maynard
>
> J
>
>
> int main(void)
> {
> DECLARE_LEAK_COUNTERS;
>
> GET_INITIAL_LEAK_COUNTS;
>
> // Originally, this program did all the work in main(), but on some
> // platforms (x86/Darwin and AMD64/Linux with --enable-only32bit) stray
> // pointers to supposedly-lost heap blocks were being left on the stack,
> // thus making them reachable. Doing the allocations in f() and the leak
> // counting in main() avoids the problem.
> f();
>
> // Zero out all the caller-saved registers, so we don't inadvertantly
> // inherit roots in caller-saved registers that were written by f().
> // We don't need to zero out the callee-saved registers, because
> // by definition they must have the same value they had before the
> // call to f(), and so can't hold any pointers created by f().
> __asm__ __volatile__(
> "mov r0, #0" "\n"
> "mov r1, #0" "\n"
> "mov r2, #0" "\n"
> "mov r3, #0" "\n"
> "mov r12, #0" "\n"
> : : : /*trash*/"r0", "r1", "r2", "r3", "r12"
> );
>
> GET_FINAL_LEAK_COUNTS;
>
> PRINT_LEAK_COUNTS(stderr);
>
> return 0;
> }
>
>
>
>
>> When I ran this testcase without the '-q' option, I get two leak summaries
>> -- they are not the same. The first one is:
>>
>> ==20677== LEAK SUMMARY:
>> ==20677== definitely lost: 48 bytes in 3 blocks
>> ==20677== indirectly lost: 144 bytes in 9 blocks
>> ==20677== possibly lost: 0 bytes in 0 blocks
>> ==20677== still reachable: 96 bytes in 6 blocks
>> ==20677== suppressed: 0 bytes in 0 blocks
>>
>> and the second is:
>>
>> ==20677== LEAK SUMMARY:
>> ==20677== definitely lost: 64 bytes in 4 blocks
>> ==20677== indirectly lost: 224 bytes in 14 blocks
>> ==20677== possibly lost: 0 bytes in 0 blocks
>> ==20677== still reachable: 0 bytes in 0 blocks
>> ==20677== suppressed: 0 bytes in 0 blocks
>>
>> The second leak summary is correct -- at least, it's what is expected in
>> the leak-cycle.stderr.exp.
>>
>> The leak-cycle test on an Intel Xeon with Valgrind 3.5 passes. And when I
>> run it without the '-q' option on Intel, both leak summaries are the same.
>> So apparently, the problem I'm seeing is ppc64-specific. Can anyone give
>> me some guidance on where to start to look for the problem?
>>
>> Thanks.
>> -Maynard
>>
>>
>> ---------------------------------------------------------------------------
>> --- This SF.Net email is sponsored by the Verizon Developer Community
>> Take advantage of Verizon's best-in-class app development support
>> A streamlined, 14 day to market process makes app distribution fast and
>> easy Join now and get one step closer to millions of Verizon customers
>> http://p.sf.net/sfu/verizon-dev2dev
>> _______________________________________________
>> Valgrind-developers mailing list
>> Val...@li...
>> https://lists.sourceforge.net/lists/listinfo/valgrind-developers
>
>
|
|
From: Julian S. <js...@ac...> - 2010-01-05 21:08:20
|
> Yes, a similar hack fixed the three leak testcases that I was seeing the > problem with. Well, good. However .. > __asm__ __volatile__( "li 3, 0" ); > __asm__ __volatile__( "li 4, 0" ); > __asm__ __volatile__( "li 5, 0" ); > __asm__ __volatile__( "li 6, 0" ); > __asm__ __volatile__( "li 7, 0" ); > __asm__ __volatile__( "li 8, 0" ); > __asm__ __volatile__( "li 9, 0" ); > __asm__ __volatile__( "li 10, 0" ); > __asm__ __volatile__( "li 11, 0" ); > __asm__ __volatile__( "li 12, 0" ); ehm .. don't you need to tell gcc that the asms trash those regs? Otherwise it has no way to know that. If the program doesn't segfault as-is it's only by luck, in that there are no live values in those regs. Viz: __asm__ __volatile__( "li 3, 0" : : :/*trash*/"r3" ); etc. J |
|
From: Maynard J. <may...@us...> - 2010-01-06 16:04:02
|
Julian Seward wrote: >> Yes, a similar hack fixed the three leak testcases that I was seeing the >> problem with. > > Well, good. However .. > >> __asm__ __volatile__( "li 3, 0" ); >> __asm__ __volatile__( "li 4, 0" ); >> __asm__ __volatile__( "li 5, 0" ); >> __asm__ __volatile__( "li 6, 0" ); >> __asm__ __volatile__( "li 7, 0" ); >> __asm__ __volatile__( "li 8, 0" ); >> __asm__ __volatile__( "li 9, 0" ); >> __asm__ __volatile__( "li 10, 0" ); >> __asm__ __volatile__( "li 11, 0" ); >> __asm__ __volatile__( "li 12, 0" ); > > ehm .. don't you need to tell gcc that the asms trash those regs? > Otherwise it has no way to know that. If the program doesn't > segfault as-is it's only by luck, in that there are no live values > in those regs. Viz: > > __asm__ __volatile__( "li 3, 0" : : :/*trash*/"r3" ); heh, yeah. I'll freely admit that assembly-level coding ain't my strong suit. I discussed this with our gcc team lead, and he agreed the "trash" business is necessary. I added it to the leak testcases, and they passed. So here's the revised ppc asm code: __asm__ __volatile__( "li 3, 0" : : :/*trash*/"r3" ); __asm__ __volatile__( "li 4, 0" : : :/*trash*/"r4" ); __asm__ __volatile__( "li 5, 0" : : :/*trash*/"r5" ); __asm__ __volatile__( "li 6, 0" : : :/*trash*/"r6" ); __asm__ __volatile__( "li 7, 0" : : :/*trash*/"r7" ); __asm__ __volatile__( "li 8, 0" : : :/*trash*/"r8" ); __asm__ __volatile__( "li 9, 0" : : :/*trash*/"r9" ); __asm__ __volatile__( "li 10, 0" : : :/*trash*/"r10" ); __asm__ __volatile__( "li 11, 0" : : :/*trash*/"r11" ); __asm__ __volatile__( "li 12, 0" : : :/*trash*/"r12" ); -Maynard > > etc. > > J |