linux-toolchains.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Indu Bhagat <indu.bhagat@oracle.com>
To: linux-toolchains@vger.kernel.org
Cc: "Jose E. Marchesi" <jose.marchesi@oracle.com>,
	Daan De Meyer <daandemeyer@meta.com>,
	Kris Van Hees <kris.van.hees@oracle.com>,
	Elena Zannoni <elena.zannoni@oracle.com>,
	andrii@kernel.org
Subject: Re: Unwinding user-space programs in the kernel using SFrame format
Date: Tue, 24 Jan 2023 13:58:27 -0800	[thread overview]
Message-ID: <ed33a0a2-b42e-4835-eb19-06b614868c37@oracle.com> (raw)
In-Reply-To: <7dcae1d1-b0f5-a497-a473-26a43f1b1ad6@oracle.com>

On 1/12/23 12:30, Indu Bhagat wrote:
> Hello,
> 
> This email is to initiate discussion/collaboration on adding a new 
> user-space program unwinder in the kernel, an unwinder which uses the 
> SFrame format.
> 
> What is SFrame format?
> SFrame is the Simple Frame format.  It represents the minimal necessary 
> information needed for backtracing - i.e. Canonical Frame Address (CFA), 
> Frame Pointer (FP), and Return Address (RA).  SFrame unwind information 
> is available in a section called .sframe, which is itself presented in a 
> new segment of its own, PT_GNU_SFRAME.  SFrame format is supported for 
> AMD64 and AARCH64 (be/le) ABIs only.
> 
> How can I experiment with the SFrame format support?
> The support for SFrame format is available in binutils trunk. GNU 
> assembler when passed a --gsframe command line option, generates the 
> .sframe section. The GNU assembler uses the .cfi_* asm directives 
> emitted by the compiler to generate an .sframe section. GNU ld merges 
> the input .sframe sections as necessary, no explicit command line option 
> is needed. There is support in objdump/readelf as well, pass a --sframe 
> option to dump the .sframe section in textual format.
> 
> Where can I find details about the format?
> More details are available in the include/sframe.h in binutils repo 
> (https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=include/sframe.h).  SFrame spec is also present in the binutils trunk.  Some more content should be available online in the form of GNU Cauldron and LPC 2022 presentations: this was talked about under the name "CTF Frame", but has since been renamed to "SFrame".
> 

The SFrame format specification doc made it to the (binutils 2.40) 
release documentation last week 
https://sourceware.org/binutils/docs/sframe-spec.html. Adding here in 
case that helps.

