Skip to contentSkip to conversation

Uprobes v4

PATCH Superseded Srikar Dronamraju 6 participants 27 messages May 18, 2010 – May 25, 2010

Subsystems (11)

v4 of 11 Superseded Latest is v11 →

lore
Share & tools
lore
#0 lore raw

v4 cover Uprobes v4

Uprobes Patches

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 postings: please refer: http://lkml.org/lkml/2010/5/6/273
and http://lkml.org/lkml/2010/3/20/107

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 this year (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.

- Rebase to -tip tree. (targeted for v5)
- 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 with bits in inat table.

The current patchset is based on 2.6.34.

Please do provide your valuable comments.

Thanks in advance.
Srikar

Srikar Dronamraju (10):

 1.  X86 instruction analysis: Move Macro W to insn.h
 2.  mm: Move replace_page() to mm/memory.c
 3.  user_bkpt: User Space Breakpoint Assistance Layer
 4.  user_bkpt: X86 details for User space breakpoint assistance
 5.  user_bkpt: Slot allocation for Execution out of line
 6.  uprobes: Uprobes Implementation
 7.  uprobes: X86 details for Uprobes
 8.  samples: Uprobes samples
 9.  uprobes: Uprobes Documentation patch

10. trace: Share common code for uprobes/kprobes traceevents
11. trace: uprobes trace_event interface
12. perf: Dont adjust symbols if lookup is by name.
13. perf: perf interface for uprobes.

 Documentation/uprobes.txt          |  236 ++++++++++
 arch/Kconfig                       |   31 ++
 arch/x86/Kconfig                   |    2 +
 arch/x86/include/asm/insn.h        |    7 +
 arch/x86/include/asm/thread_info.h |    2 +
 arch/x86/include/asm/user_bkpt.h   |   43 ++
 arch/x86/kernel/Makefile           |    3 +
 arch/x86/kernel/kprobes.c          |    7 -
 arch/x86/kernel/signal.c           |   17 +
 arch/x86/kernel/uprobes.c          |   77 ++++
 arch/x86/kernel/user_bkpt.c        |  572 ++++++++++++++++++++++++
 fs/exec.c                          |    4 +
 include/linux/mm.h                 |    4 +
 include/linux/mm_types.h           |    4 +
 include/linux/sched.h              |    4 +
 include/linux/uprobes.h            |  169 ++++++++
 include/linux/user_bkpt.h          |  305 +++++++++++++
 include/linux/user_bkpt_xol.h      |   40 ++
 kernel/Makefile                    |    3 +
 kernel/fork.c                      |   20 +
 kernel/trace/Kconfig               |   13 +
 kernel/trace/Makefile              |    1 +
 kernel/trace/trace.h               |   11 +
 kernel/trace/trace_kprobe.c        |   76 +----
 kernel/trace/trace_probe.h         |  111 +++++
 kernel/trace/trace_uprobe.c        |  839 ++++++++++++++++++++++++++++++++++++
 kernel/uprobes.c                   |  681 +++++++++++++++++++++++++++++
 kernel/user_bkpt.c                 |  589 +++++++++++++++++++++++++
 kernel/user_bkpt_xol.c             |  302 +++++++++++++
 mm/ksm.c                           |  112 -----
 mm/memory.c                        |  120 +++++
 samples/Kconfig                    |    7 +
 samples/Makefile                   |    2 +-
 samples/uprobes/Makefile           |   17 +
 samples/uprobes/uprobe_example.c   |   83 ++++
 tools/perf/builtin-probe.c         |   38 ++-
 tools/perf/builtin-top.c           |   20 -
 tools/perf/util/event.c            |   20 +
 tools/perf/util/event.h            |    1 +
 tools/perf/util/probe-event.c      |  237 +++++++++--
 tools/perf/util/probe-event.h      |    9 +-
 tools/perf/util/probe-finder.h     |    1 +
 tools/perf/util/symbol.c           |    6 +-
 43 files changed, 4576 insertions(+), 270 deletions(-)
#1 lore raw

PATCH v4 1/13 X86 instruction analysis: Move Macro W to insn.h

Move Macro W to asm/insn.h

Macro W used to know if the instructions are valid for user-space/kernel space. This macro is used by kprobes and user_bkpt. (i.e user space breakpoint assistance layer.) So moving it to a common header file asm/insn.h.

TODO: replace macro W with bits in inat table. (suggested by Masami Hiramatsu)

---

 arch/x86/include/asm/insn.h |    7 +++++++
 arch/x86/kernel/kprobes.c   |    7 -------
 2 files changed, 7 insertions(+), 7 deletions(-)
arch/x86/include/asm/insn.h +7 -0
index 96c2e0a..8586820 100644
@@ -23,6 +23,13 @@
 /* insn_attr_t is defined in inat.h */
 #include <asm/inat.h>
 
+#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\
+	(((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) |   \
+	  (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) |   \
+	  (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) |   \
+	  (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf))    \
+	 << (row % 32))
+
 struct insn_field {
 	union {
 		insn_value_t value;
arch/x86/kernel/kprobes.c +0 -7
index 1658efd..6da0a20 100644
@@ -66,12 +66,6 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
 #define stack_addr(regs) ((unsigned long *)kernel_stack_pointer(regs))
 
-#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\
-	(((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) |   \
-	  (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) |   \
-	  (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) |   \
-	  (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf))    \
-	 << (row % 32))
 	/*
 	 * Undefined/reserved opcodes, conditional jump, Opcode Extension
 	 * Groups, and some special opcodes can not boost.
@@ -98,7 +92,6 @@ static const u32 twobyte_is_boostable[256 / 32] = {
 	/*      -----------------------------------------------         */
 	/*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f          */
 };
-#undef W
 
 struct kretprobe_blackpoint kretprobe_blacklist[] = {
 	{"__switch_to", }, /* This function switches only current task, but
#2 lore raw

PATCH v4 2/13 mm: Move replace_page to mm/memory.c

In reply to Srikar Dronamraju

Move replace_page() and 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 462acaf..2bc7a9c 100644
@@ -854,6 +854,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

#3 lore raw

PATCH v4 3/13 User Space Breakpoint Assistance Layer

In reply to Srikar Dronamraju

User Space Breakpoint Assistance Layer (USER_BKPT)

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.

Currently there is no mechanism in kernel to insert/remove breakpoints.

This patch implements user space breakpoint assistance layer provides kernel subsystems with architecture independent interface to establish breakpoints in user applications. This patch provides core implementation of user_bkpt and also wrappers for architecture dependent methods.

USER_BKPT currently supports both single stepping inline and execution out of line strategies. Two different probepoints in the same process can have two different strategies. It handles pre-processing and post-processing of singlestep after a breakpoint hit.

Single stepping inline strategy 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.

Execution out of line strategy single steps on a copy of the instruction. This method works well for both single-threaded and multithreaded applications.

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 USER_BKPT patch for your architecture.

Uprobes uses this facility to insert/remove breakpoint.

TODO: Merge user_bkpt layer with uprobes.

---

 arch/Kconfig              |   14 +
 include/linux/user_bkpt.h |  305 +++++++++++++++++++++++
 kernel/Makefile           |    1 
 kernel/user_bkpt.c        |  589 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 909 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/user_bkpt.h
 create mode 100644 kernel/user_bkpt.c
arch/Kconfig +14 -0
index e5eb133..e64bbdc 100644
@@ -52,6 +52,17 @@ config OPTPROBES
 	  This option will allow kprobes to optimize breakpoint to
 	  a jump for reducing its overhead.
 
+config USER_BKPT
+	bool "User-space breakpoint assistance (EXPERIMENTAL)"
+	depends on MODULES
+	depends on HAVE_USER_BKPT
+	depends on MMU
+	help
+	  User_bkpt (User-space breakpoint assistance layer) enables
+	  kernel subsystems to establish breakpoints in user applications.
+	  This service is used by components such as uprobes.
+	  If in doubt, say "N".
+
 config HAVE_EFFICIENT_UNALIGNED_ACCESS
 	bool
 	help
@@ -85,6 +96,9 @@ config USER_RETURN_NOTIFIER
 	  Provide a kernel-internal notification when a cpu is about to
 	  switch to user mode.
 
+config HAVE_USER_BKPT
+	def_bool n
+
 config HAVE_IOREMAP_PROT
 	bool
 
include/linux/user_bkpt.h new file +305 -0

305 lines not on this page · raw message

kernel/Makefile +1 -0
index a987aa1..36a35b0 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_USER_BKPT) += user_bkpt.o
 
 ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
 # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
kernel/user_bkpt.c new file +589 -0

589 lines not on this page · raw message

#4 lore raw

PATCH v4 4/13 x86 support for User space breakpoint assistance

In reply to Srikar Dronamraju

x86 support for user breakpoint Infrastructure

Changelog from v1:
set USER_BKPT_FIX_SLEEPY if post_xol might sleep.

This patch provides x86 specific userspace breakpoint assistance implementation details. It uses the "x86: instruction decoder API" patch to do validate and analyze the instructions. This analysis is used at the time of post-processing of breakpoint hit to do the necessary fix-ups.

Almost all instructions are handled for traditional strategy and execution out of line strategy. Instruction handled include the RIP relative instructions.

This patch requires "x86: instruction decoder API" patch.
http://lkml.org/lkml/2009/6/1/459

---

 arch/x86/Kconfig                 |    1 
 arch/x86/include/asm/user_bkpt.h |   43 +++
 arch/x86/kernel/Makefile         |    2 
 arch/x86/kernel/user_bkpt.c      |  572 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 618 insertions(+), 0 deletions(-)
 create mode 100644 arch/x86/include/asm/user_bkpt.h
 create mode 100644 arch/x86/kernel/user_bkpt.c
arch/x86/Kconfig +1 -0
index 9458685..7dce185 100644
@@ -53,6 +53,7 @@ config X86
 	select HAVE_KERNEL_LZMA
 	select HAVE_KERNEL_LZO
 	select HAVE_HW_BREAKPOINT
+	select HAVE_USER_BKPT
 	select PERF_EVENTS
 	select ANON_INODES
 	select HAVE_ARCH_KMEMCHECK
arch/x86/include/asm/user_bkpt.h new file +43 -0

43 lines not on this page · raw message

arch/x86/kernel/Makefile +2 -0
index 4c58352..98c74b4 100644
@@ -117,6 +117,8 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
 
 obj-$(CONFIG_SWIOTLB)			+= pci-swiotlb.o
 
+obj-$(CONFIG_USER_BKPT)			+= user_bkpt.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
arch/x86/kernel/user_bkpt.c new file +572 -0

572 lines not on this page · raw message

#5 lore raw

PATCH v4 5/13 Slot allocation for execution out of line (XOL)

In reply to Srikar Dronamraju

Changelog from v3:

* Added a memory barrier after the slot gets initialized.

Changelog from v2: (addressing Oleg's comments)
* Removed code in !CONFIG_USER_BKPT_XOL
* Functions now pass pointer to user_bkpt_xol_area instead of pointer to void.

Slot allocation for Execution out of line strategy(XOL)

This patch provides slot allocation mechanism for execution out of line strategy for use with user space breakpoint infrastructure.

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.

---

 arch/Kconfig                  |    4 +
 include/linux/user_bkpt_xol.h |   40 +++++
 kernel/Makefile               |    1 
 kernel/user_bkpt_xol.c        |  302 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 347 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/user_bkpt_xol.h
 create mode 100644 kernel/user_bkpt_xol.c
arch/Kconfig +4 -0
index e64bbdc..da7329c 100644
@@ -99,6 +99,10 @@ config USER_RETURN_NOTIFIER
 config HAVE_USER_BKPT
 	def_bool n
 
+config USER_BKPT_XOL
+	def_bool y
+	depends on USER_BKPT
+
 config HAVE_IOREMAP_PROT
 	bool
 
include/linux/user_bkpt_xol.h new file +40 -0
new file mode 100644
index 0000000..47e8d62
@@ -0,0 +1,40 @@
+#ifndef _LINUX_XOL_H
+#define _LINUX_XOL_H
+/*
+ * User-space BreakPoint support (user_bkpt) -- Allocation of instruction
+ * slots for execution out of line (XOL)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2009, 2010
+ * Authors:
+ *	Srikar Dronamraju
+ *	Jim Keniston
+ */
+
+#define UINSNS_PER_PAGE	(PAGE_SIZE/USER_BKPT_XOL_SLOT_BYTES)
+#define MAX_USER_BKPT_XOL_SLOTS UINSNS_PER_PAGE
+struct user_bkpt_xol_area;
+
+extern unsigned long xol_get_insn_slot(struct user_bkpt *user_bkpt,
+				struct user_bkpt_xol_area *xol_area);
+extern void xol_free_insn_slot(unsigned long,
+				struct user_bkpt_xol_area *xol_area);
+extern int xol_validate_vaddr(struct pid *pid, unsigned long vaddr,
+				struct user_bkpt_xol_area *xol_area);
+extern struct user_bkpt_xol_area *xol_alloc_area(void);
+extern void xol_free_area(struct user_bkpt_xol_area *xol_area);
+
+#endif  /* _LINUX_XOL_H */
kernel/Makefile +1 -0
index 36a35b0..e404aa0 100644
@@ -106,6 +106,7 @@ obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
 obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
 obj-$(CONFIG_PADATA) += padata.o
 obj-$(CONFIG_USER_BKPT) += user_bkpt.o
+obj-$(CONFIG_USER_BKPT_XOL) += user_bkpt_xol.o
 
 ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
 # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
kernel/user_bkpt_xol.c new file +302 -0

302 lines not on this page · raw message

#6 lore raw

PATCH v4 6/13 Uprobes Implementation

In reply to Srikar Dronamraju

Uprobes Implementation

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.
- 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.)
- find_probept() takes the spinlock; unlike previously when it was expected that the spinlock was taken before calling it.

Changelog from v1:
- If fixup might sleep; then do the post singlestep processing in task context.

The uprobes infrastructure enables a user to dynamically establish probepoints in user applications and collect information by executing a handler function when a probepoint is hit.

The user specifies the virtual address and the pid of the process of interest along with the action to be performed (handler). The handle Uprobes is implemented on the user-space breakpoint assistance layer and uses the execution out of line strategy. Uprobes 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 when the probe gets unregistered and no threads are using that slot.

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. Perf/trace events interface for uprobes.
2. Allow multiple probes at a probepoint.
3. Booster probes.
4. Allow probes to be inherited across fork.
5. probing function returns.

---

 arch/Kconfig                       |   13 +
 arch/x86/include/asm/thread_info.h |    2 
 arch/x86/kernel/signal.c           |    5 
 fs/exec.c                          |    4 
 include/linux/mm_types.h           |    4 
 include/linux/sched.h              |    4 
 include/linux/uprobes.h            |  169 +++++++++
 kernel/Makefile                    |    1 
 kernel/fork.c                      |   20 +
 kernel/uprobes.c                   |  681 ++++++++++++++++++++++++++++++++++++
 10 files changed, 903 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/uprobes.h
 create mode 100644 kernel/uprobes.c
arch/Kconfig +13 -0
index da7329c..5a0f7be 100644
@@ -63,6 +63,16 @@ config USER_BKPT
 	  This service is used by components such as uprobes.
 	  If in doubt, say "N".
 
+config UPROBES
+	bool "User-space probes (EXPERIMENTAL)"
+	depends on MODULES && USER_BKPT_XOL
+	depends on HAVE_UPROBES
+	help
+	  Uprobes enables kernel modules 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
@@ -114,6 +124,9 @@ config HAVE_KRETPROBES
 
 config HAVE_OPTPROBES
 	bool
+
+config HAVE_UPROBES
+	def_bool n
 #
 # An arch should select this if it provides all these things:
 #
arch/x86/include/asm/thread_info.h +2 -0
index e0d2890..5258e69 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 */
@@ -108,6 +109,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/kernel/signal.c +5 -0
index 4fd173c..851bc8d 100644
@@ -848,6 +848,11 @@ 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);
+		uprobe_notify_resume(regs);
+	}
+
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 		clear_thread_flag(TIF_NOTIFY_RESUME);
 		tracehook_notify_resume(regs);
