Skip to contentSkip to conversation

Uprobes Patches

PATCH Superseded Srikar Dronamraju 6 participants 51 messages Jul 27, 2010 – Aug 5, 2010

Subsystems (11)

v10 of 11 Superseded Latest is v11 →

lore
Share & tools
lore
#0 lore raw

v10 cover Uprobes Patches

Changelog from V9:
- Resolved comments from Arnaldo on perf support for uprobes.
- perf probe -S will now list only global binding functions as requested by Christoph Hellwig.
- Moved Changelog to below Signed-off-by: line, so that its not part of the patch description. (Suggested by Christoph.)

Changelog from V8:
- Fix build issues reported by Christoph.
- List available probes in a file without need to specify pid.

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/7/12/67,
http://lkml.org/lkml/2010/7/8/239, 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.
- 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(14)
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: rename common fields/functions from kprobe to probe. 11: perf: perf interface for uprobes
12: perf: Add third parameter to symbol_filter_t.
13: [RFC] perf: Show Potential probe points.
14: [RFC] perf: show functions in a file without using pid

 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         |  157 ++++
 kernel/trace/trace_uprobe.c        |  739 +++++++++++++++++++
 kernel/uprobes.c                   | 1396 ++++++++++++++++++++++++++++++++++++
 mm/ksm.c                           |  112 ---
 mm/memory.c                        |  120 +++
 tools/perf/builtin-probe.c         |   58 ++-
 tools/perf/builtin-test.c          |    4 +-
 tools/perf/builtin-top.c           |   26 +-
 tools/perf/util/event.c            |   20 +
 tools/perf/util/event.h            |    1 +
 tools/perf/util/map.h              |   31 +-
 tools/perf/util/probe-event.c      |  637 +++++++++++++----
 tools/perf/util/probe-event.h      |   38 +-
 tools/perf/util/probe-finder.c     |   34 +-
 tools/perf/util/probe-finder.h     |   10 +-
 tools/perf/util/symbol.c           |   32 +-
 tools/perf/util/symbol.h           |    2 +
 37 files changed, 5007 insertions(+), 1063 deletions(-)
#1 lore raw

PATCH v10 1/14 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 a2b4804..0fafef9 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 v10 2/14 uprobes: Breakpoint insertion/removal in user space applications.

In reply to Srikar Dronamraju

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.

---

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.

 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 v10 3/14 uprobes: Slot allocation for Execution out of line(XOL)

In reply to Srikar Dronamraju

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.

---

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.

 include/linux/uprobes.h |    2 
 kernel/uprobes.c        |  283 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 285 insertions(+), 0 deletions(-)
include/linux/uprobes.h +2 -0
index 44c23d6..f556b2d 100644
@@ -37,6 +37,8 @@ struct user_bkpt_task_arch_info {};
 struct 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 v10 4/14 uprobes: x86 specific functions for user space breakpointing.

In reply to Srikar Dronamraju

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

---

Changelog from V5: Merged into uprobes layer.

Changelog from V1:
set UPROBES_FIX_SLEEPY if post_xol might sleep.

 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 v10 5/14 uprobes: Uprobes (un)registration and exception handling.

In reply to Srikar Dronamraju

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.

---

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.

 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 4f2277f..4889779 100644
@@ -1492,6 +1492,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 v10 6/14 uprobes: X86 support for Uprobes

In reply to Srikar Dronamraju

Provides x86 specific details for uprobes.
This includes interrupt notifier for uprobes, enabling/disabling singlestep.

---

Changelog from V5: Using local_irq_enable() instead of
native_irq_enable and no more disabling irqs as suggested by Oleg Nesterov.

 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 v10 7/14 uprobes: Uprobes Documentation

In reply to Srikar Dronamraju

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 v10 8/14 trace: Extract out common code for kprobes/uprobes traceevents.

In reply to Srikar Dronamraju

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.

---

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.

 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  |  155 +++++++++
 5 files changed, 823 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 c7683fd..c681fa7 100644
@@ -364,6 +364,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)
@@ -376,6 +377,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 438e84a..eb11f7d 100644
@@ -53,5 +53,6 @@ endif
 obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
 obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.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 +155 -0

155 lines not on this page · raw message

#9 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 8/14] trace: Extract out common code for kprobes/uprobes traceevents.

Hi Srikar,

Quoted 8 lines · Srikar Dronamraju

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/trace_probe.c line 446

Quoted 3 lines
kernel/trace/trace_probe.c new file +3 -0
+/* Recursive argument parser */
+static int parse_probe_arg(char *arg, const struct fetch_type *t,
+		     struct fetch_param *f, int is_return, bool is_kprobe)

If you use "bool" for "is_kprobe", change "is_return" type too.

And, maybe you missed that the fetch function supports "string" type now, which needs a bit different manner for storing fetched value. You can find store_trace_args() function in trace_kprobe.c.

BTW, current fetch functions doesn't support fetching "paged-out" user-variables because kprobe can't sleep inside its handler.
However, user-space memory can be paged out, and I assume that uprobes allows its handler to I/O (and yield). If so, it can wait for accessing paged-out variable, can't it?

Thank you,

Signature · 4 lines
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: [email protected]
#10 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 8/14] trace: Extract out common code for kprobes/uprobes traceevents.

Quoted 8 lines
Quoted 2 lines

---

[...]

kernel/trace/trace_probe.c line 446

Quoted 3 lines
kernel/trace/trace_probe.c new file +3 -0
+/* Recursive argument parser */
+static int parse_probe_arg(char *arg, const struct fetch_type *t,
+		     struct fetch_param *f, int is_return, bool is_kprobe)

If you use "bool" for "is_kprobe", change "is_return" type too.

Okay.

Quoted 4 lines

And, maybe you missed that the fetch function supports "string" type now, which needs a bit different manner for storing fetched value. You can find store_trace_args() function in trace_kprobe.c.

Yes, I have seen your changes for supporting string type. Though all the fetch functions are in common code, uprobe based probes for now supports register fetching only. We have to add support for other types gradually. Please let me know if you see a reason to change the way we fetch even when we only support register type access.

Quoted 6 lines

BTW, current fetch functions doesn't support fetching "paged-out" user-variables because kprobe can't sleep inside its handler.
However, user-space memory can be paged out, and I assume that uprobes allows its handler to I/O (and yield). If so, it can wait for accessing paged-out variable, can't it?

Yes, the uprobes handler might sleep and hence we would have to handle accessing the paged-out user variables. When perf-uprobes starts supporting dwarf based probing, we should look into these issues. Currently its a todo.

--
Thanks and Regards
Srikar

#11 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 8/14] trace: Extract out common code for kprobes/uprobes traceevents.

Quoted 14 lines · Srikar Dronamraju
Quoted 6 lines
Quoted 1 line

---

[...]

kernel/trace/trace_probe.c line 446

Quoted 3 lines
kernel/trace/trace_probe.c new file +3 -0
+/* Recursive argument parser */
+static int parse_probe_arg(char *arg, const struct fetch_type *t,
+		     struct fetch_param *f, int is_return, bool is_kprobe)

If you use "bool" for "is_kprobe", change "is_return" type too.

Okay.

Quoted 3 lines

And, maybe you missed that the fetch function supports "string" type now, which needs a bit different manner for storing fetched value. You can find store_trace_args() function in trace_kprobe.c.

Quoted 5 lines

Yes, I have seen your changes for supporting string type. Though all the fetch functions are in common code, uprobe based probes for now supports register fetching only. We have to add support for other types gradually. Please let me know if you see a reason to change the way we fetch even when we only support register type access.

Ah, OK. So uprobe-tracer restricts specifying string type on register :)

Quoted 10 lines
Quoted 5 lines

BTW, current fetch functions doesn't support fetching "paged-out" user-variables because kprobe can't sleep inside its handler.
However, user-space memory can be paged out, and I assume that uprobes allows its handler to I/O (and yield). If so, it can wait for accessing paged-out variable, can't it?

Yes, the uprobes handler might sleep and hence we would have to handle accessing the paged-out user variables. When perf-uprobes starts supporting dwarf based probing, we should look into these issues. Currently its a todo.

Great!

Thank you,

Signature · 4 lines
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: [email protected]
#12 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 8/14] trace: Extract out common code for kprobes/uprobes traceevents.

In reply to Masami Hiramatsu
Quoted 3 lines

If you use "bool" for "is_kprobe", change "is_return" type too.

Masami,
Below patch should address the comments raised by you. Please let me know if this is fine with you.

--
Thanks and Regards
Srikar

---
From: Srikar Dronamraju <[email protected]>

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.

---

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.

 kernel/trace/Kconfig        |    4 
 kernel/trace/Makefile       |    1 
 kernel/trace/trace_kprobe.c |  752 +------------------------------------------
 kernel/trace/trace_probe.c  |  654 +++++++++++++++++++++++++++++++++++++
 kernel/trace/trace_probe.h  |  155 +++++++++
 5 files changed, 828 insertions(+), 738 deletions(-)
 create mode 100644 kernel/trace/trace_probe.c
 create mode 100644 kernel/trace/trace_probe.h
