In the past few days, I’ve been playing with icegrind, a little valgrind plugin that Taras Glek wrote to investigate how Firefox startup spends its time in libxul.so reading/initialization, mostly. I invite you to check out his various posts on the subject, it’s an interesting read.
After some fiddling with the original icegrind patch in the bug linked above, I got some better understanding on the binary initialization phase (more on that in another post), as we could call it, and hit some problems due to problems in icegrind and elflog. The latest version of the icegrind patch as of writing solved my main problem half way (though it needs further modifications to work properly, see below).
What icegrind actually does is to track memory accesses in mmap()ed memory. When the program being profiled mmap()s a file, icegrind looks for a corresponding “sections” file next to it (e.g. “libxul.so.sections” for “libxul.so”). The “sections” file contains offsets, sizes, and sections names, that will be used by icegrind to report the accesses. Whenever the profiled program makes memory accesses (whether it is for instructions or data) within the mmap()ed range, icegrind will add the corresponding section name in a “log” file (e.g. “libxul.so.log” for “libxul.so”). Please note it will only do so for the first access in the given section.
To generate section information for ELF files, Taras also hacked an elflog program that scans an ELF binary (program or library) and will output sections for symbols present in its symtab. This means the binary needs not to be stripped, though the full fledged debugging symbols are not needed. It outputs the sections names in a form that would be reusable in a linker script after a build with the “-ffunction-sections” and “-fdata-sections” compiler options, but that’s mostly irrelevant when what you are after is only to see what is going on, not to reorder the sections at link time. There are glitches in the way elflog works that makes the section names for .bss symbols wrong (they will start with .symtab, .shstrtab, .comment, etc. instead of .bss). Also, technically, the .bss section is not mapped from the file.
Note icegrind has rough edges, is still experimental, and isn’t very user friendly, as in unix permissions, because its input and output files need to be next to the file being mmap()ed, and when that is a library in /usr/lib, well, you need write access there ; or you need to copy the library in a different directory and adjust LD_LIBRARY_PATH. Anyways, it’s already useful as it currently is.
If you want to play with it yourself, here are steps that worked well for me:
svn co svn://svn.valgrind.org/valgrind/trunk valgrind -r 11100
When I first tried icegrind, valgrind trunk was broken ; revision 11100 is known to work properly, at least for icegrind.
wget -O - -q https://bug549749.bugzilla.mozilla.org/attachment.cgi?id=449748 | patch -p0
You need to open
icegrind/ice_main.c, go on the last line of the
track_mmapfunction and replace
mkdir icegrind/tests ; touch icegrind/tests/Makefile.am
The valgrind build system is a bit lunatic.
libtoolize ; aclocal ; automake --add-missing ; autoreconf
g++ -o elflog elflog.cpp -lelf
You will need the
make install ; install -m 755 elflog /usr/local/bin
as root, to install in
Once you’re done with this setup, you are ready to start playing:
elflog --contents libxul.so > libxul.so.sections
Be aware that if libxul.so is a symbolic link pointing to a file in another directory, as it happens in the dist/bin directory in mozilla builds, the “sections” file needs to be in that other directory.
LD_LIBRARY_PATH=. valgrind --tool=icegrind ./firefox-bin -P my-profile -no-remote about:blank
Obviously, you don’t have to play around with Firefox. You can try with other libraries, or even programs. You’ll see in a subsequent post, however, that to get more interesting information, the elflog output is unfortunately not enough.