|
From: Robert <val...@uu...> - 2007-10-04 15:32:46
|
When a program calls dlopen() and then dlclose(), valgrind forgets the shared library's objects: --32281-- Discarding syms at 0x6724000-0x67C4000 in /usr/lib/libglib-2.0.so.0.1400.1 due to munmap() When it then comes to printing stack traces at the end of program execution, it displays '???' instead of the function names and source code filename and line, because it has discarded those symbols when program called dlclose(). This makes valgrinding of stuff like freeradius modules (or xmms modules) a bit of pain, because the main program always unloads the modules before exiting. Because memory leaks are reported after the program terminates, all the symbols will be well forgotten by then. I'm thinking of implementing a feature that would not only store function's addresses in a stack backtrace, but also this handy information about function name and source code location. Is it possible for you guys to implement it? I have never worked with valgrind code before, can you point me to where I should hack into to add this information? -- Robert |
|
From: Nicholas N. <nj...@cs...> - 2007-10-05 01:23:12
|
On Thu, 4 Oct 2007, Robert wrote: > When a program calls dlopen() and then dlclose(), valgrind forgets the shared > library's objects: > > --32281-- Discarding syms at 0x6724000-0x67C4000 in /usr/lib/libglib-2.0.so.0.1400.1 due to munmap() > > When it then comes to printing stack traces at the end of program execution, > it displays '???' instead of the function names and source code filename and > line, because it has discarded those symbols when program called dlclose(). > > This makes valgrinding of stuff like freeradius modules (or xmms modules) a > bit of pain, because the main program always unloads the modules before > exiting. Because memory leaks are reported after the program terminates, all > the symbols will be well forgotten by then. > > I'm thinking of implementing a feature that would not only store function's > addresses in a stack backtrace, but also this handy information about function > name and source code location. Is it possible for you guys to implement it? > I have never worked with valgrind code before, can you point me to where I > should hack into to add this information? The code for getting stack traces (ie. stacks of code addresses) is in coregrind/m_stacktrace.c. The code for getting file/function names and line numbers is in coregrind/m_debuginfo/debuginfo.c (see also coregrind/m_debuginfo/README.txt). I don't think it would be too hard to do this. The reason we've never done it is that a *lot* of stack traces get recorded -- eg. one for every heap block allocated, in Memcheck -- but only a few ever get shown to the user. If you look up the debuginfo when the traces are obtained, it will be a lot slower (debuginfo lookup isn't that fast, I don't think) and the traces will use a lot more space. At least, that's what I expect, it would be interesting to hear if you find otherwise! Nick |
|
From: Howard C. <hy...@sy...> - 2007-10-05 06:04:57
|
Nicholas Nethercote wrote: > On Thu, 4 Oct 2007, Robert wrote: > >> When a program calls dlopen() and then dlclose(), valgrind forgets the shared >> library's objects: >> >> --32281-- Discarding syms at 0x6724000-0x67C4000 in /usr/lib/libglib-2.0.so.0.1400.1 due to munmap() >> >> When it then comes to printing stack traces at the end of program execution, >> it displays '???' instead of the function names and source code filename and >> line, because it has discarded those symbols when program called dlclose(). >> >> This makes valgrinding of stuff like freeradius modules (or xmms modules) a >> bit of pain, because the main program always unloads the modules before >> exiting. Because memory leaks are reported after the program terminates, all >> the symbols will be well forgotten by then. >> >> I'm thinking of implementing a feature that would not only store function's >> addresses in a stack backtrace, but also this handy information about function >> name and source code location. Is it possible for you guys to implement it? >> I have never worked with valgrind code before, can you point me to where I >> should hack into to add this information? > > The code for getting stack traces (ie. stacks of code addresses) is in > coregrind/m_stacktrace.c. The code for getting file/function names and line > numbers is in coregrind/m_debuginfo/debuginfo.c (see also > coregrind/m_debuginfo/README.txt). Is it a good idea to expand the storage for stack traces like this? It may be better to checkpoint the shared object information on dlopen/dlclose events, and just record that "this block of stack traces was obtained when some set of shared objects were present." > I don't think it would be too hard to do this. The reason we've never done > it is that a *lot* of stack traces get recorded -- eg. one for every heap > block allocated, in Memcheck -- but only a few ever get shown to the user. > If you look up the debuginfo when the traces are obtained, it will be a lot > slower (debuginfo lookup isn't that fast, I don't think) and the traces will > use a lot more space. At least, that's what I expect, it would be > interesting to hear if you find otherwise! Right, this seems like it would really kill both in terms of memory usage and execution time. -- -- Howard Chu Chief Architect, Symas Corp. http://www.symas.com Director, Highland Sun http://highlandsun.com/hyc/ Chief Architect, OpenLDAP http://www.openldap.org/project/ |
|
From: Julian S. <js...@ac...> - 2007-10-05 09:29:23
|
> > The code for getting stack traces (ie. stacks of code addresses) is in > > coregrind/m_stacktrace.c. The code for getting file/function names and > > line numbers is in coregrind/m_debuginfo/debuginfo.c (see also > > coregrind/m_debuginfo/README.txt). > > Is it a good idea to expand the storage for stack traces like this? I agree; expanding to function names would really trash performance. A checkpointing scheme might be better. Something like how svn works. Each time modules are loaded/unloaded, a "debuginfo version number" is incremented. When a stack trace is made, the current version number is stored in the trace. m_debuginfo remembers all debug info that was ever loaded, so it can convert a raw trace with any valid version number to file/function names at any point in the future. It would need a bit of sophistication though. Some programs repeatedly dlopen/dlclose the same object, it gets mapped at the same address, and we wouldn't want bazillions of copies of the info for that object to clog up memory. Maybe that's a refinement though. If you want to have a go at this (which, btw, is a longstanding complaint by many users): - the debug info for each shared object is stored in on struct _SegInfo (misleading historical name), see m_debuginfo/m_storage.h. - the top level structure of the debuginfo is simply a linked list of struct _SegInfo, whose root is at segInfo_list (see debuginfo.c) - when a module is mapped, a new SegInfo is created for it and added to the list, and removed when it is unmapped So if you can come up with some way of having a "versioned" variant of segInfo_list, that would be a good first step towards solving the problem. J |
|
From: Robert <val...@uu...> - 2007-10-05 09:35:06
|
Thu, Oct 04, 2007 at 11:02:34PM -0700 -- Howard Chu wrote: >Is it a good idea to expand the storage for stack traces like this? It may be >better to checkpoint the shared object information on dlopen/dlclose events, >and just record that "this block of stack traces was obtained when some set of >shared objects were present." Yes, it's definitely better to do it this way. Ideally only changes of the objects should be stored, giving a "symbol object version number". Then, for each stack trace generated, we'd store an additional integer saying from which version of symbol table it came from. I'll have a look at the code and see if I can do it. I'll let you know around next week the latest whether I succeeded (with my patch attached) or not. Thanks -- Robert |
|
From: Robert <val...@uu...> - 2007-10-10 11:02:58
|
OK, I created an alfa version of my patch that fixes the issue. See post on valgrind-developers with subject "Remembering symbols of dynamically (un)loaded objects". -- Robert |