kernel/trace/Kconfig +4 -0
index c7683fd..c681fa7 100644
@@ -364,6 +364,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)
@@ -376,6 +377,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 438e84a..eb11f7d 100644
@@ -53,5 +53,6 @@ endif
 obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
 obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o
 obj-$(CONFIG_EVENT_TRACING) += power-traces.o
+obj-$(CONFIG_PROBE_EVENTS) +=trace_probe.o
 
 libftrace-y := ftrace.o
kernel/trace/trace_kprobe.c +14 -738

842 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 +155 -0

155 lines not on this page · raw message

#13 lore raw

PATCH v10 9/14 trace: uprobes trace_event interface

In reply to Srikar Dronamraju

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

---

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.

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 c681fa7..16e2a8c 100644
@@ -482,6 +482,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 eb11f7d..63d423b 100644
@@ -54,5 +54,6 @@ obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
 obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.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 d05c873..ad8a307 100644
@@ -97,6 +97,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 05da727..5b770e8 100644
@@ -48,6 +48,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)			\
@@ -64,6 +65,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

#14 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

Quoted 14 lines · Srikar Dronamraju
kernel/trace/Kconfig +6 -0
index c681fa7..16e2a8c 100644
@@ -482,6 +482,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

kernel/trace/Kconfig config RING_BUFFER_BENCHMARK · line 500

Quoted 10 lines
kernel/trace/Kconfig +10 -0
+	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.
+

Possible enhancement: Moving this config right after KPROBE_EVENT, because
those two provide similar dynamic events.

Thank you,

Signature · 4 lines
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: [email protected]
#15 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

Quoted 29 lines · Masami Hiramatsu
Quoted 14 lines · Srikar Dronamraju
kernel/trace/Kconfig +6 -0
index c681fa7..16e2a8c 100644
@@ -482,6 +482,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

kernel/trace/Kconfig config RING_BUFFER_BENCHMARK · line 500

Quoted 10 lines
kernel/trace/Kconfig +10 -0
+	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.
+

Possible enhancement: Moving this config right after KPROBE_EVENT, because
those two provide similar dynamic events.

Quoted 1 line

Thank you,

In fact this could be a menu "Dynamic Probes", perhaps default off, inside which Kprobes and Uprobes would be default on (but depend on "Dynamic Probes").

So that you can quickly enable them all in one.

#16 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

Quoted 29 lines · Frederic Weisbecker
Quoted 28 lines · Masami Hiramatsu
Quoted 14 lines · Srikar Dronamraju
kernel/trace/Kconfig +6 -0
index c681fa7..16e2a8c 100644
@@ -482,6 +482,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

kernel/trace/Kconfig config RING_BUFFER_BENCHMARK · line 500

Quoted 10 lines
kernel/trace/Kconfig +10 -0
+	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.
+

Possible enhancement: Moving this config right after KPROBE_EVENT, because
those two provide similar dynamic events.

Quoted 7 lines
Quoted 1 line

Thank you,

In fact this could be a menu "Dynamic Probes", perhaps default off, inside which Kprobes and Uprobes would be default on (but depend on "Dynamic Probes").

So that you can quickly enable them all in one.

Hmm, I disagree with it, because both Kprobes and Uprobes provides APIs for modules too.

I'd like to suggest below config tree

Kenrel hacking
- Kprobes
- Uprobes
- Tracing
-- Dynamic Events
depends on Kprobes || Uprobes
or

	select Kprobes && Uprobes

Thank you,

Signature · 4 lines
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: [email protected]
#17 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

Quoted 11 lines
Quoted 5 lines

In fact this could be a menu "Dynamic Probes", perhaps default off, inside which Kprobes and Uprobes would be default on (but depend on "Dynamic Probes").

So that you can quickly enable them all in one.

Hmm, I disagree with it, because both Kprobes and Uprobes provides APIs for modules too.

I'd like to suggest below config tree

Quoted 8 lines

Kenrel hacking
- Kprobes
- Uprobes
- Tracing
-- Dynamic Events
depends on Kprobes || Uprobes
or

	select Kprobes && Uprobes

I would agree with Masami since there could be people who might be apprehensive to try out Uprobes (which would still be experimental) but would be interested to use kprobes only since its more mature.

One change I would suggest would be to select respective events(i.e kprobe_event, uprobe_event) instead of kprobes and uprobes.

-
Thanks and Regards
Srikar

#18 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

Quoted 20 lines · Srikar Dronamraju
Quoted 11 lines
Quoted 5 lines

In fact this could be a menu "Dynamic Probes", perhaps default off, inside which Kprobes and Uprobes would be default on (but depend on "Dynamic Probes").

So that you can quickly enable them all in one.

Hmm, I disagree with it, because both Kprobes and Uprobes provides APIs for modules too.

I'd like to suggest below config tree

Quoted 8 lines

Kenrel hacking
- Kprobes
- Uprobes
- Tracing
-- Dynamic Events
depends on Kprobes || Uprobes
or

	select Kprobes && Uprobes
Quoted 6 lines

I would agree with Masami since there could be people who might be apprehensive to try out Uprobes (which would still be experimental) but would be interested to use kprobes only since its more mature.

One change I would suggest would be to select respective events(i.e kprobe_event, uprobe_event) instead of kprobes and uprobes.

Yeah sure. The goal was to still have both selectable independently, but have a menu that can select all in one.

ie:

config DYNAMIC_PROBE

	depends on (KPROBES || UPROBES) && EVENTS_TRACING
	default n

config KPROBES_EVENT:

	depends on DYNAMIC_PROBE && KPROBES
	default y

config UPROBES_EVENT:

	depends on DYNAMIC_PROBE && UPROBES
	default y

So that people who want dynamic probes just don't care and select dynamic probe. Those who want more granularity can still unselect uprobes events or kprobes events after that.

#19 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

In reply to Masami Hiramatsu
Quoted 33 lines · Masami Hiramatsu
Quoted 32 lines · Frederic Weisbecker
Quoted 29 lines · Masami Hiramatsu
Quoted 14 lines · Srikar Dronamraju
kernel/trace/Kconfig +6 -0
index c681fa7..16e2a8c 100644
@@ -482,6 +482,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

kernel/trace/Kconfig config RING_BUFFER_BENCHMARK · line 500

Quoted 10 lines
kernel/trace/Kconfig +10 -0
+	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.
+

Possible enhancement: Moving this config right after KPROBE_EVENT, because
those two provide similar dynamic events.

Thank you,

Quoted 7 lines
Quoted 4 lines

In fact this could be a menu "Dynamic Probes", perhaps default off, inside which Kprobes and Uprobes would be default on (but depend on "Dynamic Probes").

So that you can quickly enable them all in one.

Hmm, I disagree with it, because both Kprobes and Uprobes provides APIs for modules too.

I'm not sure there is a point in maintaining a leightweight version for out of tree code. These modules could just select kprobes/uprobes events as well.

As you prefer, that was just a suggestion to make it more simple.

Quoted 9 lines

I'd like to suggest below config tree

Kenrel hacking
- Kprobes
- Uprobes
- Tracing
-- Dynamic Events
depends on Kprobes || Uprobes

Yep, that version looks good.

#20 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

Quoted 39 lines · Frederic Weisbecker
Quoted 38 lines · Masami Hiramatsu
Quoted 36 lines · Frederic Weisbecker
Quoted 28 lines · Masami Hiramatsu
Quoted 14 lines · Srikar Dronamraju
kernel/trace/Kconfig +6 -0
index c681fa7..16e2a8c 100644
@@ -482,6 +482,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

kernel/trace/Kconfig config RING_BUFFER_BENCHMARK · line 500

Quoted 10 lines
kernel/trace/Kconfig +10 -0
+	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.
+

Possible enhancement: Moving this config right after KPROBE_EVENT, because
those two provide similar dynamic events.

Quoted 1 line

Thank you,

In fact this could be a menu "Dynamic Probes", perhaps default off, inside which Kprobes and Uprobes would be default on (but depend on "Dynamic Probes").

So that you can quickly enable them all in one.

Quoted 8 lines
Quoted 2 lines

Hmm, I disagree with it, because both Kprobes and Uprobes provides APIs for modules too.

I'm not sure there is a point in maintaining a leightweight version for out of tree code. These modules could just select kprobes/uprobes events as well.

As you prefer, that was just a suggestion to make it more simple.

The upstream policy always was that out of tree code does not exist as far as the kernel is concerned. So it is wrong to make the kernel crappier while helping out of tree code.

Thanks,

Ingo

#21 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

Quoted 7 lines · Ingo Molnar
Quoted 7 lines
Quoted 2 lines

Hmm, I disagree with it, because both Kprobes and Uprobes provides APIs for modules too.