fs/exec.c +4 -0
index e6e94c6..96b1cf1 100644
@@ -1048,6 +1048,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..b80ffb3 100644
@@ -14,6 +14,7 @@
 #include <linux/page-debug-flags.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
+#include <linux/uprobes.h>
 
 #ifndef AT_VECTOR_SIZE_ARCH
 #define AT_VECTOR_SIZE_ARCH 0
@@ -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 +4 -0
index 2b7b81d..3921367 100644
@@ -91,6 +91,7 @@ struct sched_param {
 #include <linux/kobject.h>
 #include <linux/latencytop.h>
 #include <linux/cred.h>
+#include <linux/uprobe.h>
 
 #include <asm/processor.h>
 
@@ -1505,6 +1506,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 new file +169 -0

169 lines not on this page · raw message

kernel/Makefile +1 -0
index e404aa0..f0cfb02 100644
@@ -107,6 +107,7 @@ obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
 obj-$(CONFIG_PADATA) += padata.o
 obj-$(CONFIG_USER_BKPT) += user_bkpt.o
 obj-$(CONFIG_USER_BKPT_XOL) += user_bkpt_xol.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/fork.c +20 -0
index 4c14942..c1cb9f0 100644
@@ -173,6 +173,10 @@ void __put_task_struct(struct task_struct *tsk)
 
 	exit_creds(tsk);
 	delayacct_tsk_free(tsk);
+#ifdef CONFIG_UPROBES
+	if (unlikely(tsk->utask))
+		uprobe_free_utask(tsk);
+#endif
 
 	if (!profile_handoff_task(tsk))
 		free_task(tsk);
@@ -509,6 +513,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);
@@ -667,6 +675,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:
@@ -1181,6 +1192,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
 	 */
