Skip to contentSkip to conversation

Uprobes Patches:

PATCH Superseded Srikar Dronamraju 4 participants 23 messages Jul 8, 2010 – Jul 9, 2010

Subsystems (11)

v8 of 11 Superseded Latest is v11 →

lore
Share & tools
lore
#0 lore raw

v8 cover Uprobes Patches:

Uprobes Patches
Changelog from V7:
- New feature: perf probe lists available probes.
- Fix perf probes for uprobes to exit with a error message on dwarf based probes.
- Merge changes to kprobes traceevent infrastructure.
- Merge changes to perf.

Changelog from V6:
- Remove perf adjust symbols patch.

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/29/299
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.

- Perf automatically adds probes for high-overhead functions. (Need clarity on how and when to determine a function to be a high-overhead function)
- Allow trace scripts to insert probes
- Syscall integration and TRACE_EVENT() universe.
(Need clarity/discussion on API)
- Allow users to insert probes in their applications.
- 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: Re-Add make_absolute_path
11: perf: perf interface for uprobes
12: perf: Show Potential probe points.

 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        |  742 +-------------------
 kernel/trace/trace_probe.c         |  654 +++++++++++++++++
 kernel/trace/trace_probe.h         |  153 ++++
 kernel/trace/trace_uprobe.c        |  739 +++++++++++++++++++
 kernel/uprobes.c                   | 1396 ++++++++++++++++++++++++++++++++++++
 mm/ksm.c                           |  112 ---
 mm/memory.c                        |  120 +++
 tools/perf/builtin-probe.c         |   53 ++-
 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/map.h              |    2 +
 tools/perf/util/probe-event.c      |  599 ++++++++++++----
 tools/perf/util/probe-event.h      |   38 +-
 tools/perf/util/probe-finder.c     |   14 +-
 tools/perf/util/probe-finder.h     |    6 +-
 tools/perf/util/symbol.c           |   38 +
 tools/perf/util/symbol.h           |    1 +
 38 files changed, 5005 insertions(+), 1042 deletions(-)
#1 lore raw

PATCH v8 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
index b969efb..206008e 100644
@@ -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

#2 lore raw

PATCH v8 2/12 uprobes: Breakpoint insertion/removal in user space applications.

In reply to Srikar Dronamraju

uprobes: 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
index 4877a8c..87bd26b 100644
@@ -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
index ce53fb2..ec70eab 100644
@@ -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

#3 lore raw

PATCH v8 3/12 uprobes: Slot allocation for Execution out of line(XOL)

In reply to Srikar Dronamraju

uprobes: 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
index 02d9927..a5146f5 100644
@@ -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_PAGE
 
 struct task_struct;
 struct pt_regs;
kernel/uprobes.c +283 -0

295 lines not on this page · raw message

#4 lore raw

PATCH v8 4/12 uprobes: x86 specific functions for user space breakpointing.

In reply to Srikar Dronamraju

uprobes: 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
index 3069a6d..8f2bdbf 100644
@@ -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
index f0b6e5d..5b9c9f0 100644
@@ -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
index 0925676..f1da575 100644
@@ -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

#5 lore raw

PATCH v8 5/12 uprobes: Uprobes (un)registration and exception handling.

In reply to Srikar Dronamraju

uprobes: 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
index 87bd26b..c8c8e3f 100644
@@ -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
index 97d91a0..fe49384 100644
@@ -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
index b8bb9a6..200c659 100644
@@ -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
index 1f25798..26de836 100644
@@ -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
index a82a65c..c932193 100644
@@ -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

#6 lore raw

PATCH v8 6/12 uprobes: X86 support for Uprobes

In reply to Srikar Dronamraju

uprobes: 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
index 4fd173c..3657563 100644
@@ -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

#7 lore raw

PATCH v8 7/12 uprobes: Uprobes Documentation

In reply to Srikar Dronamraju