I'm not sure there is a point in maintaining a leightweight version for out of tree code. These modules could just select kprobes/uprobes events as well.

Quoted 5 lines
Quoted 1 line

As you prefer, that was just a suggestion to make it more simple.

The upstream policy always was that out of tree code does not exist as far as the kernel is concerned. So it is wrong to make the kernel crappier while helping out of tree code.

Indeed. In addition to that the current version of uprobes does not actually have any exported symbols.

#22 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

Quoted 7 lines · Christoph Hellwig
Quoted 6 lines · Ingo Molnar
Quoted 6 lines
Quoted 2 lines

Hmm, I disagree with it, because both Kprobes and Uprobes provides APIs for modules too.

I'm not sure there is a point in maintaining a leightweight version for out of tree code. These modules could just select kprobes/uprobes events as well.

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

As you prefer, that was just a suggestion to make it more simple.

The upstream policy always was that out of tree code does not exist as far as the kernel is concerned. So it is wrong to make the kernel crappier while helping out of tree code.

Indeed. In addition to that the current version of uprobes does not actually have any exported symbols.

Ah, indeed. :-(

And then, it conflicts with the description about uprobes in Documentation/uprobes.txt:

Review

Quoted 4 lines
(quoted diff) +4 -0
+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.

So, that could be a bug.

Anyway, at least kprobes has some sample modules under samples/kprobes/. Aren't they in-tree consumers of kprobes?

Thank you,

Signature · 4 lines
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: [email protected]
#23 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

Quoted 4 lines · Masami Hiramatsu

So, that could be a bug.

Anyway, at least kprobes has some sample modules under samples/kprobes/. Aren't they in-tree consumers of kprobes?

We have quite a few kprobes users in the kernel, just no really useful modular ones. We have a couple of useful users of jprobes, which are the more useful kprobes variants in modules. All of them might better be converted to trace events, but those weren't around when they were added.

#24 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

In reply to Srikar Dronamraju
Quoted 14 lines · Srikar Dronamraju
kernel/trace/Kconfig +6 -0
index c681fa7..16e2a8c 100644
@@ -482,6 +482,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

kernel/trace/Kconfig config RING_BUFFER_BENCHMARK · line 500

Quoted 10 lines
kernel/trace/Kconfig +10 -0
+	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.
+

Possible enhancement: Moving this config right after KPROBE_EVENT, because
those two provide similar dynamic events.

Thank you,

Signature · 4 lines
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: [email protected]
#25 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

Quoted 3 lines

Possible enhancement: Moving this config right after KPROBE_EVENT, because
those two provide similar dynamic events.

Agree.

--
Thanks and Regards
Srikar

#26 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

In reply to Masami Hiramatsu
Quoted 4 lines

Possible enhancement: Moving this config right after KPROBE_EVENT, because
those two provide similar dynamic events.

Masami,
Below patch should address the comments raised by you.

--
Thanks and Regards
Srikar

---
From: Srikar Dronamraju <[email protected]>

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

---

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.

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 c681fa7..c77ba2d 100644
@@ -377,6 +377,22 @@ 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 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.
+
 config PROBE_EVENTS
 	def_bool n
 
kernel/trace/Makefile +1 -0
index eb11f7d..63d423b 100644
@@ -54,5 +54,6 @@ obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
 obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.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 d05c873..ad8a307 100644
@@ -97,6 +97,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 b3e30dc..d905386 100644
@@ -48,6 +48,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)			\
@@ -64,6 +65,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

#27 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 9/14] trace: uprobes trace_event interface

Quoted 118 lines · Srikar Dronamraju
Quoted 4 lines

Possible enhancement: Moving this config right after KPROBE_EVENT, because
those two provide similar dynamic events.

Masami,
Below patch should address the comments raised by you.

--
Thanks and Regards
Srikar

---
From: Srikar Dronamraju <[email protected]>

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

---

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.

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 +6 -0
index c681fa7..c77ba2d 100644
@@ -377,6 +377,22 @@ 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 UPROBE_EVENT
+	bool "Enable uprobes-based dynamic events"
+	depends on ARCH_SUPPORTS_UPROBES
+	depends on MMU
+	select UPROBES
+	select PROBE_EVENTS

kernel/trace/Kconfig config KPROBE_EVENT · line 395

Quoted 10 lines
kernel/trace/Kconfig +10 -0
+	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.
+

Why did you split CONFIG_UPROBES and CONFIG_UPROBE_EVENT? Is there another kind of use of uprobes than through "trace events"?

Hmm, speaking about it, I think kprobes has the same problem. In fact now I remember I noticed it by the past but we found another user of kprobes, mostly unused I guess.

Anyway, uprobes config itself doesn't need to be split from uprobes events.

Also, what about the "Dynamic Probes" menu I proposed? (it's possibly a crappy idea, I don't know).

#28 lore raw

PATCH v10 10/14 perf: rename common fields/functions from kprobe to probe.

In reply to Srikar Dronamraju

As a precursor for perf to support uprobes, rename fields/functions that had kprobe in their name but can be shared across perf-kprobes and perf-uprobes to probe.

---

 tools/perf/builtin-probe.c     |    1 
 tools/perf/util/probe-event.c  |  136 +++++++++++++++++++++-------------------
 tools/perf/util/probe-event.h  |   27 +++-----
 tools/perf/util/probe-finder.c |   34 +++++-----
 tools/perf/util/probe-finder.h |   10 +--
 5 files changed, 102 insertions(+), 106 deletions(-)
tools/perf/builtin-probe.c +0 -1
index 5455186..199d5e1 100644
@@ -267,4 +267,3 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 	}
 	return 0;
 }
-
tools/perf/util/probe-event.c +70 -66

425 lines not on this page · raw message

tools/perf/util/probe-event.h +10 -17
index ed362ac..5af3924 100644
@@ -7,33 +7,33 @@
 extern bool probe_event_dry_run;
 
 /* kprobe-tracer tracing point */
-struct kprobe_trace_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 {
+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 {
+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 */
+	struct probe_trace_arg		*args;	/* Arguments */
 };
 
 /* Perf probe probing point */
@@ -93,25 +93,18 @@ struct line_range {
 /* Command string to events */
 extern int parse_perf_probe_command(const char *cmd,
 				    struct perf_probe_event *pev);
-extern int parse_kprobe_trace_command(const char *cmd,
-				      struct kprobe_trace_event *tev);
 
 /* Events to command string */
 extern char *synthesize_perf_probe_command(struct perf_probe_event *pev);
-extern char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev);
+extern char *synthesize_probe_trace_command(struct probe_trace_event *tev);
 extern int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf,
 				     size_t len);
 
 /* Check the perf_probe_event needs debuginfo */
 extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
 
-/* Convert from kprobe_trace_event to perf_probe_event */
-extern int convert_to_perf_probe_event(struct kprobe_trace_event *tev,
-				       struct perf_probe_event *pev);
-
 /* Release event contents */
 extern void clear_perf_probe_event(struct perf_probe_event *pev);
-extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev);
 
 /* Command string to line-range */
 extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
tools/perf/util/probe-finder.c +17 -17
index f88070e..840f1aa 100644
@@ -366,10 +366,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;
@@ -385,7 +385,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 */
@@ -459,10 +459,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;
@@ -500,7 +500,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;
@@ -545,10 +545,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;
@@ -574,7 +574,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)
@@ -605,7 +605,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)
@@ -738,7 +738,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;
@@ -803,7 +803,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++) {
@@ -1060,9 +1060,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;
@@ -1072,7 +1072,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 {
#29 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 10/14] perf: rename common fields/functions from kprobe to probe.

Quoted 3 lines · Srikar Dronamraju

As a precursor for perf to support uprobes, rename fields/functions that had kprobe in their name but can be shared across perf-kprobes and perf-uprobes to probe.

Yeah, renaming itself is OK for me. But please do it carefully, I can see some gaps between 1st line and 2nd line like below after applying this patch...

static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
struct perf_probe_point *pp)

But just a trivial style issue. :)

Signature · 4 lines
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: [email protected]
#30 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 10/14] perf: rename common fields/functions from kprobe to probe.

Masami,
Below patch should address the comments raised by you.

Ingo, Arnaldo,
Please let me know if you want this to be sent as a new patchset.

--
Thanks and Regards
Srikar

---
From: Srikar Dronamraju <[email protected]>

As a precursor for perf to support uprobes, rename fields/functions that had kprobe in their name but can be shared across perf-kprobes and perf-uprobes to probe.

---

 tools/perf/builtin-probe.c     |    1 
 tools/perf/util/probe-event.c  |  135 ++++++++++++++++++++--------------------
 tools/perf/util/probe-event.h  |   27 +++-----
 tools/perf/util/probe-finder.c |   34 +++++-----
 tools/perf/util/probe-finder.h |   10 +--
 5 files changed, 101 insertions(+), 106 deletions(-)
tools/perf/builtin-probe.c +0 -1
index 5455186..199d5e1 100644
@@ -267,4 +267,3 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 	}
 	return 0;
 }