@@ -1279,6 +1293,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 new file +681 -0

681 lines not on this page · raw message

#7 lore raw

PATCH v4 7/13 x86 support for Uprobes

In reply to Srikar Dronamraju

X86 support for Uprobes

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

---

 arch/x86/Kconfig          |    1 +
 arch/x86/kernel/Makefile  |    1 +
 arch/x86/kernel/signal.c  |   12 +++++++
 arch/x86/kernel/uprobes.c |   77 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 91 insertions(+), 0 deletions(-)
 create mode 100644 arch/x86/kernel/uprobes.c
arch/x86/Kconfig +1 -0
index 7dce185..57be1fa 100644
@@ -54,6 +54,7 @@ config X86
 	select HAVE_KERNEL_LZO
 	select HAVE_HW_BREAKPOINT
 	select HAVE_USER_BKPT
+	select HAVE_UPROBES
 	select PERF_EVENTS
 	select ANON_INODES
 	select HAVE_ARCH_KMEMCHECK
arch/x86/kernel/Makefile +1 -0
index 98c74b4..bfa48f0 100644
@@ -118,6 +118,7 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
 obj-$(CONFIG_SWIOTLB)			+= pci-swiotlb.o
 
 obj-$(CONFIG_USER_BKPT)			+= user_bkpt.o
+obj-$(CONFIG_UPROBES)			+= uprobes.o
 
 ###
 # 64 bit specific files
arch/x86/kernel/signal.c +12 -0
index 851bc8d..dde9a42 100644
@@ -850,7 +850,19 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
 
 	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.
+		 */
+		native_irq_enable();
+#endif
 		uprobe_notify_resume(regs);
+
+#ifdef CONFIG_X86_32
+		native_irq_disable();
+#endif
 	}
 
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
arch/x86/kernel/uprobes.c new file +77 -0

77 lines not on this page · raw message

#8 lore raw

PATCH v4 8/13 samples: Uprobes samples

In reply to Srikar Dronamraju

Uprobes Samples

This provides an example uprobes module in the samples directory.

To run this module run (as root)
insmod uprobe_example.ko vaddr=<vaddr> pid=<pid>
Where <vaddr> is the address where we want to place the probe.
<pid> is the pid of the process we are interested to probe.

example: -

# cd samples/uprobes

[get the virtual address to place the probe.]
# vaddr=0x$(objdump -T /bin/bash |awk '/echo_builtin/ {print $1}')

[Run a bash shell in the background; have it echo 4 lines.] # (sleep 10; echo 1; echo 2; echo 3; echo 4) & [Probe calls echo_builtin() in the background bash process.]

# insmod uprobe_example.ko vaddr=$vaddr pid=$!
# sleep 10
# rmmod uprobe_example
# dmesg | tail -n 3
Registering uprobe on pid 10875, vaddr 0x45aa30
Unregistering uprobe on pid 10875, vaddr 0x45aa30
Probepoint was hit 4 times
#
[ Output shows that echo_builtin function was hit 4 times. ]

---

 samples/Kconfig                  |    7 +++
 samples/Makefile                 |    2 -
 samples/uprobes/Makefile         |   17 ++++++++
 samples/uprobes/uprobe_example.c |   83 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 108 insertions(+), 1 deletions(-)
 create mode 100644 samples/uprobes/Makefile
 create mode 100644 samples/uprobes/uprobe_example.c
samples/Kconfig +7 -0
index 8924f72..50b8b1c 100644
@@ -44,4 +44,11 @@ config SAMPLE_HW_BREAKPOINT
 	help
 	  This builds kernel hardware breakpoint example modules.
 
+config SAMPLE_UPROBES
+	tristate "Build uprobes example -- loadable module only"
+	depends on UPROBES && m
+	help
+	  This builds uprobes example module.
+
+
 endif # SAMPLES
samples/Makefile +1 -1
index 0f15e6d..c8fe6f9 100644
@@ -1,4 +1,4 @@
 # Makefile for Linux samples code
 
 obj-$(CONFIG_SAMPLES)	+= kobject/ kprobes/ tracepoints/ trace_events/ \
