Uprobes Patches:
Subsystems (11)
v6 cover Uprobes Patches:
Uprobes Patches
Changelog from V5:
- Merged user_bkpt and user_bkpt_xol into uprobes.
- Addressed comments till now.
Changelog from V4:
- Rebased to tip tree. (2.6.35-rc3-tip)
Changelog from v3:
- Reverted to background page replacement as suggested by Peter Zijlstra.
- Dso in 'perf probe' can be either be a short name or a absolute path.
- Addressed comments from Masami, Frederic, Steven on traceevents and perf
Changelog from v2:
- Addressed comments from Oleg, including removal of interrupt context handlers, reverting background page replacement in favour of access_process_vm().
- Provides perf interface for uprobes.
Changelog from v1:
- Added trace_event interface for uprobes.
- Addressed comments from Andrew Morton and Randy Dunlap.
For previous posting: please refer: http://lkml.org/lkml/2010/6/14/41
http://lkml.org/lkml/2010/3/20/107 and http://lkml.org/lkml/2010/5/18/307
This patchset implements Uprobes which enables you to dynamically break into any routine in a user space application and collect information non-disruptively.
This patchset is a rework based on suggestions from discussions on lkml in January and March 2010 (http://lkml.org/lkml/2010/1/11/92,
http://lkml.org/lkml/2010/1/27/19, http://lkml.org/lkml/2010/3/20/107
and http://lkml.org/lkml/2010/3/31/199 ). This implementation of uprobes doesnt depend on utrace.
When a uprobe is registered, Uprobes makes a copy of the probed instruction, replaces the first byte(s) of the probed instruction with a breakpoint instruction. (Uprobes uses background page replacement mechanism and ensures that the breakpoint affects only that process.)
When a CPU hits the breakpoint instruction, Uprobes gets notified of trap and finds the associated uprobe. It then executes the associated handler. Uprobes single-steps its copy of the probed instruction and resumes execution of the probed process at the instruction following the probepoint. Instruction copies to be single-stepped are stored in a per-process "execution out of line (XOL) area". Currently XOL area is allocated as one page vma.
Advantages of uprobes over conventional debugging include:
1. Non-disruptive.
Unlike current ptrace based mechanisms, uprobes tracing wouldnt involve signals, stopping threads and context switching between the tracer and tracee.
2. Much better handling of multithreaded programs because of XOL. Current ptrace based mechanisms use single stepping inline, i.e they copy back the original instruction on hitting a breakpoint. In such mechanisms tracers have to stop all the threads on a breakpoint hit or tracers will not be able to handle all hits to the location of interest. Uprobes uses execution out of line, where the instruction to be traced is analysed at the time of breakpoint insertion and a copy of instruction is stored at a different location. On breakpoint hit, uprobes jumps to that copied location and singlesteps the same instruction and does the necessary fixups post singlestepping.
3. Multiple tracers for an application.
Multiple uprobes based tracer could work in unison to trace an application. There could one tracer that could be interested in generic events for a particular set of process. While there could be another tracer that is just interested in one specific event of a particular process thats part of the previous set of process.
4. Corelating events from kernels and userspace.
Uprobes could be used with other tools like kprobes, tracepoints or as part of higher level tools like perf to give a consolidated set of events from kernel and userspace. In future we could look at a single backtrace showing application, library and kernel calls.
Here is the list of TODO Items.
- Allowing probes across fork.
- Allowing probes per-executable/per dso.
- Allow multiple probes to share a probepoint.
- Return probes.
- Support for other architectures.
- Uprobes booster.
- Merge uprobes and kprobes trace_event.
- replace macro W with bits in inat table.
Please do provide your valuable comments.
Thanks in advance.
Srikar
Srikar Dronamraju(12)
0: Uprobes Patches
1: mm: Move replace_page() / write_protect_page() to mm/memory.c 2: uprobes: Breakpoint insertion/removal in user space applications. 3: uprobes: Slot allocation for Execution out of line(XOL) 4: uprobes: x86 specific functions for user space breakpointing. 5: uprobes: Uprobes (un)registration and exception handling. 6: uprobes: X86 support for Uprobes
7: uprobes: Uprobes Documentation
8: trace: Extract out common code for kprobes/uprobes traceevents. 9: trace: uprobes trace_event interface
10: perf: Dont adjust symbols on name lookup
11: perf: Re-Add make_absolute_path
12: perf: perf interface for uprobes
Documentation/uprobes.txt | 193 +++++ arch/Kconfig | 6 + arch/x86/Kconfig | 1 + arch/x86/include/asm/thread_info.h | 2 + arch/x86/include/asm/uprobes.h | 43 ++ arch/x86/kernel/Makefile | 2 + arch/x86/kernel/signal.c | 13 + arch/x86/kernel/uprobes.c | 599 ++++++++++++++++ fs/exec.c | 4 + include/linux/mm.h | 4 + include/linux/mm_types.h | 4 + include/linux/sched.h | 3 + include/linux/uprobes.h | 334 +++++++++ kernel/Makefile | 1 + kernel/fork.c | 21 + kernel/trace/Kconfig | 20 + kernel/trace/Makefile | 2 + kernel/trace/trace.h | 5 + kernel/trace/trace_kprobe.c | 600 +--------------- kernel/trace/trace_probe.c | 521 ++++++++++++++ kernel/trace/trace_probe.h | 126 ++++ kernel/trace/trace_uprobe.c | 739 +++++++++++++++++++ kernel/uprobes.c | 1396 ++++++++++++++++++++++++++++++++++++ mm/ksm.c | 112 --- mm/memory.c | 120 +++ tools/perf/builtin-probe.c | 13 +- tools/perf/builtin-top.c | 20 - tools/perf/util/abspath.c | 81 +++ tools/perf/util/cache.h | 1 + tools/perf/util/event.c | 20 + tools/perf/util/event.h | 1 + tools/perf/util/probe-event.c | 466 +++++++++---- tools/perf/util/probe-event.h | 37 +- tools/perf/util/probe-finder.c | 20 +- tools/perf/util/probe-finder.h | 6 +- tools/perf/util/symbol.c | 6 +- 36 files changed, 4651 insertions(+), 891 deletions(-)
PATCH v6 1/12 mm: Move replace_page() / write_protect_page() to mm/memory.c
mm: Move replace_page() / write_protect_page() to mm/memory.c
User bkpt will use background page replacement approach to insert/delete breakpoints. Background page replacement approach will be based on replace_page and write_protect_page.
Now replace_page() loses its static attribute.
---
include/linux/mm.h | 4 ++ mm/ksm.c | 112 ------------------------------------------------- mm/memory.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 112 deletions(-)
include/linux/mm.h +4 -0
@@ -858,6 +858,10 @@ void account_page_dirtied(struct page *page, struct address_space *mapping);int set_page_dirty (struct page *page);int set_page_dirty_lock (struct page *page);int clear_page_dirty_for_io (struct page *page); +int replace_page (struct vm_area_struct *vma,struct page *page, +struct page *kpage,pte_t orig_pte); +int write_protect_page (struct vm_area_struct *vma,struct page *page, +pte_t *orig_pte); extern unsigned long move_page_tables(struct vm_area_struct *vma, unsigned long old_addr, struct vm_area_struct *new_vma,
mm/ksm.c +0 -112
118 lines not on this page · raw message
mm/memory.c +120 -0
126 lines not on this page · raw message
PATCH v6 2/12 uprobes: Breakpoint insertion/removal in user space applications.
In reply to Srikar Dronamrajuuprobes: Breakpoint insertion/removal in user space applications.
Changelog from V5: (Merge user_bkpt into uprobes)
* Merged user_bkpt into uprobes as suggested by Christoph Hellwig and Peter Zijlstra.
Changelog from V3: (reimplement background page replacement)
* Replemented background page replacement based on inputs from Peter Zijlstra.
Changelog from v2: (addressing comments from Oleg)
* Use access_process_vm instead of replace_page based background page replacement.
Changelog from v1:
* Use k(un)map_atomic instead of k(un)map.
* Remove BUG_ON.
* Few parameter changes to be more consistent with sparse.
* Added kernel-doc comments whereever necessary.
* Introduce a check to detect if post_xol can sleep.
Provides a mechanism in kernel to insert/remove breakpoints in user space applications including
- architecture independent mechanism to establish breakpoints in userspace applications.
- helper functions for reading/writing/validating data/opcodes from target process's address space.
- wrappers and default implementation(whereever possible) of architecture dependent functions(setting breakpoint)
- preprocessing and postprocessing of singlestep on breakpoint hit
Single stepping inline is the traditional method where original instructions replace the breakpointed instructions on a breakpoint hit. This method works well with single threaded applications. However its racy with multithreaded applications.
In execution out of line, threads single steps on a copy of the instruction. This method works well for both single-threaded and multithreaded applications.
Uprobes uses execution out of line method.
There could be other strategies like emulating an instruction. However they are currently not implemented.
Insertion and removal of breakpoints is by "Background page replacement". i.e make a copy of the page, modify its the contents, set the pagetable and flush the tlbs. This page uses enhanced replace_page to cow the page. Modified page is only reflected for the interested process. Others sharing the page will still see the old copy.
You need to follow this up with the uprobes patch for your architecture to define architecture specific functionality for reading/writing/validating data/opcodes.
---
arch/Kconfig | 14 + include/linux/uprobes.h | 189 +++++++++++++++++++ kernel/Makefile | 1 kernel/uprobes.c | 466 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 670 insertions(+), 0 deletions(-) create mode 100644 include/linux/uprobes.h create mode 100644 kernel/uprobes.c
arch/Kconfig +14 -0
@@ -47,6 +47,17 @@ config OPTPROBES depends on !PREEMPT select KALLSYMS_ALL +config UPROBES + bool "User-space probes (EXPERIMENTAL)" + depends on ARCH_SUPPORTS_UPROBES + depends on MMU + help + Uprobes enables kernel subsystems to establish probepoints + in user applications and execute handler functions when + the probepoints are hit. For more information, refer to + Documentation/uprobes.txt. + If in doubt, say "N". + config HAVE_EFFICIENT_UNALIGNED_ACCESS bool help
@@ -80,6 +91,9 @@ config USER_RETURN_NOTIFIER Provide a kernel-internal notification when a cpu is about to switch to user mode. +config ARCH_SUPPORTS_UPROBES + def_bool n + config HAVE_IOREMAP_PROT bool
include/linux/uprobes.h new file +189 -0
189 lines not on this page · raw message
kernel/Makefile +1 -0
@@ -105,6 +105,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o obj-$(CONFIG_PADATA) += padata.o +obj-$(CONFIG_UPROBES) += uprobes.o ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
kernel/uprobes.c new file +466 -0
466 lines not on this page · raw message
PATCH v6 3/12 uprobes: Slot allocation for Execution out of line(XOL)
In reply to Srikar Dronamrajuuprobes: Slot allocation for Execution out of line(XOL)
Changelog from V5: Merged into uprobes.
Changelog form V3:
* Added a memory barrier after the slot gets initialized.
Changelog from V2: (addressing Oleg's comments)
* Removed code in !CONFIG_UPROBES_XOL
* Functions now pass pointer to uprobes_xol_area instead of pointer to void.
Provides slot allocation mechanism for execution out of line for use with user space breakpointing.
Traditional method of replacing the original instructions on breakpoint hit are racy when used on multithreaded applications.
Alternatives for the traditional method include:
- Emulating the breakpointed instruction.
- Execution out of line.
Emulating the instruction:
This approach would use a in-kernel instruction emulator to
emulate the breakpointed instruction. This approach could be looked in at a later point of time.
Execution out of line:
In execution out of line strategy, a new vma is injected into
the target process, a copy of the instructions which are breakpointed is stored in one of the slots. On breakpoint hit, the copy of the instruction is single-stepped leaving the breakpoint instruction as is. This method is architecture independent.
This method is useful while handling multithreaded processes.
This patch allocates one page per process for slots to be used to copy the breakpointed instructions.
Current slot allocation mechanism:
1. Allocate one dedicated slot per user breakpoint. Each slot is big enuf to accomodate the biggest instruction for that architecture. (16 bytes for x86).
2. We currently allocate only one page for slots. Hence the number of slots is limited to active breakpoint hits on that process.
3. Bitmap to track used slots.
---
include/linux/uprobes.h | 2 kernel/uprobes.c | 283 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 285 insertions(+), 0 deletions(-)
include/linux/uprobes.h +2 -0
@@ -37,6 +37,8 @@ struct user_bkpt_task_arch_info {};struct user_bkpt_arch_info user_bkpt_arch_info;#endif +#define UINSNS_PER_PAGE (PAGE_SIZE/UPROBES_XOL_SLOT_BYTES) +#define MAX_UPROBES_XOL_SLOTS UINSNS_PER_PAGEstruct task_struct ;struct pt_regs ;
kernel/uprobes.c +283 -0
295 lines not on this page · raw message
PATCH v6 4/12 uprobes: x86 specific functions for user space breakpointing.
In reply to Srikar Dronamrajuuprobes: x86 specific functions for user space breakpointing.
Changelog from V5: Merged into uprobes layer.
Changelog from V1:
set UPROBES_FIX_SLEEPY if post_xol might sleep.
Provides x86 specific functions for instruction analysis and instruction validation and x86 specific pre-processing and post-processing of singlestep especially for RIP relative instructions. Uses "x86: instruction decoder API" for validation and analysis of user space instructions. This analysis is used at the time of post-processing of breakpoint hit to do the necessary fix-ups. There is support for breakpointing RIP relative instructions. However there are still few instructions that cannot be singlestepped.
Also defines TIF_UPROBE flag for x86.
This patch requires "x86: instruction decoder API"
http://lkml.org/lkml/2009/6/1/459
---
arch/x86/Kconfig | 1 arch/x86/include/asm/thread_info.h | 2 arch/x86/include/asm/uprobes.h | 43 +++ arch/x86/kernel/Makefile | 2 arch/x86/kernel/uprobes.c | 547 ++++++++++++++++++++++++++++++++++++ 5 files changed, 595 insertions(+), 0 deletions(-) create mode 100644 arch/x86/include/asm/uprobes.h create mode 100644 arch/x86/kernel/uprobes.c
arch/x86/Kconfig +1 -0
@@ -54,6 +54,7 @@ config X86 select HAVE_KERNEL_LZO select HAVE_HW_BREAKPOINT select HAVE_MIXED_BREAKPOINTS_REGS + select ARCH_SUPPORTS_UPROBES select PERF_EVENTS select HAVE_PERF_EVENTS_NMI select ANON_INODES
arch/x86/include/asm/thread_info.h +2 -0
@@ -84,6 +84,7 @@ struct thread_info {#define TIF_SECCOMP 8/* secure computing */ #define TIF_MCE_NOTIFY 10/* notify userspace of an MCE */ #define TIF_USER_RETURN_NOTIFY 11/* notify kernel of userspace return */ +#define TIF_UPROBE 12/* breakpointed or singlestepping */ #define TIF_NOTSC 16/* TSC is not accessible in userland */ #define TIF_IA32 17/* 32bit process */ #define TIF_FORK 18/* ret_from_fork */
@@ -107,6 +108,7 @@ struct thread_info {#define _TIF_SECCOMP (1 << TIF_SECCOMP)#define _TIF_MCE_NOTIFY (1 << TIF_MCE_NOTIFY)#define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY) +#define _TIF_UPROBE (1 << TIF_UPROBE)#define _TIF_NOTSC (1 << TIF_NOTSC)#define _TIF_IA32 (1 << TIF_IA32)#define _TIF_FORK (1 << TIF_FORK)
arch/x86/include/asm/uprobes.h new file +43 -0
43 lines not on this page · raw message
arch/x86/kernel/Makefile +2 -0
@@ -116,6 +116,8 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o +obj-$(CONFIG_UPROBES) += uprobes.o + ### # 64 bit specific files ifeq ($(CONFIG_X86_64),y)
arch/x86/kernel/uprobes.c new file +547 -0
547 lines not on this page · raw message
PATCH v6 5/12 uprobes: Uprobes (un)registration and exception handling.
In reply to Srikar Dronamrajuuprobes: Uprobes (un)registration and exception handling.
Changelog from V5:
- Merged user_bkpt and user_bkpt_xol layers into uprobes.
Changelog from V2:
- Introduce TIF_UPROBE flag.
- uprobes hooks now in fork/exec/exit paths instead of tracehooks.
- uprobe_process is now part of the mm struct and is shared between processes that share the mm.
- per thread information is now allocated on the fly.
* Hence allocation and freeing of this information is lockless.
- find_probept() takes the spinlock; unlike previously when it was expected that the spinlock was taken before calling it.
- For now run the handler in task context. The reasons for this change being.
* utask (per task meta data structure is now allocated on the fly. Hence first request on the thread and first request for the breakpoint have to be anyway allocated in task context.
* Measurements showed task based handler had negligible overhead over interrupt based handlers.
* Feedback from Oleg and few others.
* Feedback at LFCS.
* Simplicity atleast till uprobes stabilizes.
(However we introduce interrupt based handlers at a later time.)
Changelog from v1:
- If fixup might sleep; then do the post singlestep processing in task context.
The uprobes infrastructure enables a user to dynamically establish probepoints in user applications and collect information by executing a handler function when a probepoint is hit.
The user specifies the virtual address and the pid of the process of interest along with the action to be performed. Uprobes uses the execution out of line strategy and follows lazy slot allocation. I.e, on the first probe hit for that process, a new vma (to hold the probed instructions for execution out of line) is allocated. Once allocated, this vma remains for the life of the process, and is reused as needed for subsequent probes. A slot in the vma is allocated for a probepoint when it is first hit.
A slot is marked for reuse only when the probe gets unregistered and there are no threads in the vicinity.
In a multithreaded process, a probepoint once registered is active for all threads of a process. If a thread specific action for a probepoint is required then the handler should be implemented to do the same.
If a breakpoint already exists at a particular address (irrespective of who inserted the breakpoint including uprobes), uprobes will refuse to register any more probes at that address.
You need to follow this up with the uprobes patch for your architecture.
For more information: please refer to Documentation/uprobes.txt
TODO:
1. Allow multiple probes at a probepoint.
2. Booster probes.
3. Allow probes to be inherited across fork.
4. probing function returns.
---
arch/Kconfig | 1 fs/exec.c | 4 include/linux/mm_types.h | 4 include/linux/sched.h | 3 include/linux/uprobes.h | 143 ++++++++++ kernel/fork.c | 21 + kernel/uprobes.c | 653 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 826 insertions(+), 3 deletions(-)
arch/Kconfig +1 -0
@@ -49,6 +49,7 @@ config OPTPROBES config UPROBES bool "User-space probes (EXPERIMENTAL)" + default n depends on ARCH_SUPPORTS_UPROBES depends on MMU help
fs/exec.c +4 -0
@@ -1053,6 +1053,10 @@ void setup_new_exec(struct linux_binprm * bprm)flush_signal_handlers (current,0 );flush_old_files (current->files); +#ifdef CONFIG_UPROBES +if (unlikely (current->utask)) +uprobe_free_utask (current); +#endif }EXPORT_SYMBOL (setup_new_exec);
include/linux/mm_types.h +4 -0
@@ -12,6 +12,7 @@#include <linux/completion.h> #include <linux/cpumask.h> #include <linux/page-debug-flags.h> +#include <linux/uprobes.h> #include <asm/page.h> #include <asm/mmu.h>
@@ -310,6 +311,9 @@ struct mm_struct {#ifdef CONFIG_MMU_NOTIFIER struct mmu_notifier_mm *mmu_notifier_mm;#endif +#ifdef CONFIG_UPROBES +struct uprobe_process *uproc;/* per mm uprobes info */ +#endif };/* Future-safe accessor for struct mm_struct's cpu_vm_mask. */
include/linux/sched.h +3 -0
@@ -1498,6 +1498,9 @@ struct task_struct { unsigned long memsw_bytes; /* uncharged mem+swap usage */ } memcg_batch;#endif +#ifdef CONFIG_UPROBES +struct uprobe_task *utask; +#endif };/* Future-safe accessor for struct task_struct's cpus_allowed. */
include/linux/uprobes.h +143 -0
153 lines not on this page · raw message
kernel/fork.c +21 -0
@@ -187,6 +187,11 @@ void __put_task_struct(struct task_struct *tsk)delayacct_tsk_free (tsk);put_signal_struct (tsk->signal); +#ifdef CONFIG_UPROBES +if (unlikely (tsk->utask)) +uprobe_free_utask (tsk); +#endif +if (!profile_handoff_task (tsk))free_task (tsk); }
@@ -522,6 +527,10 @@ void __mmdrop(struct mm_struct *mm)mm_free_pgd (mm);destroy_context (mm);mmu_notifier_mm_destroy (mm); +#ifdef CONFIG_UPROBES +if (unlikely (mm->uproc)) +uprobe_put_uprocess (mm); +#endif free_mm (mm); }EXPORT_SYMBOL_GPL (__mmdrop);
@@ -680,6 +689,9 @@ struct mm_struct *dup_mm(struct task_struct *tsk)if (mm->binfmt && !try_module_get (mm->binfmt->module)) goto free_pt; +#ifdef CONFIG_UPROBES + mm->uproc =NULL ; +#endif return mm; free_pt:
@@ -1186,6 +1198,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,INIT_LIST_HEAD (&p->pi_state_list); p->pi_state_cache =NULL ;#endif +#ifdef CONFIG_UPROBES + p->utask =NULL ; +#endif /* * sigaltstack should be cleared when sharing the same VM */
@@ -1284,6 +1299,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,proc_fork_connector (p);cgroup_post_fork (p);perf_event_fork (p); +#ifdef CONFIG_UPROBES +if ((current->mm) && !(clone_flags &CLONE_VM )) { +if (unlikely (current->mm->uproc)) +uprobe_handle_fork (p); + } +#endif return p; bad_fork_free_pid:
kernel/uprobes.c +650 -3
696 lines not on this page · raw message
PATCH v6 6/12 uprobes: X86 support for Uprobes
In reply to Srikar Dronamrajuuprobes: X86 support for Uprobes
Changelog from V5: Using local_irq_enable() instead of
native_irq_enable and no more disabling irqs as suggested by Oleg Nesterov.
Provides x86 specific details for uprobes.
This includes interrupt notifier for uprobes, enabling/disabling singlestep.
---
arch/x86/kernel/signal.c | 13 +++++++++++ arch/x86/kernel/uprobes.c | 52 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 0 deletions(-)
arch/x86/kernel/signal.c +13 -0
@@ -848,6 +848,19 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)if (thread_info_flags & _TIF_SIGPENDING)do_signal (regs); +if (thread_info_flags & _TIF_UPROBE) { +clear_thread_flag (TIF_UPROBE ); +#ifdef CONFIG_X86_32 +/* +* On x86_32, do_notify_resume() gets called with +* interrupts disabled. Hence enable interrupts if they +* are still disabled. +*/ +local_irq_enable (); +#endif +uprobe_notify_resume (regs); + } +if (thread_info_flags & _TIF_NOTIFY_RESUME) {clear_thread_flag (TIF_NOTIFY_RESUME );tracehook_notify_resume (regs);
arch/x86/kernel/uprobes.c +52 -0
61 lines not on this page · raw message
PATCH v6 7/12 uprobes: Uprobes Documentation
In reply to Srikar Dronamrajuuprobes: Uprobes Documentation
Changelog from V5: Removed references to Modules, Samples, and
probe Overhead.
Changelog from v3: Updated measurements.
Changelog from v2: Updated measurements.
Changelog from v1: Addressed comments from Randy Dunlap.
: Updated measurements.
---
Documentation/uprobes.txt | 193 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 193 insertions(+), 0 deletions(-) create mode 100644 Documentation/uprobes.txt
Documentation/uprobes.txt new file +193 -0
@@ -0,0 +1,193 @@ +Title : User-Space Probes (Uprobes) +Authors : Jim Keniston <[email protected]> + : Srikar Dronamraju <[email protected]> + +CONTENTS + +1. Concepts: Uprobes +2. Architectures Supported +3. API Reference +4. Uprobes Features and Limitations +5. TODO +6. Uprobes Team + +1. Concepts: Uprobes + +Uprobes enables you to dynamically break into any routine in a +user application and collect debugging and performance information +non-disruptively. You can trap at any code address, specifying a +kernel handler routine to be invoked when the breakpoint is hit. + +A uprobe can be inserted on any instruction in the application's +virtual address space. The registration function register_uprobe() +specifies which process is to be probed, where the probe is to be +inserted, and what handler is to be called when the probe is hit. + +Uprobes-based instrumentation can be packaged as a kernel +module. In the simplest case, the module's init function installs +("registers") one or more probes, and the exit function unregisters +them. + +1.1 How Does a Uprobe Work? + +When a uprobe is registered, Uprobes makes a copy of the probed +instruction, stops the probed application, replaces the first byte(s) +of the probed instruction with a breakpoint instruction (e.g., int3 +on i386 and x86_64), and allows the probed application to continue. +(When inserting the breakpoint, Uprobes uses background page +replacement mechanism, so that the breakpoint affects only that +process, and not any other process running that program. This is +true even if the probed instruction is in a shared library.) + +When a CPU hits the breakpoint instruction, a trap occurs, the CPU's +user-mode registers are saved, and uprobes notifier code finds the +associated uprobe. It then executes the handler associated with the +uprobe, passing the handler the addresses of the uprobe struct and the +saved registers. The handler can run either in interrupt context or in +task context; this is specified by the user at the time of registration. +When run in task context, the handler may block, but keep in mind that +the probed thread remains stopped while your handler runs. + +Next, Uprobes single-steps its copy of the probed instruction and +resumes execution of the probed process at the instruction following +the probepoint. (It would be simpler to single-step the actual +instruction in place, but then Uprobes would have to temporarily +remove the breakpoint instruction. This would create problems in a +multithreaded application. For example, it would open a time window +when another thread could sail right past the probepoint.) + +Instruction copies to be single-stepped are stored in a per-process +"execution out of line (XOL) area," which is a little VM area +created by Uprobes in each probed process's address space. + +Uprobes handles interesting events in the lifetime of the probed +process, such as fork, clone, exec, and exit. + +1.2 Multithreaded Applications + +Uprobes supports the probing of multithreaded applications. Uprobes +imposes no limit on the number of threads in a probed application. +All threads in a process use the same text pages, so every probe +in a process affects all threads; of course, each thread hits the +probepoint (and runs the handler) independently. Multiple threads +may run the same handler simultaneously. If you want a particular +thread or set of threads to run a particular handler, your handler +should check current or current->pid to determine which thread has +hit the probepoint. + +When a process clones a new thread, that thread automatically shares +all current and future probes established for that process. + +2. Architectures Supported + +This user_bkpt based version of Uprobes is implemented on the following +architectures: + +- x86 + +3. API Reference + +The Uprobes API includes a "register" function and an "unregister" +function for uprobes. Here are terse, mini-man-page specifications for +these functions and the associated probe handlers that you'll write. +See the latter half of this document for examples. + +3.1 register_uprobe + +#include <linux/uprobes.h> +int register_uprobe(struct uprobe *u); + +Sets a breakpoint at virtual address u->vaddr in the process whose +pid is u->pid. When the breakpoint is hit, Uprobes calls u->handler. +If u->handler_in_interrupt is set, the handler runs in interrupt +context. Otherwise it runs in task context. + +register_uprobe() returns 0 on success, or a negative errno +otherwise. + +User's handler (u->handler): +#include <linux/uprobes.h> +#include <linux/ptrace.h> +void handler(struct uprobe *u, struct pt_regs *regs); + +Called with u pointing to the uprobe associated with the breakpoint, +and regs pointing to the struct containing the registers saved when +the breakpoint was hit. + +3.2 unregister_uprobe + +#include <linux/uprobes.h> +void unregister_uprobe(struct uprobe *u); + +Removes the specified probe. The unregister function can be called +at any time after the probe has been registered, and can be called +from a uprobe handler. + +4. Uprobes Features and Limitations + +The user is expected to assign values to the following members +of struct uprobe: pid, vaddr, handler. +Uprobes may produce unexpected results if you: +- change the contents of a uprobe object while it is registered; or +- attempt to register a uprobe that is already registered. + +In this implementation, Uprobes allows only one uprobe at a particular +address. + +Uprobe clients may be used to probe a particular process +simultaneously, or probe any number of processes simultaneously. + +Probes are shared by all threads in a process (including newly +created threads). + +If a probed process exits or execs, Uprobes automatically +unregisters all uprobes associated with that process. Subsequent +attempts to unregister these probes will be treated as no-ops. + +On the other hand, if a probed memory area is removed from the +process's virtual memory map (e.g., via dlclose(3) or munmap(2)), +it's currently up to you to unregister the probes first. + +There is no way to specify that probes should be inherited across fork; +Uprobes removes all probepoints in the newly created child process. + +To avoid interfering with interactive debuggers, Uprobes will refuse +to insert a probepoint where a breakpoint instruction already exists. +Some architectures may refuse to insert probes on other types of +instructions. + +If you install a probe in an inline-able function, Uprobes makes +no attempt to chase down all inline instances of the function and +install probes there. gcc may inline a function without being asked, +so keep this in mind if you're not seeing the probe hits you expect. + +A probe handler can modify the environment of the probed function +-- e.g., by modifying data structures, or by modifying the +contents of the pt_regs struct (which are restored to the registers +upon return from the breakpoint). So Uprobes can be used, for example, +to install a bug fix or to inject faults for testing. Uprobes, of +course, has no way to distinguish the deliberately injected faults +from the accidental ones. Don't drink and probe. + +When Uprobes establishes a probepoint on a previous unprobed page of +text, Linux creates a new copy of the page via background page +replacement mechanism. When probepoints are removed, Uprobes makes +no attempt to consolidate identical copies of the same page. This +could affect memory availability if you probe many, many pages in +many, many long-running processes. + +5. TODO + +a. Support for other architectures. +b. Support for multiple probes at the same address. +c. Support for boosted probes. +d. Support return probes. + +6. Uprobes Team + +The following people have made major contributions to Uprobes: +Jim Keniston - [email protected] +Srikar Dronamraju - [email protected] +Ananth Mavinakayanahalli - [email protected] +Prasanna Panchamukhi - [email protected] +Dave Wilder - [email protected]
PATCH v6 8/12 trace: Extract out common code for kprobes/uprobes traceevents.
In reply to Srikar Dronamrajutrace: Extract out common code for kprobes/uprobes traceevents.
Changelog from v5: Addressed comments from Masami Hiramatsu
and Steven Rostedt. Also shared lot more code from kprobes traceevents.
Move common parts of trace_kprobe.c and trace_uprobe.c Adjust kernel/trace/trace_kprobe.c after moving common code to kernel/trace/trace_probe.h and kernel/trace/trace_probe.c.
TODO: Merge both events to a single probe event.
---
kernel/trace/Kconfig | 4 kernel/trace/Makefile | 1 kernel/trace/trace_kprobe.c | 600 ++----------------------------------------- kernel/trace/trace_probe.c | 521 +++++++++++++++++++++++++++++++++++++ kernel/trace/trace_probe.h | 124 +++++++++ 5 files changed, 671 insertions(+), 579 deletions(-) create mode 100644 kernel/trace/trace_probe.c create mode 100644 kernel/trace/trace_probe.h
kernel/trace/Kconfig +4 -0
@@ -395,6 +395,7 @@ config KPROBE_EVENT depends on HAVE_REGS_AND_STACK_ACCESS_API bool "Enable kprobes-based dynamic events" select TRACING + select PROBE_EVENTS default y help This allows the user to add tracing events (similar to tracepoints)
@@ -407,6 +408,9 @@ config KPROBE_EVENT This option is also required by perf-probe subcommand of perf tools. If you want to use perf tools, this option is strongly recommended. +config PROBE_EVENTS + def_bool n + config DYNAMIC_FTRACE bool "enable/disable ftrace tracepoints dynamically" depends on FUNCTION_TRACER
kernel/trace/Makefile +1 -0
@@ -55,5 +55,6 @@ obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o obj-$(CONFIG_KSYM_TRACER) += trace_ksym.o obj-$(CONFIG_EVENT_TRACING) += power-traces.o +obj-$(CONFIG_PROBE_EVENTS) +=trace_probe.o libftrace-y := ftrace.o
kernel/trace/trace_kprobe.c +21 -579
715 lines not on this page · raw message
kernel/trace/trace_probe.c new file +521 -0
521 lines not on this page · raw message
kernel/trace/trace_probe.h new file +124 -0
124 lines not on this page · raw message
Re: [PATCHv6 2.6.35-rc3-tip 8/12] trace: Extract out common code for kprobes/uprobes traceevents.
Hi Sriker,
Quoted 9 lines · Srikar Dronamraju
trace: Extract out common code for kprobes/uprobes traceevents.
Changelog from v5: Addressed comments from Masami Hiramatsu
and Steven Rostedt. Also shared lot more code from kprobes traceevents.Move common parts of
trace_kprobe.candtrace_uprobe.cAdjustkernel/trace/trace_kprobe.cafter moving common code tokernel/trace/trace_probe.handkernel/trace/trace_probe.c.
Great! That's what I need.
I have just some comments. But basically it looks good to me.
Quoted 5 lines
TODO: Merge both events to a single probe event.
Signed-off-by Srikar Dronamraju <[email protected]>---
[...]
Quoted 60 lines
kernel/trace/trace_probe.c new file +54
-0@@ -0,0 +1,521 @@ +/* +* Common code for probe-based Dynamic events. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +* Copyright (C) IBM Corporation, 2010 +* Author: Srikar Dronamraju +* +* Derived from kernel/trace/trace_kprobe.c written by +* Masami Hiramatsu <[email protected]> +*/ + +#include "trace_probe.h" + +const char *reserved_field_names[] = { +"common_type" , +"common_flags" , +"common_preempt_count" , +"common_pid" , +"common_tgid" , +"common_lock_depth" , +FIELD_STRING_IP , +FIELD_STRING_RETIP , +FIELD_STRING_FUNC , +}; + +/* Printing function type */ +#define PRINT_TYPE_FUNC_NAME (type) print_type_##type +#define PRINT_TYPE_FMT_NAME (type) print_type_format_##type + +/* Printing in basic type function template */ +#define DEFINE_BASIC_PRINT_TYPE_FUNC (type, fmt, cast) \ +static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ + const char *name, void *data)\ +{ \ + return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ +} \ +static const char PRINT_TYPE_FMT_NAME(type)[] = fmt; + +DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int) +DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int) +DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long) +DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long)
kernel/trace/trace_probe.c line 64
Quoted 10 lines
kernel/trace/trace_probe.c new file +10
-0+DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int) +DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int) +DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) +DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) + +__kprobes void tp_call_fetch (struct fetch_param *fprm, +struct pt_regs *regs,void *dest) +{ +return fprm->fn (regs, fprm->data, dest); +}
I'd like to put this call_fetch() in header, as an inline, because it's just wrapping handler calling.
And also, I feel "tp_" implies "tracepoint". Perhaps "probe_" or "traceprobe_" is more obvious. It will increase amount of typing, but more readable. ;)
BTW, could you update my e-mail address to [email protected] ? :)
Thank you,
Signature · 4 lines
Masami HIRAMATSU 2nd Research Dept. Hitachi, Ltd., Systems Development Laboratory E-mail: [email protected]
PATCH v6 9/12 trace: uprobes trace_event interface
In reply to Srikar Dronamrajutrace: uprobes trace_event interface
Changelog from v5: Addressed comments from Masami Hiramatsu and Steven
Rostedt. Some changes because of changes in common probe events.
Changelog from v4: (Merged to 2.6.35-rc3-tip)
Changelog from v2/v3: (Addressing comments from Steven Rostedt
and Frederic Weisbecker)
* removed pit field from uprobe_trace_entry.
* share common parts with kprobe trace events.
* use trace_create_file instead of debugfs_create_file.
Implements trace_event support for uprobes. In its
current form it can be used to put probes at a specified text address in a process and dump the required registers when the code flow reaches the probed address.
TODO: Documentation/trace/uprobetrace.txt
---
The following example shows how to dump the instruction pointer and %ax a register at the probed text address.
Start a process to trace. Get the address to trace.
[Here pid is asssumed as 6016]
[Address to trace is 0x0000000000446420] [Registers to be dumped are %ip and %ax]
# cd /sys/kernel/debug/tracing/
# echo 'p 6016:0x0000000000446420 %ip %ax' > uprobe_events
# cat uprobe_events
p:uprobes/p_6016_0x0000000000446420 6016:0x0000000000446420 %ip=%ip %ax=%ax
# cat events/uprobes/p_6016_0x0000000000446420/enable
0
[enable the event]
# echo 1 > events/uprobes/p_6016_0x0000000000446420/enable
# cat events/uprobes/p_6016_0x0000000000446420/enable
1
# #### do some activity on the program so that it hits the breakpoint
# cat uprobe_profile
6016 p_6016_0x0000000000446420 234
# tracer: nop
#
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
zsh-6016 [004] 227931.093579: p_6016_0x0000000000446420: (0x446420) %ip=446421 %ax=79
zsh-6016 [005] 227931.097541: p_6016_0x0000000000446420: (0x446420) %ip=446421 %ax=79
zsh-6016 [000] 227931.124909: p_6016_0x0000000000446420: (0x446420) %ip=446421 %ax=79
zsh-6016 [001] 227933.128565: p_6016_0x0000000000446420: (0x446420) %ip=446421 %ax=79
zsh-6016 [004] 227933.132756: p_6016_0x0000000000446420: (0x446420) %ip=446421 %ax=79
zsh-6016 [000] 227933.158802: p_6016_0x0000000000446420: (0x446420) %ip=446421 %ax=79
zsh-6016 [001] 227935.161602: p_6016_0x0000000000446420: (0x446420) %ip=446421 %ax=79
zsh-6016 [004] 227935.165229: p_6016_0x0000000000446420: (0x446420) %ip=446421 %ax=79arch/Kconfig | 11 - kernel/trace/Kconfig | 16 + kernel/trace/Makefile | 1 kernel/trace/trace.h | 5 kernel/trace/trace_probe.h | 2 kernel/trace/trace_uprobe.c | 739 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 764 insertions(+), 10 deletions(-) create mode 100644 kernel/trace/trace_uprobe.c
arch/Kconfig +1 -10
@@ -48,16 +48,7 @@ config OPTPROBES select KALLSYMS_ALL config UPROBES - bool "User-space probes (EXPERIMENTAL)" - default n - depends on ARCH_SUPPORTS_UPROBES - depends on MMU - help - Uprobes enables kernel subsystems to establish probepoints - in user applications and execute handler functions when - the probepoints are hit. For more information, refer to - Documentation/uprobes.txt. - If in doubt, say "N". + def_bool n config HAVE_EFFICIENT_UNALIGNED_ACCESS bool
kernel/trace/Kconfig +16 -0
@@ -513,6 +513,22 @@ config RING_BUFFER_BENCHMARK If unsure, say N. +config UPROBE_EVENT + bool "Enable uprobes-based dynamic events" + depends on ARCH_SUPPORTS_UPROBES + depends on MMU + select UPROBES + select PROBE_EVENTS + select TRACING + default n + help + This allows the user to add tracing events on top of userspace dynamic + events (similar to tracepoints) on the fly via the traceevents interface. + Those events can be inserted wherever uprobes can probe, and record + various registers. + This option is required if you plan to use perf-probe subcommand of perf + tools on user space applications. + endif # FTRACE endif # TRACING_SUPPORT
kernel/trace/Makefile +1 -0
@@ -56,5 +56,6 @@ obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o obj-$(CONFIG_KSYM_TRACER) += trace_ksym.o obj-$(CONFIG_EVENT_TRACING) += power-traces.o obj-$(CONFIG_PROBE_EVENTS) +=trace_probe.o +obj-$(CONFIG_UPROBE_EVENT) += trace_uprobe.o libftrace-y := ftrace.o
kernel/trace/trace.h +5 -0
@@ -99,6 +99,11 @@ struct kretprobe_trace_entry_head {unsigned long ret_ip; }; +struct uprobe_trace_entry_head { +struct trace_entry ent; +unsigned long ip; +}; +/* * trace_flag_type is an enumeration that holds different * states when a trace occurs. These are:
kernel/trace/trace_probe.h +2 -0
@@ -43,6 +43,7 @@#define FIELD_STRING_IP "__probe_ip"#define FIELD_STRING_RETIP "__probe_ret_ip"#define FIELD_STRING_FUNC "__probe_func" +#define FIELD_STRING_PID "__probe_pid"#undef DEFINE_FIELD#define DEFINE_FIELD (type, item, name, is_signed) \
@@ -59,6 +60,7 @@/* Flags for trace_probe */ #define TP_FLAG_TRACE 1#define TP_FLAG_PROFILE 2 +#define TP_FLAG_UPROBE 4/* Data fetch function type */ typedef void (*fetch_func_t )(struct pt_regs *,void *,void *);
kernel/trace/trace_uprobe.c new file +739 -0
739 lines not on this page · raw message
PATCH v6 10/12 perf: Dont adjust symbols on name lookup
In reply to Srikar Dronamrajuperf: Dont adjust symbols on name lookup
Adjusting symbols is not needed if we are searching by name even if the symbols correspond to user space objects. Infact if we adjust and search symbols by name, we get incorrect results.
---
tools/perf/util/symbol.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
tools/perf/util/symbol.c +4 -2
@@ -1016,12 +1016,14 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, nr_syms = shdr.sh_size / shdr.sh_entsize;memset (&sym,0 ,sizeof (sym)); -if (self->kernel ==DSO_TYPE_USER ) { +if (self->kernel !=DSO_TYPE_USER || symbol_conf.sort_by_name) + self->adjust_symbols =0 ; +else { self->adjust_symbols = (ehdr.e_type ==ET_EXEC ||elf_section_by_name (elf, &ehdr, &shdr,".gnu.prelink_undo" ,NULL ) !=NULL ); - }else self->adjust_symbols =0 ; + }elf_symtab__for_each_symbol (syms, nr_syms, idx, sym) {struct symbol *f;
Re: [PATCHv6 2.6.35-rc3-tip 10/12] perf: Dont adjust symbols on name lookup
Em Mon, Jun 28, 2010 at 11:29:41AM +0530, Srikar Dronamraju escreveu:
Quoted 7 lines
perf: Dont adjust symbols on name lookup
Adjusting symbols is not needed if we are searching by name even if the symbols correspond to user space objects. Infact if we adjust and search symbols by name, we get incorrect results.
I'll review this, but it would be nice to explain why we get incorrect results, as we may be just fixing a symptom of some other problem.
- Arnaldo
Re: [PATCHv6 2.6.35-rc3-tip 10/12] perf: Dont adjust symbols on name lookup
Quoted 11 lines
Quoted 7 lines
perf: Dont adjust symbols on name lookup
Adjusting symbols is not needed if we are searching by name even if the symbols correspond to user space objects. Infact if we adjust and search symbols by name, we get incorrect results.
I'll review this, but it would be nice to explain why we get incorrect results, as we may be just fixing a symptom of some other problem.
You are right. I removed this patch and still see no change in behaviour. Earlier without this patch, I saw that perf report would show a wrong function name(around 2.6.34-rc5 and I carried it to 2.6.35-tip). However the number of events recorded would correspond to the probed function.
Since I am seeing correct behaviour even without this patch, I will drop this patch in the next posting of the patchset.
--
Thanks
Srikar
PATCH v6 11/12 perf: Re-Add make_absolute_path
In reply to Srikar Dronamrajuperf: Re-Add make_absolute_path
perf probe for uprobes would use make_absolute_path. make_absolute_path can be used to convert a file name to a dso name.
so if user specifies the function to be traced as malloc@/lib/libc.so.6 it needs to be converted to [email protected]
This patch reverts a part of a41794cdd7ee94a5199e14f642c26d649d383fa5
---
tools/perf/util/abspath.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/cache.h | 1 + 2 files changed, 82 insertions(+), 0 deletions(-)
tools/perf/util/abspath.c +81 -0
@@ -1,5 +1,86 @@#include "cache.h" +/* +* Do not use this for inspecting *tracked* content. When path is a +* symlink to a directory, we do not want to say it is a directory when +* dealing with tracked content in the working tree. +*/ +static int is_directory (const char *path) +{ +struct stat st; +return (!stat (path, &st) &&S_ISDIR (st.st_mode)); +} + +/* We allow "recursive" symbolic links. Only within reason, though. */ +#define MAXDEPTH 5 + +const char *make_absolute_path (const char *path) +{ +static char bufs[2 ][PATH_MAX +1 ], *buf = bufs[0 ], *next_buf = bufs[1 ]; +char cwd[1024 ] ="" ; +int buf_index =1 , len; + +int depth =MAXDEPTH ; +char *last_elem =NULL ; +struct stat st; + +if (strlcpy (buf, path,PATH_MAX ) >=PATH_MAX ) +die ("Too long path: %.*s" ,60 , path); + +while (depth--) { +if (!is_directory (buf)) { +char *last_slash =strrchr (buf,'/' ); +if (last_slash) { + *last_slash ='\0' ; + last_elem =xstrdup (last_slash +1 ); + }else { + last_elem =xstrdup (buf); + *buf ='\0' ; + } + } + +if (*buf) { +if (!*cwd && !getcwd (cwd,sizeof (cwd))) +die ("Could not get current working directory" ); + +if (chdir (buf)) +die ("Could not switch to '%s'" , buf); + } +if (!getcwd (buf,PATH_MAX )) +die ("Could not get current working directory" ); + +if (last_elem) { + len =strlen (buf); + +if (len +strlen (last_elem) +2 >PATH_MAX ) +die ("Too long path name: '%s/%s'" , + buf, last_elem); + buf[len] ='/' ; +strcpy (buf + len +1 , last_elem); +free (last_elem); + last_elem =NULL ; + } + +if (!lstat (buf, &st) &&S_ISLNK (st.st_mode)) { + len =readlink (buf, next_buf,PATH_MAX ); +if (len <0 ) +die ("Invalid symlink: %s" , buf); +if (PATH_MAX <= len) +die ("symbolic link too long: %s" , buf); + next_buf[len] ='\0' ; + buf = next_buf; + buf_index =1 - buf_index; + next_buf = bufs[buf_index]; + }else +break ; + } + +if (*cwd &&chdir (cwd)) +die ("Could not change back to '%s'" , cwd); + +return buf; +} +static const char *get_pwd_cwd (void ) {static char cwd[PATH_MAX +1 ];
tools/perf/util/cache.h +1 -0
@@ -73,6 +73,7 @@ static inline int is_absolute_path(const char *path)return path[0 ] =='/' ; } +const char *make_absolute_path (const char *path);const char *make_nonrelative_path (const char *path);char *strip_path_suffix (const char *path,const char *suffix);
PATCH v6 12/12 perf: perf interface for uprobes
In reply to Srikar Dronamrajuperf: perf interface for uprobes
Changelog from v4: Merged to 2.6.35-rc3-tip.
Changelog from v3: (addressed comments from Masami Hiramatsu)
* Every process id has a different group name.
* event name starts with function name.
* If vaddr is specified, event name has vaddr appended along with function name, (this is to avoid subsequent probes using same event name.)
* warning if -p and --list options are used together.
Also dso can either be a short name or absolute path.
Enhances perf probe to accept pid and user vaddr.
Provides very basic support for uprobes.
TODO:
Update perf-probes.txt.
Global tracing.
---
Here is a terminal snapshot of placing, using and removing a probe on a process with pid 3591 (corresponding to zsh)
[ Probing a function in the executable using function name ]
-------------------------------------------------------------
[root@ABCD]# perf probe -p 3591 zfree@zsh Added new event: probe_3591:zfree (on 0x446420)
You can now use it on all perf tools, such as:
perf record -e probe_3591:zfree -a sleep 1
[root@ABCD]# perf probe --list probe_3591:zfree (on 3591:0x0000000000446420) [root@ABCD]# cat /sys/kernel/debug/tracing/uprobe_events p:probe_3591/zfree 3591:0x0000000000446420 [root@ABCD]# perf record -f -e probe_3591:zfree -a sleep 10 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.039 MB perf.data (~1716 samples) ] [root@ABCD]# perf probe -p 3591 --del probe_3591:zfree Remove event: probe_3591:zfree [root@ABCD]# perf report # Samples: 447 # # Overhead Command Shared Object Symbol # ........ ............... ............. ...... # 100.00% zsh zsh [.] zfree
#
# (For a higher level overview, try: perf report --sort comm,dso) #
[ Probing a function + offset ]
-------------------------------
[root@ABCD]# perf probe -p 3591 zfree@zsh+5 Added new event: probe_3591:zfree (on 0x446425)
You can now use it on all perf tools, such as:
perf record -e probe_3591:zfree -a sleep 1
[root@ABCD]# perf probe --list probe_3591:zfree (on 3591:0x0000000000446425) [root@ABCD]# cat /sys/kernel/debug/tracing/uprobe_events p:probe_3591/zfree 3591:0x0000000000446425 [root@ABCD]# perf record -f -e probe_3591:zfree -a sleep 10 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.036 MB perf.data (~1590 samples) ] [root@ABCD]# perf probe -p 3591 --del probe_3591:zfree Remove event: probe_3591:zfree [root@ABCD]# perf report # Samples: 18 # # Overhead Command Shared Object Symbol # ........ ............... ............. ...... # 100.00% zsh zsh [.] zfree
#
# (For a higher level overview, try: perf report --sort comm,dso) #
[ Probing a library function using function name ]
--------------------------------------------------
[root@ABCD]# perf probe -p 3591 [email protected] Added new event: probe_3591:write (on 0x36010c6060)
You can now use it on all perf tools, such as:
perf record -e probe_3591:write -a sleep 1
[root@ABCD]# perf probe --list probe_3591:write (on 3591:0x00000036010c6060) [root@ABCD]# cat /sys/kernel/debug/tracing/uprobe_events p:probe_3591/write 3591:0x00000036010c6060 [root@ABCD]# perf record -f -e probe_3591:write -a sleep 10 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.040 MB perf.data (~1738 samples) ] [root@ABCD]# perf probe -p 3591 --del probe_3591:write Remove event: probe_3591:write [root@ABCD]# perf report # Samples: 11 # # Overhead Command Shared Object Symbol # ........ ............... .................. ...... # 100.00% zsh libc-2.5.so [.] __GI___libc_write
#
# (For a higher level overview, try: perf report --sort comm,dso) #
[ Probing a library function using function name and absolute path ]
---------------------------------------------------------------------
[root@ABCD]# perf probe -p 3591 write@/lib64/libc-2.5.so Added new event: probe_3591:write (on 0x36010c6060)
You can now use it on all perf tools, such as:
perf record -e probe_3591:write -a sleep 1
[root@ABCD]# perf probe --list probe_3591:write (on 3591:0x00000036010c6060) [root@ABCD]# cat /sys/kernel/debug/tracing/uprobe_events p:probe_3591/write 3591:0x00000036010c6060 [root@ABCD]# perf record -f -e probe_3591:write -a sleep 10 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.040 MB perf.data (~1738 samples) ] [root@ABCD]# perf probe -p 3591 --del probe_3591:write Remove event: probe_3591:write [root@ABCD]# perf report # Samples: 11 # # Overhead Command Shared Object Symbol # ........ ............... .................. ...... # 100.00% zsh libc-2.5.so [.] __GI___libc_write
#
# (For a higher level overview, try: perf report --sort comm,dso) #
[ Probing using vaddr 0x0000000000446420 (corresponding to zfree)]
-------------------------------------------------------------------
[root@ABCD]# perf probe -p 3591 0x0000000000446420 Added new event: probe_3591:zfree_446420 (on 0x0000000000446420)
You can now use it on all perf tools, such as:
perf record -e probe_3591:zfree_446420 -a sleep 1
[root@ABCD]# perf record -e probe_3591:zfree_446420 -a sleep 10 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.041 MB perf.data (~1797 samples) ] [root@ABCD]# perf report # # Samples: 628 # # Overhead Command Shared Object Symbol # ........ ............... ............. ...... # 100.00% zsh zsh [.] zfree
#
# (For a higher level overview, try: perf report --sort comm,dso) #
[root@ABCD]# perf report --sort comm,dso # Samples: 628 # # Overhead Command Shared Object # ........ ............... ............. # 100.00% zsh zsh
[root@ABCD]# perf probe --list probe_3591:zfree_446420 (on 3591:0x0000000000446420) [root@ABCD]# perf list | grep probe probe_3591:zfree_446420 [Tracepoint event] [root@ABCD]# perf probe -p 3591 --del probe_3591:zfree_446420 Remove event: probe_3591:zfree_446420 [root@ABCD]#
Another example for a shared library: write stub in libc. (corresponds to 0x00000036010c6060)
on a vaddr
[ Probing a libc vaddr 0x00000036010c6060 (corresponding to write) ]
[root@ABCD]# perf probe -p 3591 0x00000036010c6060 dded new event: probe_3591:__GI___libc_write_36010c6060 (on 0x00000036010c6060)
You can now use it on all perf tools, such as:
perf record -e probe_3591:__GI___libc_write_36010c6060 -a sleep 1
[root@ABCD]# perf record -f -e probe_3591:__GI___libc_write_36010c6060 -a sleep 10 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.040 MB perf.data (~1748 samples) ] [root@ABCD]# perf report # Samples: 24 # # Overhead Command Shared Object Symbol # ........ ............... .................. ...... # 100.00% zsh libc-2.5.so [.] __GI___libc_write
#
# (For a higher level overview, try: perf report --sort comm,dso) #
[root@ABCD]#
[ Probing using a function without specifying a dso (corresponding to zfree)]
-------------------------------------------------------------------
[root@ABCD]# perf probe -p 3591 zfree Added new event: probe_3591:zfree (on 0x0000000000446420)
You can now use it on all perf tools, such as:
perf record -e probe_3591:zfree -a sleep 1
[root@ABCD]# perf record -e probe_3591:zfree -a sleep 10 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.041 MB perf.data (~1797 samples) ] [root@ABCD]# perf report # # Samples: 628 # # Overhead Command Shared Object Symbol # ........ ............... ............. ...... # 100.00% zsh zsh [.] zfree
#
# (For a higher level overview, try: perf report --sort comm,dso) #
[root@ABCD]#
tools/perf/builtin-probe.c | 13 + tools/perf/builtin-top.c | 20 -- tools/perf/util/event.c | 20 ++ tools/perf/util/event.h | 1 tools/perf/util/probe-event.c | 466 ++++++++++++++++++++++++++++------------ tools/perf/util/probe-event.h | 37 +-- tools/perf/util/probe-finder.c | 20 +- tools/perf/util/probe-finder.h | 6 - 8 files changed, 385 insertions(+), 198 deletions(-)
tools/perf/builtin-probe.c +10 -3
@@ -55,6 +55,7 @@ static struct {struct strlist *dellist;struct line_range line_range;int max_probe_points; +pid_t upid; } params;
@@ -73,6 +74,7 @@ static int parse_probe_event(const char *str)/* Parse a perf-probe command into event */ ret =parse_perf_probe_command (str, pev);pr_debug ("%d arguments\n" , pev->nargs); + pev->upid = params.upid;return ret; }
@@ -188,6 +190,8 @@ static const struct option options[] = {OPT__DRY_RUN (&probe_event_dry_run),OPT_INTEGER ('\0' ,"max-probes" , ¶ms.max_probe_points,"Set how many probe points can be found for a probe." ), +OPT_INTEGER ('p' ,"pid" , ¶ms.upid, +"specify a pid for a uprobes based probe" ), OPT_END() };
@@ -225,6 +229,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)pr_err (" Error: Don't use --list with --line.\n" );usage_with_options (probe_usage, options); } +if (params.upid) { +pr_warning (" Error: Don't use --list with --pid.\n" ); +usage_with_options (probe_usage, options); + } ret =show_perf_probe_events ();if (ret <0 ) pr_err(" Error: Failed to show event list. (%d)\n",
@@ -233,7 +241,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) }#ifdef DWARF_SUPPORT -if (params.show_lines) { +if (params.show_lines && !params.upid) {if (params.nevents !=0 || params.dellist) {pr_warning (" Error: Don't use --line with" " --add/--del.\n" );
@@ -248,7 +256,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)#endif if (params.dellist) { - ret =del_perf_probe_events (params.dellist); + ret =del_perf_probe_events (params.dellist, params.upid);strlist__delete (params.dellist);if (ret <0 ) {pr_err (" Error: Failed to delete events. (%d)\n" , ret);
@@ -267,4 +275,3 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) }return 0 ; } -
tools/perf/builtin-top.c +0 -20
@@ -1082,26 +1082,6 @@ static void event__process_sample(const event_t *self, } } -static int event__process (event_t *event,struct perf_session *session) -{ -switch (event->header.type) { -case PERF_RECORD_COMM : -event__process_comm (event, session); -break ; -case PERF_RECORD_MMAP : -event__process_mmap (event, session); -break ; -case PERF_RECORD_FORK : -case PERF_RECORD_EXIT : -event__process_task (event, session); -break ; -default : -break ; - } - -return 0 ; -} -struct mmap_data {int counter;void *base;
tools/perf/util/event.c +20 -0
@@ -552,6 +552,26 @@ int event__process_task(event_t *self, struct perf_session *session)return 0 ; } +int event__process (event_t *event,struct perf_session *session) +{ +switch (event->header.type) { +case PERF_RECORD_COMM : +event__process_comm (event, session); +break ; +case PERF_RECORD_MMAP : +event__process_mmap (event, session); +break ; +case PERF_RECORD_FORK : +case PERF_RECORD_EXIT : +event__process_task (event, session); +break ; +default : +break ; + } + +return 0 ; +} + void thread__find_addr_map(struct thread *self, struct perf_session *session, u8 cpumode, enum map_type type, pid_t pid, u64 addr,
tools/perf/util/event.h +1 -0
@@ -154,6 +154,7 @@ int event__process_comm(event_t *self, struct perf_session *session);int event__process_lost (event_t *self,struct perf_session *session);int event__process_mmap (event_t *self,struct perf_session *session);int event__process_task (event_t *self,struct perf_session *session); +int event__process (event_t *event,struct perf_session *session);struct addr_location ; int event__preprocess_sample(const event_t *self, struct perf_session *session,
tools/perf/util/probe-event.c +325 -141
842 lines not on this page · raw message
tools/perf/util/probe-event.h +16 -21
@@ -6,34 +6,35 @@extern bool probe_event_dry_run; -/* kprobe-tracer tracing point */ -struct kprobe_trace_point { +/* kprobe-tracer and uprobe-tracer tracing point */ +struct probe_trace_point {char *symbol;/* Base symbol */ unsigned long offset;/* Offset from symbol */ bool retprobe;/* Return probe flag */ }; -/* kprobe-tracer tracing argument referencing offset */ -struct kprobe_trace_arg_ref { -struct kprobe_trace_arg_ref *next;/* Next reference */ +/* probe-tracer tracing argument referencing offset */ +struct probe_trace_arg_ref { +struct probe_trace_arg_ref *next;/* Next reference */ long offset;/* Offset value */ }; -/* kprobe-tracer tracing argument */ -struct kprobe_trace_arg { +/* kprobe-tracer and uprobe-tracer tracing argument */ +struct probe_trace_arg {char *name;/* Argument name */ char *value;/* Base value */ char *type;/* Type name */ -struct kprobe_trace_arg_ref *ref;/* Referencing offset */ +struct probe_trace_arg_ref *ref;/* Referencing offset */ }; -/* kprobe-tracer tracing event (point + arg) */ -struct kprobe_trace_event { +/* kprobe-tracer and uprobe-tracer tracing event (point + arg) */ +struct probe_trace_event {char *event;/* Event name */ char *group;/* Group name */ -struct kprobe_trace_point point;/* Trace point */ +struct probe_trace_point point;/* Trace point */ int nargs;/* Number of args */ -struct kprobe_trace_arg *args;/* Arguments */ +pid_t upid;/* uprobes only */ +struct probe_trace_arg *args;/* Arguments */ };/* Perf probe probing point */
@@ -67,6 +68,7 @@ struct perf_probe_event {char *group;/* Group name */ struct perf_probe_point point;/* Probe point */ int nargs;/* Number of arguments */ +pid_t upid;struct perf_probe_arg *args;/* Arguments */ };
@@ -91,25 +93,18 @@ struct line_range {/* Command string to events */ extern int parse_perf_probe_command (const char *cmd,struct perf_probe_event *pev); -extern int parse_kprobe_trace_command (const char *cmd, -struct kprobe_trace_event *tev);/* Events to command string */ extern char *synthesize_perf_probe_command (struct perf_probe_event *pev); -extern char *synthesize_kprobe_trace_command (struct kprobe_trace_event *tev); +extern char *synthesize_probe_trace_command (struct probe_trace_event *tev);extern int synthesize_perf_probe_arg (struct perf_probe_arg *pa,char *buf,size_t len);/* Check the perf_probe_event needs debuginfo */ extern bool perf_probe_event_need_dwarf (struct perf_probe_event *pev); -/* Convert from kprobe_trace_event to perf_probe_event */ -extern int convert_to_perf_probe_event (struct kprobe_trace_event *tev, -struct perf_probe_event *pev); -/* Release event contents */ extern void clear_perf_probe_event (struct perf_probe_event *pev); -extern void clear_kprobe_trace_event (struct kprobe_trace_event *tev);/* Command string to line-range */ extern int parse_line_range_desc (const char *cmd,struct line_range *lr);
@@ -117,7 +112,7 @@ extern int parse_line_range_desc(const char *cmd, struct line_range *lr);extern int add_perf_probe_events (struct perf_probe_event *pevs,int npevs,bool force_add,int max_probe_points); -extern int del_perf_probe_events (struct strlist *dellist); +extern int del_perf_probe_events (struct strlist *dellist,pid_t pid);extern int show_perf_probe_events (void );extern int show_line_range (struct line_range *lr);
tools/perf/util/probe-finder.c +10 -10
@@ -413,7 +413,7 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf)Dwarf_Word offs =0 ;bool ref = false;const char *regs; -struct kprobe_trace_arg *tvar = pf->tvar; +struct probe_trace_arg *tvar = pf->tvar;/* If this is based on frame buffer, set the offset */ if (op->atom == DW_OP_fbreg) {
@@ -455,7 +455,7 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf)return -ENOMEM ;if (ref) { - tvar->ref =zalloc (sizeof (struct kprobe_trace_arg_ref )); + tvar->ref =zalloc (sizeof (struct probe_trace_arg_ref ));if (tvar->ref ==NULL )return -ENOMEM ; tvar->ref->offset = (long )offs;
@@ -464,7 +464,7 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf) }static int convert_variable_type (Dwarf_Die *vr_die, -struct kprobe_trace_arg *targ) +struct probe_trace_arg *targ) {Dwarf_Die type;char buf[16 ];
@@ -504,10 +504,10 @@ static int convert_variable_type(Dwarf_Die *vr_die,static int convert_variable_fields (Dwarf_Die *vr_die,const char *varname,struct perf_probe_arg_field *field, -struct kprobe_trace_arg_ref **ref_ptr, +struct probe_trace_arg_ref **ref_ptr,Dwarf_Die *die_mem) { -struct kprobe_trace_arg_ref *ref = *ref_ptr; +struct probe_trace_arg_ref *ref = *ref_ptr;Dwarf_Die type;Dwarf_Word offs;int ret;
@@ -536,7 +536,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,return -EINVAL ; } - ref =zalloc (sizeof (struct kprobe_trace_arg_ref )); + ref =zalloc (sizeof (struct probe_trace_arg_ref ));if (ref ==NULL )return -ENOMEM ;if (*ref_ptr)
@@ -668,7 +668,7 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)/* Show a probe point to output buffer */ static int convert_probe_point (Dwarf_Die *sp_die,struct probe_finder *pf) { -struct kprobe_trace_event *tev; +struct probe_trace_event *tev;Dwarf_Addr eaddr;Dwarf_Die die_mem;const char *name;
@@ -733,7 +733,7 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)/* Find each argument */ tev->nargs = pf->pev->nargs; - tev->args =zalloc (sizeof (struct kprobe_trace_arg ) * tev->nargs); + tev->args =zalloc (sizeof (struct probe_trace_arg ) * tev->nargs);if (tev->args ==NULL )return -ENOMEM ;for (i =0 ; i < pf->pev->nargs; i++) {
@@ -992,7 +992,7 @@ static int find_probe_point_by_func(struct probe_finder *pf)/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ int find_kprobe_trace_events (int fd,struct perf_probe_event *pev, -struct kprobe_trace_event **tevs,int max_tevs) +struct probe_trace_event **tevs,int max_tevs) {struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs};struct perf_probe_point *pp = &pev->point;
@@ -1002,7 +1002,7 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,Dwarf *dbg;int ret =0 ; - pf.tevs =zalloc (sizeof (struct kprobe_trace_event ) * max_tevs); + pf.tevs =zalloc (sizeof (struct probe_trace_event ) * max_tevs);if (pf.tevs ==NULL )return -ENOMEM ; *tevs = pf.tevs;
tools/perf/util/probe-finder.h +3 -3
@@ -18,7 +18,7 @@ static inline int is_c_varname(const char *name)#ifdef DWARF_SUPPORT /* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ extern int find_kprobe_trace_events (int fd,struct perf_probe_event *pev, -struct kprobe_trace_event **tevs, +struct probe_trace_event **tevs,int max_tevs);/* Find a perf_probe_point from debuginfo */
@@ -33,7 +33,7 @@ extern int find_line_range(int fd, struct line_range *lr);struct probe_finder {struct perf_probe_event *pev;/* Target probe event */ -struct kprobe_trace_event *tevs;/* Result trace events */ +struct probe_trace_event *tevs;/* Result trace events */ int ntevs;/* Number of trace events */ int max_tevs;/* Max number of trace events */
@@ -50,7 +50,7 @@ struct probe_finder {#endif Dwarf_Op *fb_ops;/* Frame base attribute */ struct perf_probe_arg *pvar;/* Current target variable */ -struct kprobe_trace_arg *tvar;/* Current result variable */ +struct probe_trace_arg *tvar;/* Current result variable */ };struct line_finder {