-
tools/perf/util/probe-event.c +69 -66

424 lines not on this page · raw message

tools/perf/util/probe-event.h +10 -17
index ed362ac..5af3924 100644
@@ -7,33 +7,33 @@
 extern bool probe_event_dry_run;
 
 /* kprobe-tracer tracing point */
-struct kprobe_trace_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 {
+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 {
+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 */
+	struct probe_trace_arg		*args;	/* Arguments */
 };
 
 /* Perf probe probing point */
@@ -93,25 +93,18 @@ struct line_range {
 /* Command string to events */
 extern int parse_perf_probe_command(const char *cmd,
 				    struct perf_probe_event *pev);
-extern int parse_kprobe_trace_command(const char *cmd,
-				      struct kprobe_trace_event *tev);
 
 /* Events to command string */
 extern char *synthesize_perf_probe_command(struct perf_probe_event *pev);
-extern char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev);
+extern char *synthesize_probe_trace_command(struct probe_trace_event *tev);
 extern int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf,
 				     size_t len);
 
 /* Check the perf_probe_event needs debuginfo */
 extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
 
-/* Convert from kprobe_trace_event to perf_probe_event */
-extern int convert_to_perf_probe_event(struct kprobe_trace_event *tev,
-				       struct perf_probe_event *pev);
-
 /* Release event contents */
 extern void clear_perf_probe_event(struct perf_probe_event *pev);
-extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev);
 
 /* Command string to line-range */
 extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
tools/perf/util/probe-finder.c +17 -17
index f88070e..840f1aa 100644
@@ -366,10 +366,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;
@@ -385,7 +385,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 */
@@ -459,10 +459,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;
@@ -500,7 +500,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;
@@ -545,10 +545,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;
@@ -574,7 +574,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)
@@ -605,7 +605,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)
@@ -738,7 +738,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;
@@ -803,7 +803,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++) {
@@ -1060,9 +1060,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;
@@ -1072,7 +1072,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 {
#31 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 10/14] perf: rename common fields/functions from kprobe to probe.

Em Thu, Jul 29, 2010 at 07:43:51PM +0530, Srikar Dronamraju escreveu:

Quoted 5 lines

Masami,
Below patch should address the comments raised by you.

Ingo, Arnaldo,
Please let me know if you want this to be sent as a new patchset.

I'll try and cherrypick this one for perf/core,

Thanks,

- Arnaldo

#32 lore raw

[tip:perf/core] perf probe: Rename common fields/functions from kprobe to probe.

In reply to Srikar Dronamraju
Commit-ID:  0e60836bbd392300198c5c2d918c18845428a1fe
Gitweb:     http://git.kernel.org/tip/0e60836bbd392300198c5c2d918c18845428a1fe
Author:     Srikar Dronamraju <[email protected]>
AuthorDate: Thu, 29 Jul 2010 19:43:51 +0530
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Fri, 30 Jul 2010 12:01:38 -0300

perf probe: Rename common fields/functions from kprobe to probe.

As a precursor for perf to support uprobes, rename fields/functions that had kprobe in their name but can be shared across perf-kprobes and perf-uprobes to probe.

Cc: Ananth N Mavinakayanahalli <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Cc: "Frank Ch. Eigler" <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jim Keniston <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Mark Wielaard <[email protected]>
Cc: Mathieu Desnoyers <[email protected]>
Cc: Naren A Devaiah <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: "Paul E. McKenney" <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Steven Rostedt <[email protected]>
LKML-Reference: <[email protected]>

---
 tools/perf/builtin-probe.c     |    1 -
 tools/perf/util/probe-event.c  |  135 ++++++++++++++++++++-------------------
 tools/perf/util/probe-event.h  |   27 +++-----
 tools/perf/util/probe-finder.c |   34 +++++-----
 tools/perf/util/probe-finder.h |   10 ++--
 5 files changed, 101 insertions(+), 106 deletions(-)
tools/perf/builtin-probe.c +0 -1
index 5455186..199d5e1 100644
@@ -267,4 +267,3 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 	}
 	return 0;
 }
-
tools/perf/util/probe-event.c +69 -66

424 lines not on this page · raw message

tools/perf/util/probe-event.h +10 -17
index ed362ac..5af3924 100644
@@ -7,33 +7,33 @@
 extern bool probe_event_dry_run;
 
 /* kprobe-tracer tracing point */
-struct kprobe_trace_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 {
+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 {
+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 */
+	struct probe_trace_arg		*args;	/* Arguments */
 };
 
 /* Perf probe probing point */
@@ -93,25 +93,18 @@ struct line_range {
 /* Command string to events */
 extern int parse_perf_probe_command(const char *cmd,
 				    struct perf_probe_event *pev);
-extern int parse_kprobe_trace_command(const char *cmd,
-				      struct kprobe_trace_event *tev);
 
 /* Events to command string */
 extern char *synthesize_perf_probe_command(struct perf_probe_event *pev);
-extern char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev);
+extern char *synthesize_probe_trace_command(struct probe_trace_event *tev);
 extern int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf,
 				     size_t len);
 
 /* Check the perf_probe_event needs debuginfo */
 extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
 
-/* Convert from kprobe_trace_event to perf_probe_event */
-extern int convert_to_perf_probe_event(struct kprobe_trace_event *tev,
-				       struct perf_probe_event *pev);
-
 /* Release event contents */
 extern void clear_perf_probe_event(struct perf_probe_event *pev);
-extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev);
 
 /* Command string to line-range */
 extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