-			   hw_breakpoint/
+			   hw_breakpoint/ uprobes/
samples/uprobes/Makefile new file +17 -0
new file mode 100644
index 0000000..f535f6f
@@ -0,0 +1,17 @@
+# builds the uprobes example kernel modules;
+# then to use one (as root):
+# insmod <module_name.ko> vaddr=<vaddr> pid=<pid>
+#
+#
+# example: -
+# vaddr=0x$(objdump -T /bin/bash |awk '/echo_builtin/ print $1}')
+# (sleep 10; echo 1; echo 2; echo 3; echo 4) &
+# insmod uprobe_example.ko vaddr=$vaddr pid=$!
+# sleep 10
+# rmmod uprobe_example
+# dmesg | tail -n 3
+#	Registering uprobe on pid 3920, vaddr 0x45aa30
+#	Unregistering uprobe on pid 3920, vaddr 0x45aa30
+#	Probepoint was hit 4 times
+
+obj-$(CONFIG_SAMPLE_UPROBES) += uprobe_example.o
samples/uprobes/uprobe_example.c new file +83 -0

83 lines not on this page · raw message

#9 lore raw

PATCH v4 9/13 Uprobes documentation.

In reply to Srikar Dronamraju

uprobes-documentation.patch

Changelog from v3: Updated measurements.

Changelog from v2: Updated measurements.

Changelog from v1: Addressed comments from Randy Dunlap.
: Updated measurements.

---

 Documentation/uprobes.txt |  236 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 236 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/uprobes.txt
Documentation/uprobes.txt new file +236 -0
new file mode 100644
index 0000000..c922d5f
@@ -0,0 +1,236 @@
+Title	: User-Space Probes (Uprobes)
+Authors	: Jim Keniston <[email protected]>
+	: Srikar Dronamraju <[email protected]>
+
+CONTENTS
+
+1. Concepts: Uprobes
+2. Architectures Supported
+3. Configuring Uprobes
+4. API Reference
+5. Uprobes Features and Limitations
+6. Probe Overhead
+7. TODO
+8. Uprobes Team
+9. Uprobes Example
+
+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. Configuring Uprobes
+
+When configuring the kernel using make menuconfig/xconfig/oldconfig,
+ensure that CONFIG_UPROBES is set to "y". Under "General setup" select
+"User-space breakpoint assistance" then select "User-space probes".
+
+So that you can load and unload Uprobes-based instrumentation modules,
+make sure "Loadable module support" (CONFIG_MODULES) and "Module
+unloading" (CONFIG_MODULE_UNLOAD) are set to "y".
+
+4. 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.
+
+4.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.
+
+4.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.
+
+5. Uprobes Features and Limitations
+
+The user is expected to assign values to the following members
+of struct uprobe: pid, vaddr, handler, and handler_in_interrupt.
+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.
+
+Any number of kernel modules may probe a particular process
+simultaneously, and a particular module may 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 its copy-on-write
+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.
+
+6. Probe Overhead
+
+Probe overhead is measured on a benchmark that hits the same probepoint
+repeatedly, firing a simple handler each time. Probe overhead
+changes with different cpus/archs/probe handlers and the number of
+iterations.
+
+Here are sample overhead figures (in usec) for x86 architecture.
+
+i686: Intel(R) Xeon(TM) CPU 2.40GHz
+Without probe module.
+100000 interations in 0.000687 sec i.e 0.006870 usec per iteration
+
+With probes
+100000 interations in 0.314938 sec i.e 3.149380 usec per iteration
+probe overhead is 3.142510 usec per probe hit.
+
+x86_64: Intel(R) Xeon(R) CPU           X7350  @ 2.93GHz
+Without probe module.
+100000 interations in 0.000432 sec i.e 0.004320 usec per iteration
+
+With probes
+100000 interations in 0.101276 sec i.e 1.012760 usec per iteration
+Probe overhead is 1.301738 usec per probe hit.
+
+7. TODO
+
+a. Support for other architectures.
+b. Support for multiple probes at the same address.
+c. Support for boosted probes.
+d. Support return probes.
+
+8. 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]
+
+9. Uprobes Example
+
+samples/uprobes/uprobe_example.c
#10 lore raw

PATCH v4 10/13 trace: Common code for kprobes/uprobes traceevents

In reply to Srikar Dronamraju

Move common parts of trace_kprobe.c and adjust kernel/trace/trace_kprobe.c after moving common code to kernel/trace/trace_probe.h

---

 kernel/trace/trace_kprobe.c |   76 +----------------------------
 kernel/trace/trace_probe.h  |  111 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 113 insertions(+), 74 deletions(-)
 create mode 100644 kernel/trace/trace_probe.h
kernel/trace/trace_kprobe.c +2 -74
index 1251e36..dc1840a 100644
@@ -20,42 +20,8 @@
 #include <linux/module.h>
 #include <linux/uaccess.h>
 #include <linux/kprobes.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/smp.h>
