If one tries to build and install VirtualBox Guest Additions on a Linux that has kernel with enabled support for code coverage profiling, kernel oops may occur as a result of NULL pointer dereference.
First of all, I do not think this is a problem in VirtualBox. I cannot say either, whether Linux kernel developers will change the implementation of coverage profiling so as to avoid such problems. The current implementation is quite reasonable anyway.
So my goal here is to describe the problem and possible workarounds. Perhaps, someone will find it useful.
The problem shows up at least with VirtualBox 3.2.12. I have not tried version 4.0 yet.
Guest OS: OpenSuSE 11.3 (32 bit) kernel: 2.6.34.7-0.5-default rebuilt with support for coverage analysis enabled, to be exact, with CONFIG_GCOV_KERNEL=y and CONFIG_GCOV_PROFILE_ALL=y in the config file.
When I try to install Guest Additions on this system as usual, the kernel modules (vboxguest.ko, vboxsf.ko) also build with coverage support enabled, which is OK. But when the installer script tries to load vboxsf module, kernel oops occurs due to a NULL pointer dereference in gcov_info_is_compatible(). This function is eventually called when some of the constructors of vboxsf kernel module are executed (these constructors are placed in the module automatically by GCC and should not be confused with the module's init function).
The analysis has shown the following. Gcov support subsystem in the kernel relies on the paths to the .gcda files for the object files created when the modules was built. For example, "/tmp/vbox.0/.tmp_GenericRequest.gcda" probably corresponds to "/tmp/vbox.0/GenericRequest.o" in case of vboxguest and vboxsf modules.
By default, vboxguest and vboxsf are built using the same temporary build directory ("/tmp/vbox.0") which is removed after build of a given module is complete. Each of the modules needs GenericRequest.c and hence, "/tmp/vbox.0/GenericRequest.o" and "/tmp/vbox.0/.tmp_GenericRequest.gcda" will be created for each of the modules - and then removed along with /tmp/vbox.0. So far so good.
Now suppose the install or service script loads vboxguest.ko. Gcov subsystem will add information about each of its object files to the internal list including the data for "/tmp/vbox.0/.tmp_GenericRequest.gcda". The kernel also keeps the information about the modules that have been inloaded. The appropriate nodes of that list store the pointer for this information in their 'ghost' or 'unloaded_info' fields. For the modules that are still loaded, these fields are NULL.
Now the system tries to load vboxsf. When its constructors are executed, the system sees that the module uses "/tmp/vbox.0/.tmp_GenericRequest.gcda" for coverage data. The system searches through the list for the corresponding node - and finds the node created for this path when vboxguest was loaded! In such situations, it assumes that vboxguest has already been unloaded. It does not take into account that both modules just use the same path for some of their object files in the build trees. So the system assumes that the old information is in node->ghost (or node->unloaded_info in newer kernels) and tries to merge it with the new data. As node->ghost is NULL, the oops happens.
There could be several workarounds for this, for example:
1. Do not set CONFIG_GCOV_PROFILE_ALL to 'y' when configuring the kernel but rather enable coverage profiling only for the modules you are interested in (see Documentation/gcov.txt in the kernel sources). This is straightforward but may require a lot of work if you need to check code coverage for many modules.
2. Unpack the sources of Guest Additions and explicitly disable coverage profiling for its kernel modules (set GCOV_PROFILE := n in the Makefiles). Might work but I have not tried this yet.
3. The most reliable way would probably be to unpack the sources of Guest Additions and build each of the kernel modules in a separate directory.
I hope this information will be useful.