tools/perf/util/probe-finder.c +17 -17
index f88070e..840f1aa 100644
@@ -366,10 +366,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;
@@ -385,7 +385,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 */
@@ -459,10 +459,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;
@@ -500,7 +500,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;
@@ -545,10 +545,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;
@@ -574,7 +574,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)
@@ -605,7 +605,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)
@@ -738,7 +738,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;
@@ -803,7 +803,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++) {
@@ -1060,9 +1060,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;
@@ -1072,7 +1072,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 {
#33 lore raw

PATCH v10 11/14 perf: perf interface for uprobes

In reply to Srikar Dronamraju

Enhances perf probe to accept pid and user vaddr.
Provides very basic support for uprobes.

TODO:
Update perf-probes.txt.
Global tracing.

---

Changelog from v9: Renaming common fields/functions to refer to probe instead of kprobe. This was suggested by Arnaldo.

Changelog from v8: Fixed a build break 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.

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    |   12 +
 tools/perf/builtin-top.c      |   20 --
 tools/perf/util/event.c       |   20 ++
 tools/perf/util/event.h       |    1 
 tools/perf/util/probe-event.c |  395 +++++++++++++++++++++++++++++++++--------
 tools/perf/util/probe-event.h |   10 +
 6 files changed, 352 insertions(+), 106 deletions(-)
tools/perf/builtin-probe.c +10 -2
index 199d5e1..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);
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 +315 -80

612 lines not on this page · raw message

tools/perf/util/probe-event.h +6 -4
index 5af3924..27f052c 100644
@@ -6,7 +6,7 @@
 
 extern bool probe_event_dry_run;
 
-/* kprobe-tracer tracing point */
+/* kprobe-tracer and uprobe-tracer tracing point */
 struct probe_trace_point {
 	char		*symbol;	/* Base symbol */
 	unsigned long	offset;		/* Offset from symbol */
@@ -19,7 +19,7 @@ struct probe_trace_arg_ref {
 	long				offset;	/* Offset value */
 };
 
-/* kprobe-tracer tracing argument */
+/* kprobe-tracer and uprobe-tracer tracing argument */
 struct probe_trace_arg {
 	char				*name;	/* Argument name */
 	char				*value;	/* Base value */
@@ -27,12 +27,13 @@ struct probe_trace_arg {
 	struct probe_trace_arg_ref	*ref;	/* Referencing offset */
 };
 
-/* kprobe-tracer tracing event (point + arg) */
+/* kprobe-tracer and uprobe-tracer tracing event (point + arg) */
 struct probe_trace_event {
 	char				*event;	/* Event name */
 	char				*group;	/* Group name */
 	struct probe_trace_point	point;	/* Trace point */
 	int				nargs;	/* Number of args */
+	pid_t				upid;	/* uprobes only */
 	struct probe_trace_arg		*args;	/* Arguments */
 };
 
@@ -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 */
 };
 
@@ -112,7 +114,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);
 
#34 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 11/14] perf: perf interface for uprobes

Hi Srikar,

Quoted 2 lines · Srikar Dronamraju

Enhances perf probe to accept pid and user vaddr.
Provides very basic support for uprobes.

[...]

tools/perf/util/probe-event.c static int try_to_find_probe_trace_events(struct perf_probe_event *pev, · line 195

Quoted 7 lines
tools/perf/util/probe-event.c +3 -0
@@ -162,6 +190,14 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
 	bool need_dwarf = perf_probe_event_need_dwarf(pev);
 	int fd, ntevs;
 
+	if (pev->upid) {
+		if (need_dwarf) {
+			pr_warning("Debuginfo-analysis is not supported.\n");

This should be "Debuginfo-analysis is not supported with -p/--pid option.\n"

tools/perf/util/probe-event.c static int try_to_find_probe_trace_events(struct perf_probe_event *pev, · line 200

Quoted 5 lines
tools/perf/util/probe-event.c +5 -0
+			return -ENOSYS;
+		}
+		return convert_name_to_addr(pev);
+	}
+

And I found a small bug.

# ./perf probe -vf -p 3199 "setenv %ax"
probe-definition(0): setenv %ax
symbol:setenv file:(null) line:0 offset:0 return:0 lazy:(null)
parsing arg: %ax into %ax
1 arguments
Opening /debug/tracing/uprobe_events write=1
Add new event:
Writing event: p:probe_3199/setenv 3199:0x47e680
 %ax
Failed to write event: Invalid argument
  Error: Failed to add events. (-1)
# ./perf probe -l
  probe_3199:setenv    (on 3199:0x000000000047e680)

When writing an event, there is a "\n" right after probe point (3199:0x47e680\n)

tools/perf/util/probe-event.c char *synthesize_probe_trace_command(struct probe_trace_event *tev) · line 1217

Quoted 10 lines
tools/perf/util/probe-event.c +2 -4
@@ -1066,10 +1213,22 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
 	if (buf == NULL)
 		return NULL;
 
-	len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu",
-			 tp->retprobe ? 'r' : 'p',
-			 tev->group, tev->event,
-			 tp->symbol, tp->offset);
+	if (tev->upid)
+		len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %d:%s\n",

Here is a "\n".

Thank you,

Signature · 4 lines
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: [email protected]
#35 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 11/14] perf: perf interface for uprobes

Masami,
Below patch should address the comments raised by you.

--
Thanks and Regards
Srikar

---
From: Srikar Dronamraju <[email protected]>

Enhances perf probe to accept pid and user vaddr.
Provides very basic support for uprobes.

TODO:
Update perf-probes.txt.
Global tracing.

---

Changelog from v9: Renaming common fields/functions to refer to probe instead of kprobe. This was suggested by Arnaldo.

Changelog from v8: Fixed a build break 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.

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    |   12 +
 tools/perf/builtin-top.c      |   20 --
 tools/perf/util/event.c       |   20 ++
 tools/perf/util/event.h       |    1 
 tools/perf/util/probe-event.c |  396 +++++++++++++++++++++++++++++++++--------
 tools/perf/util/probe-event.h |   10 +
 6 files changed, 353 insertions(+), 106 deletions(-)
tools/perf/builtin-probe.c +10 -2
index 199d5e1..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);
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 +316 -80

613 lines not on this page · raw message

tools/perf/util/probe-event.h +6 -4
index 5af3924..27f052c 100644
@@ -6,7 +6,7 @@
 
 extern bool probe_event_dry_run;
 
-/* kprobe-tracer tracing point */
+/* kprobe-tracer and uprobe-tracer tracing point */
 struct probe_trace_point {
 	char		*symbol;	/* Base symbol */
 	unsigned long	offset;		/* Offset from symbol */
@@ -19,7 +19,7 @@ struct probe_trace_arg_ref {
 	long				offset;	/* Offset value */
 };
 
-/* kprobe-tracer tracing argument */
+/* kprobe-tracer and uprobe-tracer tracing argument */
 struct probe_trace_arg {
 	char				*name;	/* Argument name */
 	char				*value;	/* Base value */
@@ -27,12 +27,13 @@ struct probe_trace_arg {
 	struct probe_trace_arg_ref	*ref;	/* Referencing offset */
 };
 
-/* kprobe-tracer tracing event (point + arg) */
+/* kprobe-tracer and uprobe-tracer tracing event (point + arg) */
 struct probe_trace_event {
 	char				*event;	/* Event name */
 	char				*group;	/* Group name */
 	struct probe_trace_point	point;	/* Trace point */
 	int				nargs;	/* Number of args */
+	pid_t				upid;	/* uprobes only */
 	struct probe_trace_arg		*args;	/* Arguments */
 };
 
@@ -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 */
 };
 
@@ -112,7 +114,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);
 
#36 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 11/14] perf: perf interface for uprobes

In reply to Srikar Dronamraju

Em Tue, Jul 27, 2010 at 04:41:05PM +0530, Srikar Dronamraju escreveu:

tools/perf/builtin-probe.c static const struct option options[] = { · line 194

Quoted 9 lines

Enhances perf probe to accept pid and user vaddr.
Provides very basic support for uprobes.

tools/perf/builtin-probe.c +2 -0
@@ -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"),

"ubrobes based probe" could be made clear as:

"Specify pid of process where the probe will be added"

?

The following three hunks could be moved to a separate patch that I'd apply on my perf/core branch, so to reduce this patchset size, like I did with the s/kprobe/probe/g one that is already there:

http://git.kernel.org/?p=linux/kernel/git/acme/linux-2.6.git;a=commitdiff;h=0e60836bbd392300198c5c2d918c18845428a1fe

Quoted 74 lines
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,

[...]

Quoted 4 lines
tools/perf/util/event.h +1 -1
 			group = pev->group;
-		else
+		else if (!pev->upid)
 			group = PERFPROBE_GROUP;

tools/perf/util/event.h

Quoted 10 lines
tools/perf/util/event.h +10 -0
+		else {
+			/*
+			 * For uprobes based probes create a group
+			 * probe_<pid>.
+			 */
+			snprintf(buf, 64, "%s_%d", PERFPROBE_GROUP, pev->upid);
+			group = buf;
+		}
+
+		tev->group = strdup(group);

Here you don't check as you do on the next strdups

Quoted 10 lines
tools/perf/util/event.h +6 -0
+		if (pev->event)
+			event = pev->event;
+		else if (pev->point.function)
+			event = pev->point.function;
+		else
+			event = tev->point.symbol;
 
 		/* Get an unused new event name */
 		ret = get_new_event_name(buf, 64, event,

tools/perf/util/event.h static int __add_probe_trace_events(struct perf_probe_event *pev, · line 1685

Quoted 7 lines
tools/perf/util/event.h +1 -2
@@ -1471,9 +1681,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 		if (ret < 0)
 			break;
 		event = buf;
-
 		tev->event = strdup(event);
-		tev->group = strdup(group);
+

here

Quoted 26 lines
tools/perf/util/event.h +6 -1
 		if (tev->event == NULL || tev->group == NULL) {
 			ret = -ENOMEM;
 			break;
@@ -1571,6 +1780,11 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 		}
 	}
 
+	if (pev->upid) {
+		tev->upid = pev->upid;
+		return 1;
+	}
+
 	/* Currently just checking function name from symbol map */
 	sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION],
 				       tev->point.symbol, NULL);
@@ -1598,15 +1812,19 @@ struct __event_package {
 int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
 			  bool force_add, int max_tevs)
 {
-	int i, j, ret;
+	int i, j, ret = 0;
 	struct __event_package *pkgs;
 
 	pkgs = zalloc(sizeof(struct __event_package) * npevs);
 	if (pkgs == NULL)
 		return -ENOMEM;

tools/perf/util/event.h struct __event_package { · line 1828

Quoted 10 lines
tools/perf/util/event.h +6 -2
 
-	/* Init vmlinux path */
-	ret = init_vmlinux();
+	if (!pevs->upid)
+		/* Init vmlinux path */
+		ret = init_vmlinux();
+	else
+		ret = init_perf_uprobes();
+
 	if (ret < 0)

pkgs leaks here.

Quoted 5 lines
tools/perf/util/event.h +0 -0
 		return ret;
 
@@ -1666,23 +1884,15 @@ error:
 	return ret;
 }
#37 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 11/14] perf: perf interface for uprobes

Quoted 7 lines

tools/perf/builtin-probe.c static const struct option options[] = { · line 194

Quoted 3 lines
tools/perf/builtin-probe.c +2 -0
 		 "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"),

"ubrobes based probe" could be made clear as:

"Specify pid of process where the probe will be added"

Okay . will do.

Quoted 9 lines

?

The following three hunks could be moved to a separate patch that I'd apply on my perf/core branch, so to reduce this patchset size, like I did with the s/kprobe/probe/g one that is already there:

http://git.kernel.org/?p=linux/kernel/git/acme/linux-2.6.git;a=commitdiff;h=0e60836bbd392300198c5c2d918c18845428a1fe

[snipped]

Okay, I can make a separate patch of those three hunks and send it out.

Quoted 17 lines
Quoted 5 lines
tools/perf/util/probe-event.c +1 -1
 			group = pev->group;
-		else
+		else if (!pev->upid)
 			group = PERFPROBE_GROUP;

tools/perf/util/probe-event.c static int __add_probe_trace_events(struct perf_probe_event *pev, · line 1669

Quoted 10 lines
tools/perf/util/probe-event.c +10 -0
+		else {
+			/*
+			 * For uprobes based probes create a group
+			 * probe_<pid>.
+			 */
+			snprintf(buf, 64, "%s_%d", PERFPROBE_GROUP, pev->upid);
+			group = buf;
+		}
+
+		tev->group = strdup(group);

Here you don't check as you do on the next strdups

Actually tev->group gets checked where tev->event gets checked. However I had moved assigning tev->group to where group gets assigned. This probably is causing the confusion. I will move the assignment to where tev->event gets assigned.

Quoted 8 lines

tools/perf/util/probe-event.c static int __add_probe_trace_events(struct perf_probe_event *pev, · line 1685

Quoted 6 lines
tools/perf/util/probe-event.c +1 -2
 			break;
 		event = buf;
-
 		tev->event = strdup(event);
-		tev->group = strdup(group);
+

here

This strdup(group) was moved ahead by few lines. I can move it back here it makes things more clear.

Quoted 14 lines
Quoted 14 lines
tools/perf/util/probe-event.c +1 -1
 				       tev->point.symbol, NULL);
@@ -1598,15 +1812,19 @@ struct __event_package {
 int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
 			  bool force_add, int max_tevs)
 {
-	int i, j, ret;
+	int i, j, ret = 0;
 	struct __event_package *pkgs;
 
 	pkgs = zalloc(sizeof(struct __event_package) * npevs);
 	if (pkgs == NULL)
 		return -ENOMEM;
 
Quoted 11 lines

tools/perf/util/probe-event.c struct __event_package { · line 1828

Quoted 9 lines
tools/perf/util/probe-event.c +6 -2
-	/* Init vmlinux path */
-	ret = init_vmlinux();
+	if (!pevs->upid)
+		/* Init vmlinux path */
+		ret = init_vmlinux();
+	else
+		ret = init_perf_uprobes();
+
 	if (ret < 0)

pkgs leaks here.

Right, but I dont think this leak was introduced by my patch(s). I guess its better fixed by a different patch.

Quoted 1 line

--
Thanks and Regards
Srikar

#38 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 11/14] perf: perf interface for uprobes

Em Sat, Jul 31, 2010 at 08:27:48AM +0530, Srikar Dronamraju escreveu:

Quoted 24 lines
Quoted 12 lines
Quoted 12 lines
tools/perf/util/probe-event.c +1 -1
@@ -1598,15 +1812,19 @@ struct __event_package {
 int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
 			  bool force_add, int max_tevs)
 {
-	int i, j, ret;
+	int i, j, ret = 0;
 	struct __event_package *pkgs;
 
 	pkgs = zalloc(sizeof(struct __event_package) * npevs);
 	if (pkgs == NULL)
 		return -ENOMEM;
 
Quoted 11 lines

tools/perf/util/probe-event.c struct __event_package { · line 1828

Quoted 9 lines
tools/perf/util/probe-event.c +6 -2
-	/* Init vmlinux path */
-	ret = init_vmlinux();
+	if (!pevs->upid)
+		/* Init vmlinux path */
+		ret = init_vmlinux();
+	else
+		ret = init_perf_uprobes();
+
 	if (ret < 0)

pkgs leaks here.

Quoted 2 lines

Right, but I dont think this leak was introduced by my patch(s). I guess its better fixed by a different patch.

Sorry, will fix that then on a separate patch.

- Arnaldo

#39 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 11/14] perf: perf interface for uprobes

Quoted 23 lines · Arnaldo Carvalho de Melo

Em Sat, Jul 31, 2010 at 08:27:48AM +0530, Srikar Dronamraju escreveu:

Quoted 22 lines
Quoted 22 lines
Quoted 11 lines
tools/perf/util/probe-event.c +1 -1
@@ -1598,15 +1812,19 @@ struct __event_package {
 int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
 			  bool force_add, int max_tevs)
 {
-	int i, j, ret;
+	int i, j, ret = 0;
 	struct __event_package *pkgs;
 
 	pkgs = zalloc(sizeof(struct __event_package) * npevs);
 	if (pkgs == NULL)
 		return -ENOMEM;

tools/perf/util/probe-event.c struct __event_package { · line 1828

Quoted 10 lines
tools/perf/util/probe-event.c +6 -2
 
-	/* Init vmlinux path */
-	ret = init_vmlinux();
+	if (!pevs->upid)
+		/* Init vmlinux path */
+		ret = init_vmlinux();
+	else
+		ret = init_perf_uprobes();
+
 	if (ret < 0)

pkgs leaks here.

Quoted 4 lines
Quoted 2 lines

Right, but I dont think this leak was introduced by my patch(s). I guess its better fixed by a different patch.

Sorry, will fix that then on a separate patch.

Yes, sorry, that was introduced by me...

Thanks for pointing it out.

Signature · 4 lines
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: [email protected]
#40 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 11/14] perf: perf interface for uprobes

In reply to Arnaldo Carvalho de Melo

Hi Arnaldo,

Quoted 6 lines

The following three hunks could be moved to a separate patch that I'd apply on my perf/core branch, so to reduce this patchset size, like I did with the s/kprobe/probe/g one that is already there:

http://git.kernel.org/?p=linux/kernel/git/acme/linux-2.6.git;a=commitdiff;h=0e60836bbd392300198c5c2d918c18845428a1fe

I will soon 2 patches instead of this patch splitting the 3 hunks into a new patch and the resuting patch after removing the previous 3 hunks.

-Srikar

#41 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 11/14] perf: perf interface for uprobes

Em Mon, Aug 02, 2010 at 05:57:14PM +0530, Srikar Dronamraju escreveu:

Quoted 4 lines

Hi Arnaldo,

Quoted 1 line
Quoted 8 lines
Quoted 5 lines

The following three hunks could be moved to a separate patch that I'd apply on my perf/core branch, so to reduce this patchset size, like I did with the s/kprobe/probe/g one that is already there:

http://git.kernel.org/?p=linux/kernel/git/acme/linux-2.6.git;a=commitdiff;h=0e60836bbd392300198c5c2d918c18845428a1fe

I will soon 2 patches instead of this patch splitting the 3 hunks into a new patch and the resuting patch after removing the previous 3 hunks.

Thanks, I'm just trying to erode the patchset by merging the completely uncontentious hunks. :)

- Arnaldo

#42 lore raw

PATCH 1/1 perf: expose event__process function

In reply to Arnaldo Carvalho de Melo

event__process is useful in processing /proc/<pid>/maps. All of the functions that are called from event__process are defined in util/event.c. Though its defined in builtin-top.c, it could be reused for perf probe for uprobes. Hence moving it to util/event.c and exporting the function.

---

 tools/perf/builtin-top.c |   20 --------------------
 tools/perf/util/event.c  |   20 ++++++++++++++++++++
 tools/perf/util/event.h  |    1 +
 3 files changed, 21 insertions(+), 20 deletions(-)
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 6b0db55..08b6424 100644
@@ -554,6 +554,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,
#43 lore raw

[tip:perf/core] perf: expose event__process function

Commit-ID:  b83f920e179101a54721e5ab1d6c3edfb9d4bcbb
Gitweb:     http://git.kernel.org/tip/b83f920e179101a54721e5ab1d6c3edfb9d4bcbb
Author:     Srikar Dronamraju <[email protected]>
AuthorDate: Mon, 2 Aug 2010 18:08:51 +0530
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 4 Aug 2010 12:41:23 -0300

perf: expose event__process function

The event__process function is useful in processing /proc/<pid>/maps. All of the functions that are called from event__process are defined in util/event.c. Though its defined in builtin-top.c, it could be reused for perf probe for uprobes. Hence moving it to util/event.c and exporting the function.

LKML-Reference: <[email protected]>

---
 tools/perf/builtin-top.c |   20 --------------------
 tools/perf/util/event.c  |   20 ++++++++++++++++++++
 tools/perf/util/event.h  |    1 +
 3 files changed, 21 insertions(+), 20 deletions(-)
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 db8a1d4..dab9e75 100644
@@ -548,6 +548,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 887ee63bb..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,
#44 lore raw

PATCH v10 11/14 perf: perf interface for uprobes

In reply to Arnaldo Carvalho de Melo

Enhances perf probe to accept pid and user vaddr.
Provides very basic support for uprobes.

TODO:
Update perf-probes.txt.
Global tracing.

---

Changelog from v10: moving of event__process moved to a new patch.
Also addressed other comments from Arnaldo.

Changelog from v9: Renaming common fields/functions to refer to probe instead of kprobe. This was suggested by Arnaldo.

Changelog from v8: Fixed a build break 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.

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    |   12 +
 tools/perf/util/probe-event.c |  391 +++++++++++++++++++++++++++++++++--------
 tools/perf/util/probe-event.h |   10 +
 3 files changed, 329 insertions(+), 84 deletions(-)
tools/perf/builtin-probe.c +10 -2
index 199d5e1..a98ef8a 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 pid of process where probe will be added"),
 	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);
tools/perf/util/probe-event.c +313 -78

601 lines not on this page · raw message

tools/perf/util/probe-event.h +6 -4
index 5af3924..27f052c 100644
@@ -6,7 +6,7 @@
 
 extern bool probe_event_dry_run;
 
-/* kprobe-tracer tracing point */
+/* kprobe-tracer and uprobe-tracer tracing point */
 struct probe_trace_point {
 	char		*symbol;	/* Base symbol */
 	unsigned long	offset;		/* Offset from symbol */
@@ -19,7 +19,7 @@ struct probe_trace_arg_ref {
 	long				offset;	/* Offset value */
 };
 
-/* kprobe-tracer tracing argument */
+/* kprobe-tracer and uprobe-tracer tracing argument */
 struct probe_trace_arg {
 	char				*name;	/* Argument name */
 	char				*value;	/* Base value */
@@ -27,12 +27,13 @@ struct probe_trace_arg {
 	struct probe_trace_arg_ref	*ref;	/* Referencing offset */
 };
 
-/* kprobe-tracer tracing event (point + arg) */
+/* kprobe-tracer and uprobe-tracer tracing event (point + arg) */
 struct probe_trace_event {
 	char				*event;	/* Event name */
 	char				*group;	/* Group name */
 	struct probe_trace_point	point;	/* Trace point */
 	int				nargs;	/* Number of args */
+	pid_t				upid;	/* uprobes only */
 	struct probe_trace_arg		*args;	/* Arguments */
 };
 
@@ -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 */
 };
 
@@ -112,7 +114,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);
 
#45 lore raw

PATCH v10 12/14 perf: Add third parameter to symbol_filter_t.

In reply to Srikar Dronamraju

GElf_Sym for a symbol is needed to filter out based on binding, type, value. This will be needed to list only global binding functions when listing functions from perf probe.

---

 tools/perf/builtin-test.c |    4 +++-
 tools/perf/builtin-top.c  |    6 +++++-
 tools/perf/util/map.h     |    4 +++-
 tools/perf/util/symbol.c  |   10 +++++-----
 4 files changed, 16 insertions(+), 8 deletions(-)
tools/perf/builtin-test.c +3 -1
index 035b9fa..31fb9e3 100644
@@ -11,10 +11,12 @@
 #include "util/session.h"
 #include "util/symbol.h"
 #include "util/thread.h"
+#include <gelf.h>
 
 static long page_size;
 
-static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym)
+static int vmlinux_matches_kallsyms_filter(struct map *map __used,
+		struct symbol *sym, GElf_Sym *gsym __used)
 {
 	bool *visited = symbol__priv(sym);
 	*visited = true;
tools/perf/builtin-top.c +5 -1
index b513e40..56989e8 100644
@@ -54,6 +54,7 @@
 
 #include <linux/unistd.h>
 #include <linux/types.h>
+#include <gelf.h>
 
 static int			*fd[MAX_NR_CPUS][MAX_COUNTERS];
 
@@ -932,7 +933,10 @@ static const char *skip_symbols[] = {
 	NULL
 };
 
-static int symbol_filter(struct map *map, struct symbol *sym)
+#define __unused __attribute__((unused))
+
+static int symbol_filter(struct map *map, struct symbol *sym,
+					GElf_Sym *gsym __unused)
 {
 	struct sym_entry *syme;
 	const char *name = sym->name;
tools/perf/util/map.h +3 -1
index f391345..1fcde24 100644
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include "types.h"
+#include <gelf.h>
 
 enum map_type {
 	MAP__FUNCTION = 0,
@@ -100,7 +101,8 @@ u64 map__objdump_2ip(struct map *map, u64 addr);
 
 struct symbol;
 
-typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
+typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym,
+						GElf_Sym *gsym);
 
 void map__init(struct map *self, enum map_type type,
 	       u64 start, u64 end, u64 pgoff, struct dso *dso);
tools/perf/util/symbol.c +5 -5
index 410e824..38ad5c9 100644
@@ -574,7 +574,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
 			++kernel_range;
 		}
 
-		if (filter && filter(curr_map, pos)) {
+		if (filter && filter(curr_map, pos, NULL)) {
 discard_symbol:		rb_erase(&pos->rb_node, root);
 			symbol__delete(pos);
 		} else {
@@ -653,7 +653,7 @@ static int dso__load_perf_map(struct dso *self, struct map *map,
 		if (sym == NULL)
 			goto out_delete_line;
 
-		if (filter && filter(map, sym))
+		if (filter && filter(map, sym, NULL))
 			symbol__delete(sym);
 		else {
 			symbols__insert(&self->symbols[map->type], sym);
@@ -864,7 +864,7 @@ static int dso__synthesize_plt_symbols(struct  dso *self, struct map *map,
 			if (!f)
 				goto out_elf_end;
 
-			if (filter && filter(map, f))
+			if (filter && filter(map, f, &sym))
 				symbol__delete(f);
 			else {
 				symbols__insert(&self->symbols[map->type], f);
@@ -886,7 +886,7 @@ static int dso__synthesize_plt_symbols(struct  dso *self, struct map *map,
 			if (!f)
 				goto out_elf_end;
 
-			if (filter && filter(map, f))
+			if (filter && filter(map, f, &sym))
 				symbol__delete(f);
 			else {
 				symbols__insert(&self->symbols[map->type], f);
@@ -1122,7 +1122,7 @@ new_symbol:
 		if (!f)
 			goto out_elf_end;
 
-		if (filter && filter(curr_map, f))
+		if (filter && filter(curr_map, f, &sym))
 			symbol__delete(f);
 		else {
 			symbols__insert(&curr_dso->symbols[curr_map->type], f);
#46 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 12/14] perf: Add third parameter to symbol_filter_t.

Em Tue, Jul 27, 2010 at 04:41:19PM +0530, Srikar Dronamraju escreveu:

Quoted 3 lines

GElf_Sym for a symbol is needed to filter out based on binding, type, value. This will be needed to list only global binding functions when listing functions from perf probe.

Humm, I think it is better to store the symbol binding in struct symbol, so that we can have the full symtab and then, on a particular routine, decide wheter we should use it or not.

I'll cook up a patch now.

- Arnaldo

#47 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 12/14] perf: Add third parameter to symbol_filter_t.

Em Thu, Aug 05, 2010 at 12:19:30PM -0300, Arnaldo Carvalho de Melo escreveu:

Quoted 8 lines

Em Tue, Jul 27, 2010 at 04:41:19PM +0530, Srikar Dronamraju escreveu:

Quoted 3 lines

GElf_Sym for a symbol is needed to filter out based on binding, type, value. This will be needed to list only global binding functions when listing functions from perf probe.

Humm, I think it is better to store the symbol binding in struct symbol, so that we can have the full symtab and then, on a particular routine, decide wheter we should use it or not.

One extra reason is that when we read the symtab from kallsyms, we don't have a GElf_Sym to pass to the filter.

Quoted 3 lines

I'll cook up a patch now.

- Arnaldo

#48 lore raw

Re: [PATCHv10 2.6.35-rc6-tip 12/14] perf: Add third parameter to symbol_filter_t.

In reply to Arnaldo Carvalho de Melo
Quoted 11 lines

Em Tue, Jul 27, 2010 at 04:41:19PM +0530, Srikar Dronamraju escreveu:

Quoted 3 lines

GElf_Sym for a symbol is needed to filter out based on binding, type, value. This will be needed to list only global binding functions when listing functions from perf probe.

Humm, I think it is better to store the symbol binding in struct symbol, so that we can have the full symtab and then, on a particular routine, decide wheter we should use it or not.

I'll cook up a patch now.

Okay, Please keep me in loop on that patch so that I can update this patch accordingly.

--
Thanks and Regards
Srikar

#49 lore raw

RFC PATCH v10 13/14 perf: Show Potential probe points.

In reply to Srikar Dronamraju

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.

---

Changelog from V9:
Filter labels, weak, and local binding functions from listing
as suggested by Christoph Hellwig.
Incorporated comments from Arnaldo on Version 9 of patchset.

Show all potential probes in the current running kernel and limit to the last 10 functions.

# perf probe -S | tail
zlib_inflateInit2
zlib_inflateReset
zlib_inflate_blob
zlib_inflate_table
zlib_inflate_workspacesize
zone_pcp_update
zone_reclaim
zone_reclaimable_pages
zone_statistics
zone_watermark_ok

Show all potential probes in a process by pid 3104 across all dsos and limit to the last 10 functions.

# perf probe -S -p 3104 | tail
_nss_files_setgrent
_nss_files_sethostent
_nss_files_setnetent
_nss_files_setnetgrent
_nss_files_setprotoent
_nss_files_setpwent
_nss_files_setrpcent
_nss_files_setservent
_nss_files_setspent
_nss_netgroup_parseline

Show all potentail probes in a process by pid 3104 limit to zsh dso and limit to the last 10 functions.

# perf probe -S -p 3104 -D zsh | tail
zstrtol
ztrcmp
ztrdup
ztrduppfx
ztrftime
ztrlen
ztrncpy
ztrsub
zwarn
zwarnnam
 tools/perf/builtin-probe.c    |   45 ++++++++++++++++-
 tools/perf/util/map.h         |   27 ++++++++++
 tools/perf/util/probe-event.c |  109 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/probe-event.h |    1 
 tools/perf/util/symbol.c      |   14 +++++
 tools/perf/util/symbol.h      |    1 
 6 files changed, 194 insertions(+), 3 deletions(-)
tools/perf/builtin-probe.c +43 -2
index cb915a5..e8af545 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,19 @@ 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);
+		if (!params.limitlist)
+			return -1;
+		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 +207,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 +236,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,18 +252,40 @@ 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) {
 		if (params.nevents != 0 || params.dellist) {
 			pr_warning("  Error: Don't use --line with"
-				   " --add/--del.\n");
+						" --add/--del.\n");
 			usage_with_options(probe_usage, options);
 		}
 
tools/perf/util/map.h +27 -0
index 1fcde24..6c6664a 100644
@@ -54,6 +54,33 @@ struct map_groups {
 	struct machine	 *machine;
 };
 
+/* For map_groups iteration */
+static inline struct map *map__first(struct map_groups *self,
+						enum map_type type)
+{
+	struct rb_node *rn = rb_first(&self->maps[type]);
+	return rn ? rb_entry(rn, struct map, rb_node) : NULL;
+}
+
+static inline struct map *map__next(struct map *map)
+{
+	struct rb_node *rn;
+	if (!map)
+		return NULL;
+	rn = rb_next(&map->rb_node);
+	return rn ? rb_entry(rn, struct map, rb_node) : NULL;
+}
+
+/**
+ * map_groups__for_each_map      - iterate over a strlist
+ * @pos:	the &struct map to use as a loop cursor.
+ * @type:	the map type.
+ * @self:	the &struct map_groups for loop.
+ */
+#define map_groups__for_each_map(pos, type, self)	\
+	for (pos = map__first(self, type); pos;		\
+				pos = map__next(pos))
+
 /* Native host kernel uses -1 as pid index in machine */
 #define	HOST_KERNEL_ID			(-1)
 #define	DEFAULT_GUEST_KERNEL_ID		(0)
tools/perf/util/probe-event.c +108 -1

124 lines not on this page · raw message

tools/perf/util/probe-event.h +1 -0
index 27f052c..0c0b0f8 100644
@@ -117,6 +117,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 +14 -0
index 38ad5c9..674b95a 100644
@@ -370,6 +370,20 @@ size_t dso__fprintf_buildid(struct dso *self, FILE *fp)
 	return fprintf(fp, "%s", sbuild_id);
 }
 
+size_t dso__fprintf_symbols(struct dso *self, enum map_type type, FILE *fp)
+{
+	size_t ret = 0;
+	struct rb_node *nd;
+	struct symbol_name_rb_node *pos;
+
+	for (nd = rb_first(&self->symbol_names[type]); nd; nd = rb_next(nd)) {
+		pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
+		fprintf(fp, "%s\n", pos->sym.name);
+	}
+
+	return ret;
+}
+
 size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
 {
 	struct rb_node *nd;
tools/perf/util/symbol.h +1 -0
index 80e569b..93f1058 100644
@@ -175,6 +175,7 @@ size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp);
 size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits);
 
 size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
+size_t dso__fprintf_symbols(struct dso *self, enum map_type type, FILE *fp);
 size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
 
 enum dso_origin {
#50 lore raw

RFC PATCH v10 14/14 perf: show functions in a file without using pid

In reply to Srikar Dronamraju

Lists function names in a dso. Dso needs to a filename. However passing Dso short name will not work.

---

Changelog from V9: Filter labels, weak, and local binding functions from listing as suggested by Christoph Hellwig.

Show last 10 functions in /bin/zsh.

# perf probe -S -D /bin/zsh | tail
zstrtol
ztrcmp
ztrdup
ztrduppfx
ztrftime
ztrlen
ztrncpy
ztrsub
zwarn
zwarnnam

Show first 10 functions in /lib/libc.so.6

# perf probe -S -D /lib/libc.so.6 | head
_IO_adjust_column
_IO_adjust_wcolumn
_IO_default_doallocate
_IO_default_finish
_IO_default_pbackfail
_IO_default_uflow
_IO_default_xsgetn
_IO_default_xsputn
_IO_do_write@@GLIBC_2.2.5
_IO_doallocbuf
 tools/perf/util/probe-event.c |   75 ++++++++++++++++++++++-------------------
 tools/perf/util/symbol.c      |    8 ++++
 tools/perf/util/symbol.h      |    1 +
 3 files changed, 50 insertions(+), 34 deletions(-)
tools/perf/util/probe-event.c +41 -34
index d0636e1..a079ecc 100644
@@ -2018,14 +2018,14 @@ static int print_list_available_symbols(struct map *map,
 
 int show_possible_probes(struct strlist *limitlist, pid_t pid)
 {
-	struct perf_session *session;
-	struct thread *thread;
+	struct perf_session *session = NULL;
+	struct thread *thread = NULL;
 	struct str_node *ent;
 	struct map *map = NULL;
 	char *name = NULL, *tmpname = NULL, *str;
 	int ret = -EINVAL;
 
-	if (!pid) {
+	if (!pid && !limitlist) { /* Show functions in kernel */
 		ret = init_vmlinux();
 		if (ret < 0)
 			return ret;
@@ -2036,26 +2036,28 @@ int show_possible_probes(struct strlist *limitlist, pid_t pid)
 		if (ret < 0)
 			return ret;
 	}
-	session = perf_session__new(NULL, O_WRONLY, false, false);
-	if (!session) {
-		ret = -ENOMEM;
-		goto out_delete;
-	}
-	event__synthesize_thread(pid, event__process, session);
-
-	thread = perf_session__findnew(session, pid);
-	if (!thread)
-		goto out_delete;
-
-	if (!limitlist) {
-		map_groups__for_each_map(map, MAP__FUNCTION, &thread->mg) {
-			ret = print_list_available_symbols(map, NULL);
-			if (ret)
-				pr_warning("No Symbols in dso %s.\n",
+	if (pid)  {
+		session = perf_session__new(NULL, O_WRONLY, false, false);
+		if (!session) {
+			ret = -ENOMEM;
+			goto out_delete;
+		}
+		event__synthesize_thread(pid, event__process, session);
+		thread = perf_session__findnew(session, pid);
+		if (!thread)
+			goto out_delete;
+		if (!limitlist) {
+			map_groups__for_each_map(map, MAP__FUNCTION,
+								&thread->mg) {
+				ret = print_list_available_symbols(map, NULL);
+				if (ret)
+					pr_warning("No Symbols in dso %s.\n",
 							map->dso->short_name);
+			}
+			goto out_delete;
 		}
-		goto out_delete;
 	}
+
 	strlist__for_each(ent, limitlist) {
 		str = strdup(ent->s);
 		if (!str) {
@@ -2063,20 +2065,25 @@ int show_possible_probes(struct strlist *limitlist, pid_t pid)
 			goto out_delete;
 		}
 
-		tmpname = realpath(str, NULL);
-		if (tmpname)
-			name = basename(tmpname);
-		if (!name)
-			name = str;
-		map = map_groups__find_by_name(&thread->mg,
-						MAP__FUNCTION, name);
-		if (tmpname)
-			free(tmpname);
-		if (!map) {
-			pr_warning("Skip probe listing in %s DSO.", str);
-			free(str);
-			continue;
-		}
+		if (pid) {
+			tmpname = realpath(str, NULL);
+			if (tmpname)
+				name = basename(tmpname);
+			if (!name)
+				name = str;
+			map = map_groups__find_by_name(&thread->mg,
+							MAP__FUNCTION, name);
+			if (tmpname)
+				free(tmpname);
+			if (!map) {
+				pr_warning("Skip probe listing in %s DSO.\n",
+							str);
+				free(str);
+				continue;
+			}
+		} else
+			map = dso__new_map(str);
+
 		ret = print_list_available_symbols(map, NULL);
 		if (ret)
 			pr_warning("No Symbols in dso %s.\n", str);
tools/perf/util/symbol.c +8 -0
index 674b95a..3ec57a8 100644
@@ -2360,3 +2360,11 @@ int machine__load_vmlinux_path(struct machine *self, enum map_type type,
 
 	return ret;
 }
+
+struct map *dso__new_map(char *name)
+{
+	struct dso *dso = dso__new(name);
+	struct map *map = map__new2(0, dso, MAP__FUNCTION);
+
+	return map;
+}
tools/perf/util/symbol.h +1 -0
index 93f1058..b1f608e 100644
@@ -196,6 +196,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);
+struct map *dso__new_map(char *name);
 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);