uprobes: 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
new file mode 100644
index 0000000..cf87136
@@ -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]
#8 lore raw

PATCH v8 8/12 trace: Extract out common code for kprobes/uprobes traceevents.

In reply to Srikar Dronamraju

trace: Extract out common code for kprobes/uprobes traceevents.

Changelog from v7: Merge changes due to string support in kprobes
traceevent.

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 |  742 +------------------------------------------
 kernel/trace/trace_probe.c  |  654 ++++++++++++++++++++++++++++++++++++++
 kernel/trace/trace_probe.h  |  151 +++++++++
 5 files changed, 819 insertions(+), 733 deletions(-)
 create mode 100644 kernel/trace/trace_probe.c
 create mode 100644 kernel/trace/trace_probe.h
kernel/trace/Kconfig +4 -0
index f669092..ab62d9a 100644
@@ -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
index 469a1c7..5a45910 100644
@@ -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 +9 -733

812 lines not on this page · raw message

kernel/trace/trace_probe.c new file +654 -0

654 lines not on this page · raw message

kernel/trace/trace_probe.h new file +151 -0

151 lines not on this page · raw message

#9 lore raw

PATCH v8 9/12 trace: uprobes trace_event interface

In reply to Srikar Dronamraju

trace: 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=79
 arch/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
index c8c8e3f..af167f8 100644
@@ -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
index ab62d9a..2f46188 100644
@@ -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
index 5a45910..a386d12 100644
@@ -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
index cc90ccd..8ef185f 100644
@@ -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
index ad783a5..b52d527 100644
@@ -44,6 +44,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)			\
@@ -60,6 +61,7 @@
 /* Flags for trace_probe */
 #define TP_FLAG_TRACE	1
 #define TP_FLAG_PROFILE	2
+#define TP_FLAG_UPROBE	4
 
 
 /* data_rloc: data relative location, compatible with u32 */
kernel/trace/trace_uprobe.c new file +739 -0

739 lines not on this page · raw message

#10 lore raw

PATCH v8 10/12 perf: Re-Add make_absolute_path

In reply to Srikar Dronamraju

revert_make_absolute_path

From: Srikar Dronamraju <[email protected]>

perf: 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
index 0e76aff..0a985fd 100644
@@ -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
index 27e9ebe..0dfed40 100644
@@ -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);
 
#11 lore raw

PATCH v8 11/12 perf: perf interface for uprobes

In reply to Srikar Dronamraju

perf: perf interface for uprobes

Changelog from v6: Changelog from v6: Fixed a bug reported by Masami.
i.e Throw an error message and exit if perf probe is for a dwarf based probes.

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  |  516 +++++++++++++++++++++++++++++-----------
 tools/perf/util/probe-event.h  |   37 +--
 tools/perf/util/probe-finder.c |   14 +
 tools/perf/util/probe-finder.h |    6 
 8 files changed, 431 insertions(+), 196 deletions(-)
tools/perf/builtin-probe.c +10 -3
index 5455186..cb915a5 100644
@@ -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", &params.max_probe_points,
 		 "Set how many probe points can be found for a probe."),
+	OPT_INTEGER('p', "pid", &params.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
index 1e8e92e..b513e40 100644
@@ -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
index d7f21d7..d93e0bb 100644
@@ -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
index 887ee63..8e790da 100644
@@ -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 +374 -142

919 lines not on this page · raw message

tools/perf/util/probe-event.h +16 -21
index bc06d3e..f69f98e 100644
@@ -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 */
@@ -68,6 +69,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 */
 };
 