-#include <linux/debugfs.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/ptrace.h>
-#include <linux/perf_event.h>
-
-#include "trace.h"
-#include "trace_output.h"
-
-#define MAX_TRACE_ARGS 128
-#define MAX_ARGSTR_LEN 63
-#define MAX_EVENT_NAME_LEN 64
-#define KPROBE_EVENT_SYSTEM "kprobes"
-
-/* Reserved field names */
-#define FIELD_STRING_IP "__probe_ip"
-#define FIELD_STRING_NARGS "__probe_nargs"
-#define FIELD_STRING_RETIP "__probe_ret_ip"
-#define FIELD_STRING_FUNC "__probe_func"
-
-const char *reserved_field_names[] = {
-	"common_type",
-	"common_flags",
-	"common_preempt_count",
-	"common_pid",
-	"common_tgid",
-	"common_lock_depth",
-	FIELD_STRING_IP,
-	FIELD_STRING_NARGS,
-	FIELD_STRING_RETIP,
-	FIELD_STRING_FUNC,
-};
+
+#include "trace_probe.h"
 
 struct fetch_func {
 	unsigned long (*func)(struct pt_regs *, void *);
@@ -192,10 +158,6 @@ struct probe_arg {
 	const char		*name;
 };
 
-/* Flags for trace_probe */
-#define TP_FLAG_TRACE	1
-#define TP_FLAG_PROFILE	2
-
 struct trace_probe {
 	struct list_head	list;
 	struct kretprobe	rp;	/* Use rp.kp for kprobe use */
@@ -274,19 +236,6 @@ static LIST_HEAD(probe_list);
 static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
 static int kretprobe_dispatcher(struct kretprobe_instance *ri,
 				struct pt_regs *regs);
-
-/* Check the name is good for event/group */
-static int check_event_name(const char *name)
-{
-	if (!isalpha(*name) && *name != '_')
-		return 0;
-	while (*++name != '\0') {
-		if (!isalpha(*name) && !isdigit(*name) && *name != '_')
-			return 0;
-	}
-	return 1;
-}
-
 /*
  * Allocate new trace_probe and initialize it (including kprobes).
  */
@@ -454,9 +403,6 @@ static int split_symbol_offset(char *symbol, unsigned long *offset)
 	return 0;
 }
 
-#define PARAM_MAX_ARGS 16
-#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
-
 static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
 {
 	int ret = 0;
@@ -835,24 +781,6 @@ static int probes_open(struct inode *inode, struct file *file)
 	return seq_open(file, &probes_seq_op);
 }
 
-static int command_trace_probe(const char *buf)
-{
-	char **argv;
-	int argc = 0, ret = 0;
-
-	argv = argv_split(GFP_KERNEL, buf, &argc);
-	if (!argv)
-		return -ENOMEM;
-
-	if (argc)
-		ret = create_trace_probe(argc, argv);
-
-	argv_free(argv);
-	return ret;
-}
-
-#define WRITE_BUFSIZE 128
-
 static ssize_t probes_write(struct file *file, const char __user *buffer,
 			    size_t count, loff_t *ppos)
 {
kernel/trace/trace_probe.h new file +111 -0

111 lines not on this page · raw message

#11 lore raw

Re: [PATCH v4 10/13] trace: Common code for kprobes/uprobes traceevents

Quoted 5 lines · Srikar Dronamraju

Move common parts of trace_kprobe.c and adjust kernel/trace/trace_kprobe.c after moving common code to kernel/trace/trace_probe.h

Looks good!
I have just a few comments.

kernel/trace/trace_probe.h line 2

Quoted 8 lines
kernel/trace/trace_probe.h new file +2 -0
new file mode 100644
index 0000000..66a4498
@@ -0,0 +1,111 @@
+/*
+ * Uprobes-based tracing events

Isn't it a common header for kprobes and uprobes? :)

Maybe "Probe-based dynamic events common header" ?

Quoted 25 lines
kernel/trace/trace_probe.h new file +25 -0
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Copyright (C) IBM Corporation, 2010
+ * Author:	Srikar Dronamraju
+ */
+
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/debugfs.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ctype.h>

kernel/trace/trace_probe.h line 37

Quoted 10 lines
kernel/trace/trace_probe.h new file +10 -0
+#include <linux/ptrace.h>
+#include <linux/perf_event.h>
+
+#include "trace.h"
+#include "trace_output.h"
+
+#define MAX_TRACE_ARGS 128
+#define MAX_ARGSTR_LEN 63
+#define MAX_EVENT_NAME_LEN 64
+#define UPROBE_EVENT_SYSTEM "uprobes"

You should *just move* the common code in this patch. Additional uprobes code can be introduced in next patch.

Quoted 17 lines
kernel/trace/trace_probe.h new file +17 -0
+#define KPROBE_EVENT_SYSTEM "kprobes"
+
+/* Reserved field names */
+#define FIELD_STRING_IP "__probe_ip"
+#define FIELD_STRING_NARGS "__probe_nargs"
+#define FIELD_STRING_RETIP "__probe_ret_ip"
+#define FIELD_STRING_FUNC "__probe_func"
+#define FIELD_STRING_PID "__probe_pid"
+
+static const char *reserved_field_names[] = {
+	"common_type",
+	"common_flags",
+	"common_preempt_count",
+	"common_pid",
+	"common_tgid",
+	"common_lock_depth",
+	FIELD_STRING_IP,

kernel/trace/trace_probe.h line 64

Quoted 10 lines
kernel/trace/trace_probe.h new file +10 -0
+	FIELD_STRING_NARGS,
+	FIELD_STRING_RETIP,
+	FIELD_STRING_FUNC,
+	FIELD_STRING_PID,
+};
+
+/* Flags for trace_probe */
+#define TP_FLAG_TRACE	1
+#define TP_FLAG_PROFILE	2
+#define UPROBE_ENABLED	4

If this is a trace_probe flag, it is better to start with TP_FLAG_.

Thank you,

Signature · 2 lines
Masami Hiramatsu
e-mail: [email protected]
#12 lore raw

Re: [PATCH v4 10/13] trace: Common code for kprobes/uprobes traceevents

Quoted 5 lines

Isn't it a common header for kprobes and uprobes? :)

Maybe "Probe-based dynamic events common header" ?

Agree.

Quoted 8 lines

kernel/trace/trace_probe.h line 37

Quoted 4 lines
kernel/trace/trace_probe.h new file +4 -0
+#define MAX_TRACE_ARGS 128
+#define MAX_ARGSTR_LEN 63
+#define MAX_EVENT_NAME_LEN 64
+#define UPROBE_EVENT_SYSTEM "uprobes"

You should *just move* the common code in this patch. Additional uprobes code can be introduced in next patch.

Okay.

Quoted 7 lines

kernel/trace/trace_probe.h line 64

Quoted 5 lines
kernel/trace/trace_probe.h new file +5 -0
+
+/* Flags for trace_probe */
+#define TP_FLAG_TRACE	1
+#define TP_FLAG_PROFILE	2
+#define UPROBE_ENABLED	4

If this is a trace_probe flag, it is better to start with TP_FLAG_.

Okay.
Does TP_FLAG_UPROBE sound fine?

Thanks Masami.

--
Thanks and Regards
Srikar

#13 lore raw

Re: [PATCH v4 10/13] trace: Common code for kprobes/uprobes traceevents

Quoted 27 lines · Srikar Dronamraju
Quoted 5 lines

Isn't it a common header for kprobes and uprobes? :)

Maybe "Probe-based dynamic events common header" ?

Agree.

Quoted 8 lines

kernel/trace/trace_probe.h line 37

Quoted 4 lines
kernel/trace/trace_probe.h new file +4 -0
+#define MAX_TRACE_ARGS 128
+#define MAX_ARGSTR_LEN 63
+#define MAX_EVENT_NAME_LEN 64
+#define UPROBE_EVENT_SYSTEM "uprobes"

You should *just move* the common code in this patch. Additional uprobes code can be introduced in next patch.

Okay.

Quoted 7 lines

kernel/trace/trace_probe.h line 64

Quoted 5 lines
kernel/trace/trace_probe.h new file +5 -0
+
+/* Flags for trace_probe */
+#define TP_FLAG_TRACE	1
+#define TP_FLAG_PROFILE	2
+#define UPROBE_ENABLED	4

If this is a trace_probe flag, it is better to start with TP_FLAG_.

Quoted 2 lines

Okay.
Does TP_FLAG_UPROBE sound fine?

Sure, that's good for me:)

Thank you,

Signature · 2 lines
Masami Hiramatsu
e-mail: [email protected]
#14 lore raw

PATCH v4 11/13 trace: uprobes trace_event interface

In reply to Srikar Dronamraju

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 patch 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.

This is based on trace_events for kprobes to the extent that it may resemble that file on 2.6.34.

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 3548]
[Address to trace is 0x0000000000446420] [Registers to be dumped are %ip and %ax]

# cd /sys/kernel/debug/tracing/
# echo 'p 3548:0x0000000000446420 %ip %ax' > uprobe_events
# cat uprobe_events
p:uprobes/p_3548_0x0000000000446420 3548:0x0000000000446420 %ip=%ip %ax=%ax
# cat events/uprobes/p_3548_0x0000000000446420/enable
0
[enable the event]
# echo 1 > events/uprobes/p_3548_0x0000000000446420/enable
# cat events/uprobes/p_3548_0x0000000000446420/enable
1
# #### do some activity on the program so that it hits the breakpoint
# cat uprobe_profile
  3548 p_3548_0x0000000000446420                                234
# tracer: nop
#
#           TASK-PID    CPU#    TIMESTAMP  FUNCTION
#              | |       |          |         |
           <...>-3548  [001]   294.285812: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1
           <...>-3548  [001]   294.285884: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1
           <...>-3548  [001]   294.285894: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1
           <...>-3548  [001]   294.285903: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1
           <...>-3548  [001]   294.285912: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1
           <...>-3548  [001]   294.285922: p_3548_0x0000000000446420: (0x446420) %ip=446421 %ax=1

TODO: Documentation/trace/uprobetrace.txt
Rebase to -tip tree.

---

 kernel/trace/Kconfig        |   13 +
 kernel/trace/Makefile       |    1 
 kernel/trace/trace.h        |   11 +
 kernel/trace/trace_uprobe.c |  839 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 864 insertions(+), 0 deletions(-)
 create mode 100644 kernel/trace/trace_uprobe.c
kernel/trace/Kconfig +13 -0
index 13e13d4..7d39f08 100644
@@ -557,6 +557,19 @@ config RING_BUFFER_BENCHMARK
 
 	  If unsure, say N.
 
+config UPROBE_EVENT
+	depends on UPROBES
+	bool "Enable uprobes-based dynamic events"
+	select TRACING
+	default y
+	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 78edc64..8911959 100644
@@ -58,5 +58,6 @@ obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
 obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o
 obj-$(CONFIG_KSYM_TRACER) += trace_ksym.o
 obj-$(CONFIG_EVENT_TRACING) += power-traces.o
+obj-$(CONFIG_UPROBE_EVENT) += trace_uprobe.o
 
 libftrace-y := ftrace.o
kernel/trace/trace.h +11 -0
index 2825ef2..767fb97 100644
@@ -126,6 +126,17 @@ struct kretprobe_trace_entry {
 	(offsetof(struct kretprobe_trace_entry, args) +	\
 	(sizeof(unsigned long) * (n)))
 
+struct uprobe_trace_entry {
+	struct trace_entry	ent;
+	unsigned long		ip;
+	int			nargs;
+	unsigned long		args[];
+};
+
+#define SIZEOF_UPROBE_TRACE_ENTRY(n)			\
+	(offsetof(struct uprobe_trace_entry, args) +	\
+	(sizeof(unsigned long) * (n)))
+
 /*
  * trace_flag_type is an enumeration that holds different
  * states when a trace occurs. These are:
kernel/trace/trace_uprobe.c new file +839 -0

839 lines not on this page · raw message

maintainer
#15 lore raw

Re: [PATCH v4 11/13] trace: uprobes trace_event interface

Quoted 2 lines · Srikar Dronamraju

This is based on trace_events for kprobes to the extent that it may resemble that file on 2.6.34.

Check the changes that have been done in tip/perf/core. These will be going mainline for 35. The interface with the ftrace_event_call structure will affect this patch too.

-- Steve

#16 lore raw

Re: [PATCH v4 11/13] trace: uprobes trace_event interface

Quoted 9 lines · Steven Rostedt
Quoted 2 lines · Srikar Dronamraju

This is based on trace_events for kprobes to the extent that it may resemble that file on 2.6.34.

Check the changes that have been done in tip/perf/core. These will be going mainline for 35. The interface with the ftrace_event_call structure will affect this patch too.

Okay,

I shall update the trace_events for uprobes to the current changes in tip/master.

--
Thanks and Regards
Srikar

#17 lore raw

PATCH v4 12/13 perf: Dont adjust symbols on name lookup

In reply to Srikar Dronamraju

Adjusting symbols is not needed if we are searching by name. Infact if we adjust and search symbols by name, we get incorrect results.

---

 tools/perf/util/symbol.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)
tools/perf/util/symbol.c +4 -2
index c458c4a..7267050 100644
@@ -958,12 +958,14 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
 	nr_syms = shdr.sh_size / shdr.sh_entsize;
 
 	memset(&sym, 0, sizeof(sym));
-	if (!self->kernel) {
+	if (self->kernel || symbol_conf.sort_by_name)
+		self->adjust_symbols = 0;
+	else {
 		self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
 				elf_section_by_name(elf, &ehdr, &shdr,
 						     ".gnu.prelink_undo",
 						     NULL) != NULL);
-	} else self->adjust_symbols = 0;
+	}
 
 	elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
 		struct symbol *f;
#18 lore raw

PATCH v4 13/13 perf: perf interface for uprobes.

In reply to Srikar Dronamraju

This patch enhances perf probe to accept pid and user vaddr. This patch provides very basic support for uprobes.

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.

TODO:
Rebase to -tip tree. (targeted for v5)
Update perf-probes.txt.
Global tracing.

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

[ Probing a function in the executable using function name ]
-------------------------------------------------------------

[root@ABCD]# perf probe -p 7057 zfree@zsh
Added new event:
  probe_7057:zfree                       (on 0x446420)

You can now use it on all perf tools, such as:

perf record -e probe_7057:zfree -a sleep 1

[root@ABCD]# perf probe --list
probe_7057:zfree                       (on 7057:0x0000000000446420)
[root@ABCD]# cat /sys/kernel/debug/tracing/uprobe_events
p:probe_7057/zfree 7057:0x0000000000446420
[root@ABCD]# perf record -f -e probe_7057: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 7057 --del probe_7057:zfree
Remove event: probe_7057: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 7057 zfree@zsh+5
Added new event:
  probe_7057:zfree                         (on 0x446425)

You can now use it on all perf tools, such as:

perf record -e probe_7057:zfree -a sleep 1

[root@ABCD]# perf probe --list
probe_7057:zfree                       (on 7057:0x0000000000446425)
[root@ABCD]# cat /sys/kernel/debug/tracing/uprobe_events
p:probe_7057/zfree 7057:0x0000000000446425
[root@ABCD]# perf record -f -e probe_7057: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 7057 --del probe_7057:zfree
Remove event: probe_7057: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 7057 [email protected]
Added new event:
  probe_7057:write                       (on 0x36010c6060)

You can now use it on all perf tools, such as:

perf record -e probe_7057:write -a sleep 1

[root@ABCD]# perf probe --list
probe_7057:write                       (on 7057:0x00000036010c6060)
[root@ABCD]# cat /sys/kernel/debug/tracing/uprobe_events
p:probe_7057/write 7057:0x00000036010c6060
[root@ABCD]# perf record -f -e probe_7057: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 7057 --del probe_7057:write
Remove event: probe_7057: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 7057 write@/lib64/libc-2.5.so
Added new event:
  probe_7057:write                       (on 0x36010c6060)

You can now use it on all perf tools, such as:

perf record -e probe_7057:write -a sleep 1

[root@ABCD]# perf probe --list
probe_7057:write                       (on 7057:0x00000036010c6060)
[root@ABCD]# cat /sys/kernel/debug/tracing/uprobe_events
p:probe_7057/write 7057:0x00000036010c6060
[root@ABCD]# perf record -f -e probe_7057: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 7057 --del probe_7057:write
Remove event: probe_7057: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 7057 0x0000000000446420
Added new event:
  probe_7057:zfree_446420          (on 0x0000000000446420)

You can now use it on all perf tools, such as:

        perf record -e probe_7057:zfree_446420 -a sleep 1
[root@ABCD]# perf record -e probe_7057: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_7057:zfree_446420          (on 7057:0x0000000000446420)
[root@ABCD]#  perf list | grep probe
  probe_7057:zfree_446420            [Tracepoint event]
[root@ABCD]# perf probe -p 7057 --del probe_7057:zfree_446420
Remove event: probe_7057: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 7057 0x00000036010c6060
dded new event:
  probe_7057:__GI___libc_write_36010c6060          (on 0x00000036010c6060)

You can now use it on all perf tools, such as:

        perf record -e probe_7057:__GI___libc_write_36010c6060 -a sleep 1
[root@ABCD]# perf record -f -e probe_7057:__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 7057 zfree
Added new event:
  probe_7057:zfree		          (on 0x0000000000446420)

You can now use it on all perf tools, such as:

perf record -e probe_7057:zfree -a sleep 1

[root@ABCD]# perf record -e probe_7057: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     |   38 +++++-
 tools/perf/builtin-top.c       |   20 ---
 tools/perf/util/event.c        |   20 +++
 tools/perf/util/event.h        |    1 
 tools/perf/util/probe-event.c  |  237 +++++++++++++++++++++++++++++++++-------
 tools/perf/util/probe-event.h  |    9 +-
 tools/perf/util/probe-finder.h |    1 
 7 files changed, 252 insertions(+), 74 deletions(-)
tools/perf/builtin-probe.c +28 -10
index 152d6c9..ce59282 100644
@@ -55,6 +55,7 @@ static struct {
 	bool force_add;
 	bool show_lines;
 	int nr_probe;
+	pid_t pid;
 	struct probe_point probes[MAX_PROBES];
 	struct strlist *dellist;
 	struct map_groups kmap_groups;
@@ -73,7 +74,7 @@ static void parse_probe_event(const char *str)
 		die("Too many probes (> %d) are specified.", MAX_PROBES);
 
 	/* Parse perf-probe event into probe_point */
-	parse_perf_probe_event(str, pp, &session.need_dwarf);
+	parse_perf_probe_event(str, pp, &session.need_dwarf, session.pid);
 
 	pr_debug("%d arguments\n", pp->nr_args);
 }
@@ -203,6 +204,8 @@ static const struct option options[] = {
 		     "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]",
 		     "Show source code lines.", opt_show_lines),
 #endif
+	OPT_INTEGER('p', "pid", &session.pid,
+	"specify a pid for a uprobes based probe"),
 	OPT_END()
 };
 
