From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 841 invoked by alias); 26 Mar 2009 20:00:25 -0000 Received: (qmail 32041 invoked by uid 48); 26 Mar 2009 20:00:08 -0000 Date: Thu, 26 Mar 2009 22:58:00 -0000 Message-ID: <20090326200008.32040.qmail@sourceware.org> From: "dsmith at redhat dot com" To: systemtap@sources.redhat.com In-Reply-To: <20090311164601.9940.fche@redhat.com> References: <20090311164601.9940.fche@redhat.com> Reply-To: sourceware-bugzilla@sourceware.org Subject: [Bug runtime/9940] double calling double calling of uprobes in shared libraries X-Bugzilla-Reason: AssignedTo Mailing-List: contact systemtap-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: systemtap-owner@sourceware.org X-SW-Source: 2009-q1/txt/msg00929.txt.bz2 ------- Additional Comments From dsmith at redhat dot com 2009-03-26 20:00 ------- After debugging this a bit, I may see what is going on. The uprobes code asks the task_finder to notify it about vma changes (by setting the vma_callback). So, the task_finder does notify it - about all vma changes. Here's a longish description of what is going on: If you strace Mark's new testcase, you'll see this. execve("./uprobes_exe", ["uprobes_exe"], [/* 39 vars */]) = 0 ... open("./libuprobes_lib.so", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300\4\0\0\0\0\0\0@"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0775, st_size=7493, ...}) = 0 ... mmap(NULL, 2099320, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x110000 mprotect(0x111000, 2093056, PROT_NONE) = 0 mmap(0x310000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x310000 close(3) = 0 ... If you looked at /proc/PID/maps before the mprotect() call, you'd see something like this (with some extra info deleted): vm_start-vm_end flags vm_pgoff path 00110000-00311000 r-xp 00000000 ./libuprobes_lib.so (1) At this point, the task_finder will call the vm_callback, stap_uprobe_vmchange_found() with map_p=1. stap_uprobe_vmchange_found() will call stap_uprobe_change() which registers the first uprobe. If you looked at /proc/PID/maps after the mprotect() and 2nd mmap() calls, you'd see something like this (with some extra info deleted): vm_start-vm_end flags vm_pgoff path 00110000-00111000 r-xp 00000000 ./libuprobes_lib.so 00111000-00310000 ---p 00001000 ./libuprobes_lib.so 00310000-00311000 r-xp 00200000 ./libuprobes_lib.so The former 1 mmap area has been split into 3 areas. The task_finder will make several vm_callbacks here: (2) It calls the vm_callback with map_p=0 to let the callback know the original vma is gone. The stap_uprobe_vmchange_found() function is called with map_p=0. Because of a bug in the task_finder, in this case path is NULL, so stap_uprobe_vmchange_found() exits early and stap_uprobe_change() isn't called. This means the uprobe isn't unregistered. (3-5) It calls the vm_callback with map_p=1 3 times to let the callback know of the 3 new vmas. On the first callback, the uprobe gets re-registered by stap_uprobe_vmchange_found()/stap_uprobe_change(). Note that even if the path was correct in step (2), stap_uprobe_change() never unregisters uprobes so we'd still have a duplicate uprobe (because of bug #6829). I'm unsure of the best way to proceed here. -- http://sourceware.org/bugzilla/show_bug.cgi?id=9940 ------- You are receiving this mail because: ------- You are the assignee for the bug, or are watching the assignee.