@@ -92,25 +94,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);
@@ -118,7 +113,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 +7 -7
index 3e64e1f..bbcf3cb 100644
@@ -585,10 +585,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, tag;
@@ -645,7 +645,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)
@@ -778,7 +778,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;
@@ -843,7 +843,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++) {
@@ -1102,7 +1102,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;
@@ -1112,7 +1112,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
index e1f61dc..73aabb2 100644
@@ -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 {
#12 lore raw

Re: [PATCHv8 2.6.35-rc4-tip 11/12] perf: perf interface for uprobes

Quoted 2 lines

Here is a terminal snapshot of placing, using and removing a probe on a process with pid 3591 (corresponding to zsh)

Btw, I think this interface is not the most the best one for typical uses cases. To make perf probe support more useful we'll need at least a way to create a probe in all intances of a given binary/DSO, and a way to run a binary with pre-defined breakpoints.

#13 lore raw

Re: [PATCHv8 2.6.35-rc4-tip 11/12] perf: perf interface for uprobes

Hi Christoph,

Quoted 8 lines
Quoted 2 lines

Here is a terminal snapshot of placing, using and removing a probe on a process with pid 3591 (corresponding to zsh)

Btw, I think this interface is not the most the best one for typical uses cases. To make perf probe support more useful we'll need at least a way to create a probe in all intances of a given binary/DSO, and a way to run a binary with pre-defined breakpoints.

Yes Peter had already asked for this and we have it in plan. These are listed in the todos I listed corresponding to file based probes.

- Allowing probes per-executable/per dso.
- Allowing probes across fork.

I have some thoughts on how to achieve these.

However I am not sure which items I should work first
- file based probes or on
- automatically trigger perf uprobes on high overhead functions that Ingo suggested.

I am not too clear on later so I might as well start thinking on file based probes.

--
Thanks and Regards
Srikar

#14 lore raw

Re: [PATCHv8 2.6.35-rc4-tip 11/12] perf: perf interface for uprobes

In reply to Srikar Dronamraju

perf: perf interface for uprobes

Changelog:
Fixed a compilation issue reported by Christoph Hellwig.

Changelog from v6: Changelog from v6: Fixed a bug reported by Masami.
i.e Throw an error message and exit if perf probe is for a dwarf based probes.

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  |  520 +++++++++++++++++++++++++++++-----------
 tools/perf/util/probe-event.h  |   37 +--
 tools/perf/util/probe-finder.c |   34 +--
 tools/perf/util/probe-finder.h |   10 -
 8 files changed, 445 insertions(+), 210 deletions(-)
tools/perf/builtin-probe.c +10 -3
index 5455186..cb915a5 100644
@@ -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", &params.max_probe_points,
 		 "Set how many probe points can be found for a probe."),
+	OPT_INTEGER('p', "pid", &params.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
index 1e8e92e..b513e40 100644
@@ -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
index d7f21d7..d93e0bb 100644
@@ -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
index 887ee63..8e790da 100644
@@ -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 +376 -144

932 lines not on this page · raw message

tools/perf/util/probe-event.h +16 -21
index bc06d3e..f69f98e 100644
@@ -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 */
@@ -68,6 +69,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 */
 };
 
@@ -92,25 +94,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);
@@ -118,7 +113,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 +17 -17
index 3e64e1f..f3a024a 100644
@@ -406,10 +406,10 @@ static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
  * Probe finder related functions
  */
 