@@ -258,12 +261,16 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 			pr_warning("  Error: Don't use --list with --line.\n");
 			usage_with_options(probe_usage, options);
 		}
+		if (session.pid) {
+			pr_warning("  Error: Don't use --list with -pid.\n");
+			usage_with_options(probe_usage, options);
+		}
 		show_perf_probe_events();
 		return 0;
 	}
 
 #ifndef NO_DWARF_SUPPORT
-	if (session.show_lines) {
+	if (session.show_lines && !session.pid) {
 		if (session.nr_probe != 0 || session.dellist) {
 			pr_warning("  Error: Don't use --line with"
 				   " --add/--del.\n");
@@ -283,12 +290,19 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 #endif
 
 	if (session.dellist) {
-		del_trace_kprobe_events(session.dellist);
+		if (session.pid)
+			del_trace_uprobe_events(session.dellist);
+		else
+			del_trace_kprobe_events(session.dellist);
+
 		strlist__delete(session.dellist);
 		if (session.nr_probe == 0)
 			return 0;
 	}
 
+	if (session.pid)
+		goto end_dwarf;
+
 	/* Add probes */
 	init_vmlinux();
 
@@ -334,18 +348,19 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 		break;
 	}
 	close(fd);
-
-end_dwarf:
 #endif /* !NO_DWARF_SUPPORT */
 
+end_dwarf:
 	/* Synthesize probes without dwarf */
 	for (i = 0; i < session.nr_probe; i++) {
 		pp = &session.probes[i];
 		if (pp->found)	/* This probe is already found. */
 			continue;
 
-		evaluate_probe_point(pp);
-		ret = synthesize_trace_kprobe_event(pp);
+		if (!session.pid)
+			evaluate_probe_point(pp);
+
+		ret = synthesize_trace_probe_event(pp);
 		if (ret == -E2BIG)
 			die("probe point definition becomes too long.");
 		else if (ret < 0)
@@ -353,8 +368,11 @@ end_dwarf:
 	}
 
 	/* Settng up probe points */
-	add_trace_kprobe_events(session.probes, session.nr_probe,
-				session.force_add);
+	if (session.pid)
+		add_trace_uprobe_events(session.probes, session.nr_probe,
+					session.force_add, session.pid);
+	else
+		add_trace_kprobe_events(session.probes, session.nr_probe,
+					session.force_add);
 	return 0;
 }
-
tools/perf/builtin-top.c +0 -20
index 1f52932..430d910 100644
@@ -1005,26 +1005,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 705ec63..e5190f2 100644
@@ -432,6 +432,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, u64 addr,
tools/perf/util/event.h +1 -0
index a33b949..282486b 100644
@@ -128,6 +128,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 +196 -41

440 lines not on this page · raw message

tools/perf/util/probe-event.h +6 -3
index 711287d..bcb7ab2 100644
@@ -7,14 +7,17 @@
 
 extern void parse_line_range_desc(const char *arg, struct line_range *lr);
 extern void parse_perf_probe_event(const char *str, struct probe_point *pp,
-				   bool *need_dwarf);
+				   bool *need_dwarf, pid_t pid);
 extern int synthesize_perf_probe_point(struct probe_point *pp);
 extern int synthesize_perf_probe_event(struct probe_point *pp);