> Why is SFrame based unwinder useful?
> Having an unwinder for user-space programs based on SFrame format can be 
> useful:
>    - enabling -fno-omit-frame-pointers has performance implications and 
> other issues.
>    - Compared to .eh_frame info, SFrame is a simpler format to decode 
> and generate backtraces. SFrame unwinder itself, hence, is small and 
> simple 
> (https://github.com/oracle/binutils-gdb/blob/oracle/sframe-unwinder/libsframe/sframe-backtrace.c is how an SFrame based unwinder can look like. This code uses libsframe APIs like sframe_decode, sframe_find_fre, sframe_fre_get_fp_offset etc. to generate backtraces.).
> 
> There was some interest, at LPC 2022, in exploring an SFrame-based 
> userspace unwinder for the kernel.  To get started on that, some 
> discussion on following items will be great. (Please feel free to 
> add/delete/correct any items; my knowledge about the kernel and its 
> internals remains limited).
> 
> Userspace unwinder selection
> ----------------------------
> IIUC, userspace unwinding is always frame-pointer based in the kernel. 
> This is unlike kernel-space unwinding where there are a set of unwinders 
> to chose from: say, for x86_64, UNWINDER_ORC / UNWINDER_FRAME_POINTER / 
> UNWINDER_GUESS. Additionally, for kernel stack unwinding, there is also 
> a framework in place to plug-and-play these different unwinders.
> 
> For userspace stack unwinding, first, we may want to add new config 
> options, such that:
>     - USERSPACE_UNWINDER_SFRAME => This option enables the SFrame 
> unwinder for unwinding user stack traces as the first choice.  User 
> programs must be built with SFrame support. If not, no SFrame section 
> will be present in the user program binary; In such a case, the 
> userspace unwinder defaults to frame pointer unwinding.
>     - USERSPACE_UNWINDER_FRAME_POINTER => userspace unwinding does frame 
> pointer based unwinding only. User programs must be built with frame 
> pointer preservation build flags to ensure useful stack traces.
> 
> Second, regarding "the framework" needed for non-frame-pointer-based 
> unwinders, more thought is needed.
> 
> Interface of the userspace unwinder
> -----------------------------------
> * OPTION 1
> This one might be overly simplified but is an option.  We add the 
> following stub:
> 
>     ...
>     if (check_sframe_state_p (current)) // checks for SFrame sections if 
> CONFIG_USER_UNWINDER_SFRAME is true
>        sframe_callchain_user (entry, regs); // current is implicit, 
> stores callchain entries as it unwinds using .sframe sections
>     ...
> 
> in the following target APIs in x86_64 and aarch64 to give the desired 
> effect of "userspace unwinder selection"
>    -- perf_callchain_user in arch/x86/events/core.c
>    -- perf_callchain_user in in arch/arm64/kernel/perf_callchain.c
> 
> where the functions look like:
>    static inline bool check_sframe_state_p(struct task_struct *task);
>    void sframe_callchain_user(struct perf_callchain_entry_ctx *entry, 
> struct pt_regs *regs);
> 
> Here, sframe_callchain_user () will, first, perform an operation similar 
> to dl_iterate_phdr, because we need the location of the SFrame sections 
> for unwinding. This means, for every sframe_unwind() call, we go over 
> the memory mappings of "current" task_struct and find the locations of 
> the .sframe sections of the program + its DSOs from pages that contain 
> the ELF program headers. Next, using these SFrame sections, it will then 
> decode the SFrame section and unwind.
> 
> * OPTION 2
> A possible optimization is to instead:
> 
> 1. Cache some sframe related state, "struct *sframe_state", in the 
> "struct task_struct" (guarded by CONFIG_USER_UNWINDER_SFRAME), and
> 2. Use an API like so "void sframe_callchain_user(struct *sframe_state, 
> struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)"
> This state (struct sframe_state) is simply put: data about the size and 
> addr of the text and SFrame segments of the program and its DSOs. 
> Ideally this state can be setup at task setup time and needs to be 
> updated only if there is any change in the DSOs (added or removed) [1]. 
> The size of the struct sframe_state itself is small here, as SFrame 
> sections can be decoded on-the-fly with no need for additional mallocs.
> 
> [1] PS: That this detection of "add/delete of DSOs in a user program" is 
> possible in some efficient way in the kernel remains an assumption; I 
> still need to figure things out. Any inputs on this appreciated.
> 
> Other framework
> ---------------
> The kernel stack unwinders adhere to some interface allowing them to be 
> used interchangeably.  The requirements of the userspace unwinder are a 
> bit different though: not all user applications may be compiled with 
> SFrame support, which means there needs to be a way we fall back on the 
> frame-pointer based unwinder in the kernel for unwinding user programs.
> 
> This requirement, however, does not mean that some framework changes 
> shouldn't be done now to make things work better.
> 
> Any feedback/ideas are appreciated.  I have also not been able yet to 
> evaluate what other impacts could this have on perf, if at all.
> 
> Thanks


  reply	other threads:[~2023-01-24 21:58 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-12 20:30 Unwinding user-space programs in the kernel using SFrame format Indu Bhagat
2023-01-24 21:58 ` Indu Bhagat [this message]
2023-02-06 19:44 ` Unwinding user-space programs in the kernel using SFrame fo Steven Rostedt
2023-02-07  8:36   ` Indu Bhagat

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ed33a0a2-b42e-4835-eb19-06b614868c37@oracle.com \
    --to=indu.bhagat@oracle.com \
    --cc=andrii@kernel.org \
    --cc=daandemeyer@meta.com \
    --cc=elena.zannoni@oracle.com \
    --cc=jose.marchesi@oracle.com \
    --cc=kris.van.hees@oracle.com \
    --cc=linux-toolchains@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).