[Patch] Losing many samples when profiling multiple JVMs

大平怜 <[email protected]>
Newsgroups gmane.linux.oprofile
Message-ID <CAERM-PgKHj7y9nFEsGROOsYs=BB6+LfMTfPu2Pe4ExjHV1wdSQ@mail.gmail.com>
Hi,

I found when profiling multiple JVMs, many samples that should have hit
JITted methods were lost due to no permanent mapping. This was because
OProfile did not have correct operf_mmap for the JITted code anon regions
of some of the JVMs. This error can happen as follows:

(1) __handle_mmap_event() creates a new operf_mmap for a small anon region
of a JVM.
(2) When another JVM happens to allocate its anon region at the same
starting virtual address but with a larger size, __handle_mmap_event()
first searches all_images_map.
(3) __handle_mmap_event() finds the previously created operf_mmap in
all_images_map and reuses it, because it checks only filename and
start_addr.
(4) As a result, when a sample hits a JITted method that was generated
between the incorrect end_addr and the actual end
address, __get_operf_trans() cannot find an appropriate mapping.

The root cause of this problem is that __handle_mmap_event() does not check
end_addr when searching all_images_map. This should work for a normal file,
which should have the same size when mapped to different processes, but not
for anon regions, which can have different sizes in different processes.
The attached patch will add this check.

More fundamentally, I am wondering what the purpose of all_images_region
is. I guess it is to reuse operf_mmap structures for more than one
processes. The file names in all_images_map are stored in absolute paths,
but they are compared against a file base name in __handle_mmap_event(). As
a result, this comparison succeeds only for anon and [vdso]. Is this
intended behavior?


Regards,
Rei Odaira

------------------------------------------------------------------------------

_______________________________________________
oprofile-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/oprofile-list
oprofile_check_end_addr.patch (application/octet-stream, 701 B)
diff --git a/libperf_events/operf_utils.cpp b/libperf_events/operf_utils.cpp
index 90a0765..4fc255a 100644
--- a/libperf_events/operf_utils.cpp
+++ b/libperf_events/operf_utils.cpp
@@ -275,7 +275,8 @@ static void __handle_mmap_event(event_t * event)
 	range = all_images_map.equal_range(image_basename);
 	for (it = range.first; it != range.second; it++) {
 		if (((strcmp((*it).second->filename, image_basename.c_str())) == 0)
-				&& ((*it).second->start_addr == event->mmap.start)) {
+				&& ((*it).second->start_addr == event->mmap.start)
+				&& (*it).second->end_addr == (event->mmap.len == 0ULL ? 0ULL : mapping->start_addr + event->mmap.len - 1)) {
 			mapping = (*it).second;
 			break;
 		}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.