-extern void parse_trace_kprobe_event(const char *str, struct probe_point *pp);
-extern int synthesize_trace_kprobe_event(struct probe_point *pp);
+extern int synthesize_trace_probe_event(struct probe_point *pp);
+extern void parse_trace_probe_event(const char *str, struct probe_point *pp);
 extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes,
 				    bool force_add);
 extern void del_trace_kprobe_events(struct strlist *dellist);
+extern void add_trace_uprobe_events(struct probe_point *probes, int nr_probes,
+				    bool force_add, pid_t pid);
+extern void del_trace_uprobe_events(struct strlist *dellist);
 extern void show_perf_probe_events(void);
 extern void show_line_range(struct line_range *lr);
 
tools/perf/util/probe-finder.h +1 -0
index 21f7354..b4d8ebc 100644
@@ -33,6 +33,7 @@ struct probe_point {
 
 	/* Output */
 	int			found;			/* Number of found probe points */
+	pid_t			upid;			/* uprobes only */
 	char			*probes[MAX_PROBES];	/* Output buffers (will be allocated)*/
 };
 
#19 lore raw
In reply to Srikar Dronamraju
Quoted 4 lines · * Srikar Dronamraju ([email protected]) wrote:

Uprobes Patches

Changelog from v3:
- Reverted to background page replacement as suggested by Peter Zijlstra.

Why ?

I'm not sure we reached any concensus about the need for a background page replacement.

Thanks,

Mathieu

Quoted 149 lines