-static struct kprobe_trace_arg_ref *alloc_trace_arg_ref(long offs)
+static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
 {
-	struct kprobe_trace_arg_ref *ref;
-	ref = zalloc(sizeof(struct kprobe_trace_arg_ref));
+	struct probe_trace_arg_ref *ref;
+	ref = zalloc(sizeof(struct probe_trace_arg_ref));
 	if (ref != NULL)
 		ref->offset = offs;
 	return ref;
@@ -425,7 +425,7 @@ static int convert_variable_location(Dwarf_Die *vr_die, 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;
 	int ret;
 
 	/* TODO: handle more than 1 exprs */
@@ -499,10 +499,10 @@ static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf)
 }
 
 static int convert_variable_type(Dwarf_Die *vr_die,
-				 struct kprobe_trace_arg *tvar,
+				 struct probe_trace_arg *tvar,
 				 const char *cast)
 {
-	struct kprobe_trace_arg_ref **ref_ptr = &tvar->ref;
+	struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
 	Dwarf_Die type;
 	char buf[16];
 	int ret;
@@ -540,7 +540,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
 			while (*ref_ptr)
 				ref_ptr = &(*ref_ptr)->next;
 			/* Add new reference with offset +0 */
-			*ref_ptr = zalloc(sizeof(struct kprobe_trace_arg_ref));
+			*ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref));
 			if (*ref_ptr == NULL) {
 				pr_warning("Out of memory error\n");
 				return -ENOMEM;
@@ -585,10 +585,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, tag;
@@ -614,7 +614,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
 		pr_debug2("Array real type: (%x)\n",
 			 (unsigned)dwarf_dieoffset(&type));
 		if (tag == DW_TAG_pointer_type) {
-			ref = zalloc(sizeof(struct kprobe_trace_arg_ref));
+			ref = zalloc(sizeof(struct probe_trace_arg_ref));
 			if (ref == NULL)
 				return -ENOMEM;
 			if (*ref_ptr)
@@ -645,7 +645,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)
@@ -778,7 +778,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;
@@ -843,7 +843,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++) {
@@ -1100,9 +1100,9 @@ static int find_probe_point_by_func(struct probe_finder *pf)
 	return _param.retval;
 }
 
