|
From: Darryl M. <dar...@ne...> - 2006-05-12 06:10:24
|
I am trying to migrate some code from the old GCC checker to valgrind as part of the learning curve I fired it up over Mozilla. If I interpret (the output at end of email) correctly the system call write() has uninitialized data that is included in the scope of its length, so the kernel maybe expected to perform a read operation on one or more bytes of uninitialised data. But.... this memory was allocated with calloc(), so it was initialised to zero. If it had been allocated with malloc() the warning would make sense. Can I disable this class of error specifically for the calloc() case ? One could argue this should be default behaviour and a -pedantic like option could be added to emit this class of problem. Is it possible to directly manipulate the A and V bits of memcheck from within the program by linking with some sort of valgrind stub library which could communicate with valgrind at runtime. I could do this with Checker GCC. So that I can purposefully invalidate (or validate) an area of memory. In fact this was exactly how the libc stubs of Checker GCC worked, and it is my application library wrapper I wish to port to valgrind. Thanks Darryl ==31294== ==31294== Syscall param write(buf) points to uninitialised byte(s) ==31294== at 0x125A815B: (within /lib64/libpthread-2.3.5.so) ==31294== by 0x136D3BDE: (within /usr/X11R6/lib64/libX11.so.6.2) ==31294== by 0x136B7BEA: (within /usr/X11R6/lib64/libX11.so.6.2) ==31294== by 0x13694F0F: XCheckWindowEvent (in /usr/X11R6/lib64/libX11.so.6.2) ==31294== by 0x1AFA6A0D: nsWindow::OnMotionNotifyEvent(_GtkWidget*, _GdkEventMotion*) (in /data/src/mozilla/widget/src/gtk2/libwidget_gtk2.so) ==31294== by 0x1AFA768F: motion_notify_event_cb(_GtkWidget*, _GdkEventMotion*) (in /data/src/mozilla/widget/src/gtk2/libwidget_gtk2.so) ==31294== by 0x128BAE61: (within /usr/lib64/libgtk-x11-2.0.so.0.600.10) ==31294== by 0x132B927B: g_closure_invoke (in /usr/lib64/libgobject-2.0.so.0.600.6) ==31294== by 0x132C62E9: (within /usr/lib64/libgobject-2.0.so.0.600.6) ==31294== by 0x132C754A: g_signal_emit_valist (in /usr/lib64/libgobject-2.0.so.0.600.6) ==31294== by 0x132C7BC1: g_signal_emit (in /usr/lib64/libgobject-2.0.so.0.600.6) ==31294== by 0x1297F4A7: (within /usr/lib64/libgtk-x11-2.0.so.0.600.10) ==31294== Address 0x14E06A4B is 27 bytes inside a block of size 16384 alloc'd ==31294== at 0x11B211FD: calloc (vg_replace_malloc.c:279) ==31294== by 0x136A814B: XOpenDisplay (in /usr/X11R6/lib64/libX11.so.6.2) ==31294== by 0x12BCCE38: gdk_display_open (in /usr/lib64/libgdk-x11-2.0.so.0.600.10) ==31294== by 0x12BB287D: gdk_display_open_default_libgtk_only (in /usr/lib64/libgdk-x11-2.0.so.0.600.10) ==31294== by 0x128B8944: gtk_init_check (in /usr/lib64/libgtk-x11-2.0.so.0.600.10) ==31294== by 0x128B895B: gtk_init (in /usr/lib64/libgtk-x11-2.0.so.0.600.10) ==31294== by 0x40B86F: main (in /data/src/mozilla/xpfe/bootstrap/seamonkey-bin) |
|
From: Ashley P. <as...@qu...> - 2006-05-12 08:53:48
|
On Fri, 2006-05-12 at 07:10 +0100, Darryl Miles wrote: > But.... this memory was allocated with calloc(), so it was initialised > to zero. If it had been allocated with malloc() the warning would make > sense. Can I disable this class of error specifically for the calloc() > case ? One could argue this should be default behaviour and a -pedantic > like option could be added to emit this class of problem. That is how it should work already, the allocation functions have a "zeroed" bit associated with them, it's set for calloc and not for malloc. As your error is only 27 bytes into 16k and I doubt you are sending 16 of blank data! it's likely that what you copied into the buffer was itself uninitialised. > Is it possible to directly manipulate the A and V bits of memcheck from > within the program by linking with some sort of valgrind stub library > which could communicate with valgrind at runtime. I could do this with > Checker GCC. So that I can purposefully invalidate (or validate) an > area of memory. In fact this was exactly how the libc stubs of Checker > GCC worked, and it is my application library wrapper I wish to port to > valgrind. Have a look in <prefix>/valgrind/memcheck.h, in particular at the VALGRIND_MAKE_READABLE() and VALGRIND_MAKE_NOACCESS() macros. These are a little heavy handed though as they work on both the V and A bits at the same time, I know there was talk of macros that only work on the V bits without affecting the A bits but it's not finished yet. SVN code has more macros of this nature if your serious about it... That said I'm not 100% sure what you are trying to do here, most, *almost all* people get by without needing to manipulate the bits directly, are you sure you are tackling the problem in the right way? Ashley, |
|
From: Darryl M. <dar...@ne...> - 2006-05-12 09:47:55
|
Ashley Pittman wrote: > On Fri, 2006-05-12 at 07:10 +0100, Darryl Miles wrote: > As your error is only 27 bytes into 16k and I doubt you are sending 16 > of blank data! it's likely that what you copied into the buffer was > itself uninitialised. Ah. I did read something about this somewhere (in the docs) but the penny has not hit home that what I am seeing is the result of valgrind able to track where uninitialised data can end up. Then ultimately report it being read with a kernel call. Hmm, this leads me to ask can the diagnostic output also report where the data first came from to end up in the buffer ? A sort of tracking system for copied uninitialised data giving me a trail. Maybe even reporting trails that don't end up getting as far as a system call but thrown around internally. > Have a look in <prefix>/valgrind/memcheck.h, in particular at the > VALGRIND_MAKE_READABLE() and VALGRIND_MAKE_NOACCESS() macros. These are > a little heavy handed though as they work on both the V and A bits at > the same time, I know there was talk of macros that only work on the V > bits without affecting the A bits but it's not finished yet. SVN code > has more macros of this nature if your serious about it... > > That said I'm not 100% sure what you are trying to do here, most, > *almost all* people get by without needing to manipulate the bits > directly, are you sure you are tackling the problem in the right way? Maybe I don't, maybe I still have Checker GCC ways of thinking about the problem of memory checking / bound checking. I have found some info in the documentation from your clue, so I shall play a lot more and maybe even investigate the problems I have found in X11/Xlib and Mozilla. Another difference to GCC Cherker: Some other stuff online I read a few comments that the glibc maintainer isn't too cool with addressing issues that aren't really bugs but STFU patches. While I agree their goal is to provide maximum runtime performance on as many platforms as possible there must be some workable happy medium. Is there any active project to deal with that situation at source, i.e. some form of agreed cooperation of both parties needs. A mechanism to be able to mark symbols/offsets, sizes and initialisation value in a table which is stored in glibc itself but is never used or executed under normal operating conditions. Maybe adding an ELF section is good enough for this. Then we just teach valgrind to look and initialise from the table as necessary. You could even teach the ld.so loader to do the same thing if a magic envvar is set. My current understanding of the workaround is to suppress these messages, which doesn't seem like the same thing as implementing the initialization at runtime. Anyway food for another topic maybe. Thanks for your info, a great help. Darryl L. Miles |
|
From: Ashley P. <as...@qu...> - 2006-05-12 10:00:05
|
On Fri, 2006-05-12 at 10:47 +0100, Darryl Miles wrote: > Ashley Pittman wrote: > > On Fri, 2006-05-12 at 07:10 +0100, Darryl Miles wrote: > > > As your error is only 27 bytes into 16k and I doubt you are sending 16 > > of blank data! it's likely that what you copied into the buffer was > > itself uninitialised. > > Ah. I did read something about this somewhere (in the docs) but the > penny has not hit home that what I am seeing is the result of valgrind > able to track where uninitialised data can end up. Exactly. > Hmm, this leads me to ask can the diagnostic output also report where > the data first came from to end up in the buffer ? A sort of tracking > system for copied uninitialised data giving me a trail. Maybe even > reporting trails that don't end up getting as far as a system call but > thrown around internally. It's an idea that's been banded about but I'm fairly sure there isn't one. Perhaps somebody will correct me here? > <snip> > Anyway food for another topic maybe. I think the thing here is to use suppressions where needed but try to ensure that error reports get properly looked at so they are understood. Performance isn't the only reason to leave the code as it is in places. I can't see the need for suppressions going away any time soon. As you say, another topic entirely. Ashley, |
|
From: Howard C. <hy...@sy...> - 2006-05-12 10:51:13
|
Ashley Pittman wrote: > On Fri, 2006-05-12 at 10:47 +0100, Darryl Miles wrote: > >> Ashley Pittman wrote: >> >>> On Fri, 2006-05-12 at 07:10 +0100, Darryl Miles wrote: >>> >>> As your error is only 27 bytes into 16k and I doubt you are sending 16 >>> of blank data! it's likely that what you copied into the buffer was >>> itself uninitialised. >>> >> Ah. I did read something about this somewhere (in the docs) but the >> penny has not hit home that what I am seeing is the result of valgrind >> able to track where uninitialised data can end up. >> > > Exactly. > > >> Hmm, this leads me to ask can the diagnostic output also report where >> the data first came from to end up in the buffer ? A sort of tracking >> system for copied uninitialised data giving me a trail. Maybe even >> reporting trails that don't end up getting as far as a system call but >> thrown around internally. >> > > It's an idea that's been banded about but I'm fairly sure there isn't > one. Perhaps somebody will correct me here? > Reporting the trail might get pretty annoying. But it would probably be good to note the first read of an uninitialized memory location, instead of just the first time it affects a decision. -- -- Howard Chu Chief Architect, Symas Corp. http://www.symas.com Director, Highland Sun http://highlandsun.com/hyc OpenLDAP Core Team http://www.openldap.org/project/ |
|
From: Paul P. <ppl...@gm...> - 2006-05-12 13:22:02
|
Howard Chu wrote: > Reporting the trail might get pretty annoying. But it would probably > be good to note the first read of an uninitialized memory location, > instead of just the first time it affects a decision. This has been discussed before. See this message and thread: http://sourceforge.net/mailarchive/message.php?msg_id=12007505 |
|
From: Nicholas N. <nj...@cs...> - 2006-05-17 16:09:13
|
On Fri, 12 May 2006, Ashley Pittman wrote: >> Hmm, this leads me to ask can the diagnostic output also report where >> the data first came from to end up in the buffer ? A sort of tracking >> system for copied uninitialised data giving me a trail. Maybe even >> reporting trails that don't end up getting as far as a system call but >> thrown around internally. > > It's an idea that's been banded about but I'm fairly sure there isn't > one. Perhaps somebody will correct me here? We'd love to do it, but we don't know how without huge slow-downs. Nick |
|
From: Julian S. <js...@ac...> - 2006-05-16 11:56:39
|
This is a FAQ, although I can't find it on any of our documentation. Most likely explanation is that V isn't handling uninitialised memory in the way you expect. See here for details http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.machine The short story is that whilst it's true that callocing the buffer gives you a defined buffer, it's what happens after calloc and before the write that matters. Hence: char* p = calloc(...) p[1] = .. some uninitialised value .. write(.., p, ..) will get you the same complaint. Usually, the uninitialised junk in the buffer is as a result of doing assignments to struct-typed lvalues in the buffer. The uninitialised stuff is padding bytes in the struct(s). > Is it possible to directly manipulate the A and V bits of memcheck from > within the program by linking with some sort of valgrind stub library > which could communicate with valgrind at runtime. Naturally. It doesn't even require a stub library. See http://www.valgrind.org/docs/manual/manual-core.html#manual-core.clientreq and http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.clientreqs (you need to read both; read the first URL first). J |