Received: by 2002:a05:6a10:1a4d:0:0:0:0 with SMTP id nk13csp638027pxb; Tue, 1 Feb 2022 07:27:33 -0800 (PST) X-Google-Smtp-Source: ABdhPJznbCeuDTlnR1OdHWN6iYIjqLxhToP7MaitT7SLkT/6RalxITW57z5jTYCtADqcaz1AlRcU X-Received: by 2002:a17:90b:4d05:: with SMTP id mw5mr2909893pjb.34.1643729253474; Tue, 01 Feb 2022 07:27:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1643729253; cv=none; d=google.com; s=arc-20160816; b=rrURQrYtpzGXVcJvpvjCDCsLBc0AZU0aKJAktdxhM4RLZdVWFFkOlVYZtL5Y6sBfMJ KLGdHnbxq9lrnRPLrXh0u9qm5Rish0kfgszVBdh1Uo5Rt3feK5sEbuUsVMy6EcVvGekw OZgOKR1MY+aHaoQ2+AKbgshbCn2y9dHzXdtpw1ZS1qcl4yutIRLB8mqxbpkpyQGdeJE6 Hm6LXiPCT81D3DbnRxjobHn1wz+2TkqlncDilCbc+9Rjzx43Ilzq2uaffWJFbaslxt7J rD4XwfYbHpKxgOL34wFd8O6306dLeMNjJklQx4IRba6Aa7Bq/wrzhzA9lYBXu5y3idDZ XmQA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=0KSbZVCWtqKg5AJyT9TNbnz75Qo8XF+ysBnQWJQzgIA=; b=roVdFFnj+8G7ooqTpR/d/r3Gqx2lj3mU5t8rPPiXeMn02crmS1CFLkZ7B6sIUe7Lsv ancWc19PXfgYjqrM86qYuOUtrEGwwsGoUghPCcJ3s+Qv4JjLTwSXBU+kiJVbggEX0Xer l9IgYeXBfdA6zkUQQejnsrkSu9JFdThOhQCmvUdTESDgSc+PYosZdAID1rrUIiBaZo26 XFWNj0dIvV5hRlYNRFQFPczsyXhkp7jI4/Vsbqqy49mtfPcYc2aMlMMX20ZVPTctS7+G aH4YM2NJbfqkM42/QUk5UX9BG83Ci7IXbr13DZiRcQQtNqdV3wu4VkRicoZyg9MC60mH YCZA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=stcJQUVq; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id mh4si2992156pjb.38.2022.02.01.07.27.20; Tue, 01 Feb 2022 07:27:33 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=stcJQUVq; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1357768AbiAaFDH (ORCPT + 99 others); Mon, 31 Jan 2022 00:03:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1357745AbiAaFCn (ORCPT ); Mon, 31 Jan 2022 00:02:43 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 88BF9C06173B; Sun, 30 Jan 2022 21:02:28 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 44E16B80ADD; Mon, 31 Jan 2022 05:02:27 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DA649C340E8; Mon, 31 Jan 2022 05:02:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1643605346; bh=oB3OHV7PT9qKuceHnY4r/cZGELfQzY+D6DiCbhHAX1w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=stcJQUVqdMu01XowloYJx3Jf29eO7j7FCgn1lX2GsQ7/cHHT0NujCfEXtOmgP659G Ngy1ZmZGe/OqEATUU0m7h0ds1iBWLYFrgOI8cxNc2yH/TwRJpZrECzng/2iALrnnTl w90Nd54DmZCigZPJ44EA72wRG6H4yfMaMxBudidrs2TTVnDAQ48JVbgomLozAJFs0l SOE/PEH2YU6vSX6XuH/QPaEqA5EBLM2d9rbvk0j/3KVEL4UsgkgM0gBqbHiqFjSYfI Uw0F3L0yQGe3rVufvzzt8bug3IOetbS+18ek4W91VraGFlZb9r4SYDx+vCl/XE6Bdm cP1wK4cfvkCNQ== From: Masami Hiramatsu To: Jiri Olsa , Alexei Starovoitov Cc: Daniel Borkmann , Andrii Nakryiko , Masami Hiramatsu , netdev@vger.kernel.org, bpf@vger.kernel.org, lkml , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Steven Rostedt , "Naveen N . Rao" , Anil S Keshavamurthy , "David S . Miller" Subject: [PATCH v7 10/10] docs: fprobe: Add fprobe description to ftrace-use.rst Date: Mon, 31 Jan 2022 14:02:20 +0900 Message-Id: <164360534036.65877.17482125933683080.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <164360522462.65877.1891020292202285106.stgit@devnote2> References: <164360522462.65877.1891020292202285106.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a documentation of fprobe for the user who needs this interface. Signed-off-by: Masami Hiramatsu --- Changes in v7: - Clarify unregister_fprobe() guarantee the callbacks will no longer being called after that. - Fix some wording. Changes in v6: - Update document according to the latest spec. --- Documentation/trace/fprobe.rst | 171 ++++++++++++++++++++++++++++++++++++++++ Documentation/trace/index.rst | 1 2 files changed, 172 insertions(+) create mode 100644 Documentation/trace/fprobe.rst diff --git a/Documentation/trace/fprobe.rst b/Documentation/trace/fprobe.rst new file mode 100644 index 000000000000..4275e95e16bc --- /dev/null +++ b/Documentation/trace/fprobe.rst @@ -0,0 +1,171 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================================== +Fprobe - Function entry/exit probe +================================== + +.. Author: Masami Hiramatsu + +Introduction +============ + +Instead of using ftrace full feature, if you only want to attach callbacks +on function entry and exit, similar to the kprobes and kretprobes, you can +use fprobe. Compared with kprobes and kretprobes, fprobe gives faster +instrumentation for multiple functions with single handler. This document +describes how to use fprobe. + +The usage of fprobe +=================== + +The fprobe is a wrapper of ftrace (+ kretprobe-like return callback) to +attach callbacks to multiple function entry and exit. User needs to set up +the `struct fprobe` and pass it to `register_fprobe()`. + +Typically, `fprobe` data structure is initialized with the `entry_handler` +and/or `exit_handler` as below. + +.. code-block:: c + + struct fprobe fp = { + .entry_handler = my_entry_callback, + .exit_handler = my_exit_callback, + }; + +To enable the fprobe, call one of register_fprobe(), register_fprobe_ips(), and +register_fprobe_syms(). These register the fprobe with different type of +parameters. + +The register_fprobe() enables a fprobe by function-name filters. +E.g. this enables @fp on "func*()" function except "func2()".:: + + register_fprobe(&fp, "func*", "func2"); + +The register_fprobe_ips() enables a fprobe by ftrace-location addresses. +E.g. + +.. code-block:: c + + unsigned long ips[] = { 0x.... }; + + register_fprobe_ips(&fp, ips, ARRAY_SIZE(ips)); + +And the register_fprobe_syms() enables a fprobe by symbol names. +E.g. + +.. code-block:: c + + char syms[] = {"func1", "func2", "func3"}; + + register_fprobe_syms(&fp, syms, ARRAY_SIZE(syms)); + +To disable (remove from functions) this fprobe, call:: + + unregister_fprobe(&fp); + +You can temporally (soft) disable the fprobe by:: + + disable_fprobe(&fp); + +and resume by:: + + enable_fprobe(&fp); + +The above is defined by including the header:: + + #include + +Same as ftrace, the registered callback will start being called some time +after the register_fprobe() is called and before it returns. See +:file:`Documentation/trace/ftrace.rst`. + +Also, the unregister_fprobe() will guarantee that the both enter and exit +handlers are no longer being called by functions after unregister_fprobe() +returns as same as unregister_ftrace_function(). + +The fprobe entry/exit handler +============================= + +The prototype of the entry/exit callback function is as follows: + +.. code-block:: c + + void callback_func(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs); + +Note that both entry and exit callback has same ptototype. The @entry_ip is +saved at function entry and passed to exit handler. + +@fp + This is the address of `fprobe` data structure related to this handler. + You can embed the `fprobe` to your data structure and get it by + container_of() macro from @fp. The @fp must not be NULL. + +@entry_ip + This is the entry address of the traced function (both entry and exit). + +@regs + This is the `pt_regs` data structure at the entry and exit. Note that + the instruction pointer of @regs may be different from the @entry_ip + in the entry_handler. If you need traced instruction pointer, you need + to use @entry_ip. On the other hand, in the exit_handler, the instruction + pointer of @regs is set to the currect return address. + +Share the callbacks with kprobes +================================ + +Since the recursion safety of the fprobe (and ftrace) is a bit different +from the kprobes, this may cause an issue if user wants to run the same +code from the fprobe and the kprobes. + +The kprobes has per-cpu 'current_kprobe' variable which protects the +kprobe handler from recursion in any case. On the other hand, the fprobe +uses only ftrace_test_recursion_trylock(), which will allow interrupt +context calls another (or same) fprobe during the fprobe user handler is +running. + +This is not a matter in cases if the common callback shared among the +kprobes and the fprobe has its own recursion detection, or it can handle +the recursion in the different contexts (normal/interrupt/NMI.) +But if it relies on the 'current_kprobe' recursion lock, it has to check +kprobe_running() and use kprobe_busy_*() APIs. + +Fprobe has FPROBE_FL_KPROBE_SHARED flag to do this. If your common callback +code will be shared with kprobes, please set FPROBE_FL_KPROBE_SHARED +*before* registering the fprobe, like: + +.. code-block:: c + + fprobe.flags = FPROBE_FL_KPROBE_SHARED; + + register_fprobe(&fprobe, "func*", NULL); + +This will protect your common callback from the nested call. + +The missed counter +================== + +The `fprobe` data structure has `fprobe::nmissed` counter field as same as +kprobes. +This counter counts up when; + + - fprobe fails to take ftrace_recursion lock. This usually means that a function + which is traced by other ftrace users is called from the entry_handler. + + - fprobe fails to setup the function exit because of the shortage of rethook + (the shadow stack for hooking the function return.) + +Since `fprobe::nmissed` field is counted up in both case, the former case +will skip both of entry and exit callback, and the latter case will skip exit +callback, but in both case the counter is just increased by 1. + +Note that if you set the FTRACE_OPS_FL_RECURSION and/or FTRACE_OPS_FL_RCU to +`fprobe::ops::flags` (ftrace_ops::flags) when registering the fprobe, this +counter may not work correctly, because those will skip fprobe's callback. + + +Functions and structures +======================== + +.. kernel-doc:: include/linux/fprobe.h +.. kernel-doc:: kernel/trace/fprobe.c + diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst index 3769b9b7aed8..b9f3757f8269 100644 --- a/Documentation/trace/index.rst +++ b/Documentation/trace/index.rst @@ -9,6 +9,7 @@ Linux Tracing Technologies tracepoint-analysis ftrace ftrace-uses + fprobe kprobes kprobetrace uprobetracer