-/* 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)
+/* Find probe_trace_events specified by perf_probe_event from debuginfo */
+int find_probe_trace_events(int fd, struct perf_probe_event *pev,
+			     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;
@@ -1112,7 +1112,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 +5 -5
index e1f61dc..4507d51 100644
@@ -16,9 +16,9 @@ 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,
+/* Find probe_trace_events specified by perf_probe_event from debuginfo */
+extern int find_probe_trace_events(int fd, struct perf_probe_event *pev,
+				    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 {
#15 lore raw

PATCH v8 12/12 perf: Show Potential probe points.

In reply to Srikar Dronamraju

perf: Show Potential probe points.

Introduces an option to list potential probes to probe using perf probe command. Also introduces an option to limit the dso to list the potential probes. Listing of potential probes is sorted by dso and alphabetical order.

---

Show all potential probes in the current running kernel.

# perf probe -S | tail
zone_reclaimable_pages
zone_spanned_pages_in_node
zone_statistics
zone_wait_table_init
zone_watermark_ok
zoneinfo_open
zoneinfo_show
zoneinfo_show_print
zoneref_set_zone
zp_probe

Show all potential probes in a process by pid 21106 across all dsos

# perf probe -S -p 21106 | tail
_nss_files_gethostbyname2_r
_nss_files_gethostbyname_r
_nss_files_gethostent_r
_nss_files_gethostton_r
_nss_files_getnetbyaddr_r
_nss_files_getnetbyname_r
_nss_files_getnetent_r
_nss_files_getnetgrent_r
_nss_files_getntohost_r
_nss_files_getpr

Show all potentail probes in a process by pid 21106 limit to libc.so dso.

# perf probe -S -p 21106 -D zsh | tail
zstrtol
ztrcmp
ztrdup
ztrduppfx
ztrftime
ztrlen
ztrncpy
ztrsub
zwarn
zwarnnam
 tools/perf/builtin-probe.c    |   40 +++++++++++++++++++
 tools/perf/util/map.h         |    2 +
 tools/perf/util/probe-event.c |   85 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/probe-event.h |    1 
 tools/perf/util/symbol.c      |   38 ++++++++++++++++++
 tools/perf/util/symbol.h      |    1 
 6 files changed, 165 insertions(+), 2 deletions(-)
tools/perf/builtin-probe.c +39 -1
index cb915a5..6de3236 100644
@@ -50,9 +50,11 @@ static struct {
 	bool list_events;
 	bool force_add;
 	bool show_lines;
+	bool list_functions;
 	int nevents;
 	struct perf_probe_event events[MAX_PROBES];
 	struct strlist *dellist;
+	struct strlist *limitlist;
 	struct line_range line_range;
 	int max_probe_points;
 	pid_t upid;
@@ -134,6 +136,17 @@ static int opt_show_lines(const struct option *opt __used,
 }
 #endif
 
+static int opt_limit_dsos(const struct option *opt __used,
+			       const char *str, int unset __used)
+{
+	if (str) {
+		if (!params.limitlist)
+			params.limitlist = strlist__new(true, NULL);
+		strlist__add(params.limitlist, str);
+	}
+	return 0;
+}
+
 static const char * const probe_usage[] = {
 	"perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
 	"perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
@@ -192,6 +205,10 @@ static const struct option options[] = {
 		 "Set how many probe points can be found for a probe."),
 	OPT_INTEGER('p', "pid", &params.upid,
 			"specify a pid for a uprobes based probe"),
+	OPT_BOOLEAN('S', "show_functions", &params.list_functions,
+				"Show potential probes."),
+	OPT_CALLBACK('D', "limit_dsos", NULL, "DSO",
+				"Limit Dsos.", opt_limit_dsos),
 	OPT_END()
 };
 
@@ -217,7 +234,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 		params.max_probe_points = MAX_PROBES;
 
 	if ((!params.nevents && !params.dellist && !params.list_events &&
-	     !params.show_lines))
+	     !params.show_lines && !params.list_functions))
 		usage_with_options(probe_usage, options);
 
 	if (params.list_events) {
@@ -233,12 +250,33 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 			pr_warning("  Error: Don't use --list with --pid.\n");
 			usage_with_options(probe_usage, options);
 		}
+		if (params.list_functions) {
+			pr_warning("  Error: Don't use --list with --show_functions.\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",
 			       ret);
 		return ret;
 	}
+	if (params.list_functions) {
+		if (params.nevents != 0 || params.dellist) {
+			pr_err("  Error: Don't use --show_functions with"
+					"--add/--del.\n");
+			usage_with_options(probe_usage, options);
+		}
+		if (params.show_lines) {
+			pr_err("  Error: Don't use --show_functions with"
+					"--line.\n");
+			usage_with_options(probe_usage, options);
+		}
+		ret = show_possible_probes(params.limitlist, params.upid);
+		if (ret < 0)
+			pr_err("  Error: Failed to show possible"
+					"probes (%d).\n", ret);
+		return ret;
+	}
 
 #ifdef DWARF_SUPPORT
 	if (params.show_lines && !params.upid) {
tools/perf/util/map.h +2 -0
index f391345..b7dedcd 100644
@@ -210,6 +210,8 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
 
 struct map *map_groups__find_by_name(struct map_groups *self,
 				     enum map_type type, const char *name);
+int map_groups__iterate_maps(struct map_groups *self, enum map_type type,
+		const char *name, int (*fn)(struct map*, const char *));
 struct map *machine__new_module(struct machine *self, u64 start, const char *filename);
 
 void map_groups__flush(struct map_groups *self);
tools/perf/util/probe-event.c +84 -1

94 lines not on this page · raw message

tools/perf/util/probe-event.h +1 -0
index f69f98e..a7a6a86 100644
@@ -116,6 +116,7 @@ extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
 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);
+extern int show_possible_probes(struct strlist *availlist, pid_t pid);
 
 
 /* Maximum index number of event-name postfix */
tools/perf/util/symbol.c +38 -0
index 971d0a0..18bb1d8 100644
@@ -1448,6 +1448,28 @@ struct map *map_groups__find_by_name(struct map_groups *self,
 	return NULL;
 }
 
+int map_groups__iterate_maps(struct map_groups *self, enum map_type type,
+			const char *name, int (*fn)(struct map*, const char *))
+{
+	struct rb_node *nd;
+	struct map *map;
+	int ret;
+
+	if (!fn)
+		return -EINVAL;
+
+	for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
+		map = rb_entry(nd, struct map, rb_node);
+		if (!map)
+			return -EINVAL;
+
+		ret = fn(map, name);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
 static int dso__kernel_module_get_build_id(struct dso *self,
 				const char *root_dir)
 {
@@ -2343,3 +2365,19 @@ int machine__load_vmlinux_path(struct machine *self, enum map_type type,
 
 	return ret;
 }
+
+void dso__list_available_symbols(struct dso *self, enum map_type type)
+{
+	struct rb_root *rb;
+	struct rb_node *nd;
+	struct symbol_name_rb_node *pos;
+
+	if (!self)
+		return;
+
+	rb = &self->symbol_names[type];
+	for (nd = rb_first(&self->symbol_names[type]); nd; nd = rb_next(nd)) {
+		pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
+		printf("%s\n", pos->sym.name);
+	}
+}
tools/perf/util/symbol.h +1 -0
index 80e569b..04614b0 100644
@@ -195,6 +195,7 @@ char dso__symtab_origin(const struct dso *self);
 void dso__set_long_name(struct dso *self, char *name);
 void dso__set_build_id(struct dso *self, void *build_id);
 void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine);
+void dso__list_available_symbols(struct dso *self, enum map_type type);
 struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr);
 struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type,
 					const char *name);
#16 lore raw

Re: [PATCHv8 2.6.35-rc4-tip 12/12] perf: Show Potential probe points.

Quoted 2 lines

Show all potential probes in a process by pid 21106 across all dsos

# perf probe -S -p 21106 | tail

Again, a file based interface would be much more useful. E.g. what possible probe points do I have in my qemu binary.

Btw, this doesn't mean I want to see the PID based variant removed, it can be very useful for debugging long running processes. I just don't think it's the most important / conveniant one.

#17 lore raw

Re: [PATCHv8 2.6.35-rc4-tip 12/12] perf: Show Potential probe points.

Quoted 6 lines
Quoted 3 lines

Show all potential probes in a process by pid 21106 across all dsos

# perf probe -S -p 21106 | tail

Again, a file based interface would be much more useful. E.g. what possible probe points do I have in my qemu binary.

Right, Currently perf probe needs -p option because it depend on thread->map_groups for listing the dsos and its functions.

I am not sure if perf already has ability to list functions in a file esp if we dont have dwarf information in that file. If perf has the ability I will reuse it here or will try implementing one.

Arnaldo, Do you know offhand if perf already has the ability to list functions in a file (with / without dwarf info).

Quoted 4 lines

Btw, this doesn't mean I want to see the PID based variant removed, it can be very useful for debugging long running processes. I just don't think it's the most important / conveniant one.

Agree.

--
Thanks and Regards
Srikar

#18 lore raw

Re: [PATCHv8 2.6.35-rc4-tip 12/12] perf: Show Potential probe points.

Quoted 7 lines · Srikar Dronamraju
Quoted 6 lines
Quoted 3 lines

Show all potential probes in a process by pid 21106 across all dsos

# perf probe -S -p 21106 | tail

Again, a file based interface would be much more useful. E.g. what possible probe points do I have in my qemu binary.

Quoted 6 lines

Right, Currently perf probe needs -p option because it depend on thread->map_groups for listing the dsos and its functions.

I am not sure if perf already has ability to list functions in a file esp if we dont have dwarf information in that file. If perf has the ability I will reuse it here or will try implementing one.

Excellent - this would increase usability very visibly.

People fundamentally like to work in the ASCII space: command names, function names, etc. People like to query these spaces to figure out what's available and use wildcards to define categories or limit queries.

PIDs and addresses are useful too - but it's mostly for computers or for odd-one-out cases: tools and the occasional need-something-on-the-PID-level lowlevel workflow.

Thanks,

Ingo

#19 lore raw

Re: [PATCHv8 2.6.35-rc4-tip 12/12] perf: Show Potential probe points.

In reply to Srikar Dronamraju

Em Fri, Jul 09, 2010 at 11:26:44AM +0530, Srikar Dronamraju escreveu:

Quoted 9 lines
Quoted 5 lines
Quoted 2 lines

Show all potential probes in a process by pid 21106 across all dsos

# perf probe -S -p 21106 | tail

Again, a file based interface would be much more useful. E.g. what possible probe points do I have in my qemu binary.

Right, Currently perf probe needs -p option because it depend on thread->map_groups for listing the dsos and its functions.

Quoted 6 lines

I am not sure if perf already has ability to list functions in a file esp if we dont have dwarf information in that file. If perf has the ability I will reuse it here or will try implementing one.

Arnaldo, Do you know offhand if perf already has the ability to list functions in a file (with / without dwarf info).

Definetely, it actually doesn't use DWARF at all, its just the symtabs that are used. It prefers -debuginfo packages because those have richer symtabs, but if just the stripped file is used it will try to use .dynsym, etc.

Look at tools/perf/builtin-test.c, it has a regression test for the symbol lib, should be enough.

- Arnaldo

#20 lore raw

Re: [PATCHv8 2.6.35-rc4-tip 12/12] perf: Show Potential probe points.

In reply to Srikar Dronamraju
Quoted 2 lines

Show all potentail probes in a process by pid 21106 limit to libc.so dso.

Actually It should have been

Show all potential probes in a process by pid 21106 limit to zsh dso.

Quoted 12 lines
# perf probe -S -p 21106 -D zsh | tail
zstrtol
ztrcmp
ztrdup
ztrduppfx
ztrftime
ztrlen
ztrncpy
ztrsub
zwarn
zwarnnam

Sorry for the mismatch.

--
Thanks and Regards
Srikar

#21 lore raw
In reply to Srikar Dronamraju

I can't actually get perf to build with these patches applied ontop of the -tip tree master branch:

CC util/probe-finder.o
til/probe-finder.c: In function 'alloc_trace_arg_ref':
util/probe-finder.c:412: error: invalid application of 'sizeof' to incomplete type 'struct kprobe_trace_arg_ref' util/probe-finder.c:414: error: dereferencing pointer to incomplete type
cc1: warnings being treated as errors
util/probe-finder.c: In function 'convert_variable_location':
util/probe-finder.c:428: error: initialization from incompatible pointertype util/probe-finder.c:444: error: dereferencing pointer to incomplete type
util/probe-finder.c:445: error: dereferencing pointer to incomplete type
util/probe-finder.c:447: error: dereferencing pointer to incomplete type
util/probe-finder.c:448: error: dereferencing pointer to incomplete type
util/probe-finder.c:449: error: dereferencing pointer to incomplete type
util/probe-finder.c:489: error: dereferencing pointer to incomplete type
util/probe-finder.c:490: error: dereferencing pointer to incomplete type
util/probe-finder.c:494: error: dereferencing pointer to incomplete type
util/probe-finder.c:495: error: dereferencing pointer to incomplete type
util/probe-finder.c: At top level:
util/probe-finder.c:503: error: 'struct kprobe_trace_arg' declared inside parameter list util/probe-finder.c:503: error: its scope is only this definition or declaration, which is probably not what you want util/probe-finder.c: In function 'convert_variable_type':
util/probe-finder.c:505: error: dereferencing pointer to incomplete type
util/probe-finder.c:513: error: dereferencing pointer to incomplete type
util/probe-finder.c:514: error: dereferencing pointer to incomplete type
util/probe-finder.c:541: error: dereferencing pointer to incomplete type
util/probe-finder.c:543: error: invalid application of 'sizeof' to incomplete type 'struct kprobe_trace_arg_ref' util/probe-finder.c:556: error: dereferencing pointer to incomplete type
util/probe-finder.c:557: error: dereferencing pointer to incomplete type
util/probe-finder.c:579: error: dereferencing pointer to incomplete type
util/probe-finder.c:580: error: dereferencing pointer to incomplete type
util/probe-finder.c: In function 'convert_variable_fields':
util/probe-finder.c:617: error: invalid application of 'sizeof' to incomplete type 'struct kprobe_trace_arg_ref' util/probe-finder.c: In function 'convert_variable':
util/probe-finder.c:718: error: passing argument 2 of 'convert_variable_type' from incompatible pointer type util/probe-finder.c:501: note: expected 'struct kprobe_trace_arg *' but
argument is of type 'struct probe_trace_arg *'
make: *** [util/probe-finder.o] Error 1

hch@brick:~/work/linux-2.6-tip/tools/perf$  
#22 lore raw

Thanks for trying and informing of the problem. This problem occurs when compiling perf with elfutils-devel > 0.138 installed. I am resending the patch 11/12 which was "[PATCHv8 2.6.35-rc4-tip 11/12]
perf: perf interface for uprobes"

I probably messed it up while merging to the latest tip/master.

--
Thanks
Srikar

Quoted 41 lines

I can't actually get perf to build with these patches applied ontop of the -tip tree master branch:

CC util/probe-finder.o
til/probe-finder.c: In function 'alloc_trace_arg_ref':
util/probe-finder.c:412: error: invalid application of 'sizeof' to incomplete type 'struct kprobe_trace_arg_ref' util/probe-finder.c:414: error: dereferencing pointer to incomplete type
cc1: warnings being treated as errors
util/probe-finder.c: In function 'convert_variable_location':
util/probe-finder.c:428: error: initialization from incompatible pointertype util/probe-finder.c:444: error: dereferencing pointer to incomplete type
util/probe-finder.c:445: error: dereferencing pointer to incomplete type
util/probe-finder.c:447: error: dereferencing pointer to incomplete type
util/probe-finder.c:448: error: dereferencing pointer to incomplete type
util/probe-finder.c:449: error: dereferencing pointer to incomplete type
util/probe-finder.c:489: error: dereferencing pointer to incomplete type
util/probe-finder.c:490: error: dereferencing pointer to incomplete type
util/probe-finder.c:494: error: dereferencing pointer to incomplete type
util/probe-finder.c:495: error: dereferencing pointer to incomplete type
util/probe-finder.c: At top level:
util/probe-finder.c:503: error: 'struct kprobe_trace_arg' declared inside parameter list util/probe-finder.c:503: error: its scope is only this definition or declaration, which is probably not what you want util/probe-finder.c: In function 'convert_variable_type':
util/probe-finder.c:505: error: dereferencing pointer to incomplete type
util/probe-finder.c:513: error: dereferencing pointer to incomplete type
util/probe-finder.c:514: error: dereferencing pointer to incomplete type
util/probe-finder.c:541: error: dereferencing pointer to incomplete type
util/probe-finder.c:543: error: invalid application of 'sizeof' to incomplete type 'struct kprobe_trace_arg_ref' util/probe-finder.c:556: error: dereferencing pointer to incomplete type
util/probe-finder.c:557: error: dereferencing pointer to incomplete type
util/probe-finder.c:579: error: dereferencing pointer to incomplete type
util/probe-finder.c:580: error: dereferencing pointer to incomplete type
util/probe-finder.c: In function 'convert_variable_fields':
util/probe-finder.c:617: error: invalid application of 'sizeof' to incomplete type 'struct kprobe_trace_arg_ref' util/probe-finder.c: In function 'convert_variable':
util/probe-finder.c:718: error: passing argument 2 of 'convert_variable_type' from incompatible pointer type util/probe-finder.c:501: note: expected 'struct kprobe_trace_arg *' but
argument is of type 'struct probe_trace_arg *'
make: *** [util/probe-finder.o] Error 1

hch@brick:~/work/linux-2.6-tip/tools/perf$