- 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 postings: please refer: http://lkml.org/lkml/2010/5/6/273
and http://lkml.org/lkml/2010/3/20/107

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 this year (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.

- Rebase to -tip tree. (targeted for v5)
- 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 with bits in inat table.

The current patchset is based on 2.6.34.

Please do provide your valuable comments.

Thanks in advance.
Srikar

Srikar Dronamraju (10):

 1.  X86 instruction analysis: Move Macro W to insn.h
 2.  mm: Move replace_page() to mm/memory.c
 3.  user_bkpt: User Space Breakpoint Assistance Layer
 4.  user_bkpt: X86 details for User space breakpoint assistance
 5.  user_bkpt: Slot allocation for Execution out of line
 6.  uprobes: Uprobes Implementation
 7.  uprobes: X86 details for Uprobes
 8.  samples: Uprobes samples
 9.  uprobes: Uprobes Documentation patch

10. trace: Share common code for uprobes/kprobes traceevents
11. trace: uprobes trace_event interface
12. perf: Dont adjust symbols if lookup is by name.
13. perf: perf interface for uprobes.

 Documentation/uprobes.txt          |  236 ++++++++++
 arch/Kconfig                       |   31 ++
 arch/x86/Kconfig                   |    2 +
 arch/x86/include/asm/insn.h        |    7 +
 arch/x86/include/asm/thread_info.h |    2 +
 arch/x86/include/asm/user_bkpt.h   |   43 ++
 arch/x86/kernel/Makefile           |    3 +
 arch/x86/kernel/kprobes.c          |    7 -
 arch/x86/kernel/signal.c           |   17 +
 arch/x86/kernel/uprobes.c          |   77 ++++
 arch/x86/kernel/user_bkpt.c        |  572 ++++++++++++++++++++++++
 fs/exec.c                          |    4 +
 include/linux/mm.h                 |    4 +
 include/linux/mm_types.h           |    4 +
 include/linux/sched.h              |    4 +
 include/linux/uprobes.h            |  169 ++++++++
 include/linux/user_bkpt.h          |  305 +++++++++++++
 include/linux/user_bkpt_xol.h      |   40 ++
 kernel/Makefile                    |    3 +
 kernel/fork.c                      |   20 +
 kernel/trace/Kconfig               |   13 +
 kernel/trace/Makefile              |    1 +
 kernel/trace/trace.h               |   11 +
 kernel/trace/trace_kprobe.c        |   76 +----
 kernel/trace/trace_probe.h         |  111 +++++
 kernel/trace/trace_uprobe.c        |  839 ++++++++++++++++++++++++++++++++++++
 kernel/uprobes.c                   |  681 +++++++++++++++++++++++++++++
 kernel/user_bkpt.c                 |  589 +++++++++++++++++++++++++
 kernel/user_bkpt_xol.c             |  302 +++++++++++++
 mm/ksm.c                           |  112 -----
 mm/memory.c                        |  120 +++++
 samples/Kconfig                    |    7 +
 samples/Makefile                   |    2 +-
 samples/uprobes/Makefile           |   17 +
 samples/uprobes/uprobe_example.c   |   83 ++++
 tools/perf/builtin-probe.c         |   38 ++-
 tools/perf/builtin-top.c           |   20 -
 tools/perf/util/event.c            |   20 +
 tools/perf/util/event.h            |    1 +
 tools/perf/util/probe-event.c      |  237 +++++++++--
 tools/perf/util/probe-event.h      |    9 +-
 tools/perf/util/probe-finder.h     |    1 +
 tools/perf/util/symbol.c           |    6 +-
 43 files changed, 4576 insertions(+), 270 deletions(-)
Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
#20 lore raw
Quoted 6 lines · * Srikar Dronamraju ([email protected]) wrote:
Quoted 4 lines

Uprobes Patches

Changelog from v3:
- Reverted to background page replacement as suggested by Peter Zijlstra.

Quoted 9 lines

Why ?

I'm not sure we reached any concensus about the need for a background page replacement.

Thanks,

Mathieu

I was tested with access_process_vm(previous patchset) and the current (background page replacement) and the results are the same.

However Peter Zijlstra's contention still stands that we might be relying on a undocumented feature in the hardware and the flipping the pages isnt that hard or expensive.

Even Linus, (http://lkml.org/lkml/2010/1/27/87) had shown inclination towards background page replacement.

Also when uprobes implements global tracing support (i.e probing a particular symbol in a dso across processes), it has to rely on background page replacement.

Hence I based this patchset on background page replacement rather than on access_process_vm. Later On, if there is a consensus on using access_process_vm, we can make the corresponding changes.

--
Thanks and Regards
Srikar

#21 lore raw
Quoted 13 lines · * Srikar Dronamraju ([email protected]) wrote:
Quoted 13 lines · * Srikar Dronamraju ([email protected]) wrote:
Quoted 4 lines

Uprobes Patches

Changelog from v3:
- Reverted to background page replacement as suggested by Peter Zijlstra.

Why ?

I'm not sure we reached any concensus about the need for a background page replacement.

Thanks,

Quoted 8 lines
Quoted 2 lines

Mathieu

I was tested with access_process_vm(previous patchset) and the current (background page replacement) and the results are the same.

However Peter Zijlstra's contention still stands that we might be relying on a undocumented feature in the hardware

The access_process_vm scheme is in many ways similar to what kprobes has been doing for years. So I would not rely on that as a primary argument against the access_process_vm approach.

Quoted 9 lines

and the flipping the
pages isnt that hard or expensive.

Even Linus, (http://lkml.org/lkml/2010/1/27/87) had shown inclination towards background page replacement.

Also when uprobes implements global tracing support (i.e probing a particular symbol in a dso across processes), it has to rely on background page replacement.

Ah OK. If you have to use page replacement for global tracing, I see that as a good argument for using page replacement everywhere.

Quoted 4 lines

Hence I based this patchset on background page replacement rather than on access_process_vm. Later On, if there is a consensus on using access_process_vm, we can make the corresponding changes.

Well, page replacement seems like a good way to support global tracing, so I doubt that we'll ever revert back to access_process_vm.

Thanks,

Mathieu

Quoted 4 lines

--
Thanks and Regards
Srikar

Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
maintainer
#22 lore raw
In reply to Srikar Dronamraju
Quoted 4 lines · Srikar Dronamraju

Also when uprobes implements global tracing support (i.e probing a particular symbol in a dso across processes), it has to rely on background page replacement.

Uhm, how so?

#23 lore raw
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Srikar Dronamraju

Also when uprobes implements global tracing support (i.e probing a particular symbol in a dso across processes), it has to rely on background page replacement.

Uhm, how so?

For global tracing we cant use access_process_vm. The equivalent to access_process_vm for global tracing would be to use copy_to_user.

However I am sure people wouldnt be happy using copy_to_user on a page that other processes could have mapped.

So that leaves us with background page replacement method.
I do agree that we will not be using the same routine. But the technique should be something similar(or do you disagree?).

Or do you suggest any alternative methods for global tracing?

--
Thanks and Regards
Srikar

maintainer
#24 lore raw
Quoted 1 line · Srikar Dronamraju

Or do you suggest any alternative methods for global tracing?

COW the page for each existing and future mapping.

#25 lore raw
Quoted 5 lines · Peter Zijlstra
Quoted 1 line · Srikar Dronamraju

Or do you suggest any alternative methods for global tracing?

COW the page for each existing and future mapping.

Yes, we could certainly do this. However we could end up with multiple copies of the same page. And probably equal number of uprobe and probept structures.

--
Thanks and Regards
Srikar

Quoted 1 line
#26 lore raw
In reply to Srikar Dronamraju

Hi -

Quoted 1 line · Srikar Dronamraju

[...] For global tracing we can't use access_process_vm. [...]

Well, we have already demonstrated functional "global tracing" via access_process_vm, with the trade-off that affected pages are replicated on a per-process basis. (KSM could end up sharing them again, one supposes.)

- FChE