public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Indu Bhagat <indu.bhagat@oracle.com>
To: Jens Remus <jremus@linux.ibm.com>, binutils@sourceware.org
Cc: Andreas Krebbel <krebbel@linux.ibm.com>
Subject: Re: [RFC PATCH 9/9] s390: Initial support to generate .sframe from CFI directives in assembler
Date: Wed, 28 Feb 2024 23:01:08 -0800	[thread overview]
Message-ID: <77565421-0d23-4dec-a563-d7ff46a613b4@oracle.com> (raw)
In-Reply-To: <20240223170800.3993092-10-jremus@linux.ibm.com>

On 2/23/24 09:08, Jens Remus wrote:
> This introduces initial support to generate .sframe from CFI directives
> in assembler on s390x. Due to the following SFrame limitations it is
> incomplete and does not work for most real-world applications (i.e.
> generation of SFrame FDE is skipped):
> 

Hi Jens,

I am curious to know more about the use-case that triggered the interest 
in exploring SFrame for s390x.  It will be helpful if you can elaborate 
a bit.

My comments are scattered inline, but let me state some high-level 
comments here:

- As I previously mentioned, we cannot go down the route of tracking all 
callee-saved registers in SFrame.  This will significantly bloat up the 
information.  SFrame (like ORC) is designed to provide the exact offsets 
for stacktracing, which is what enables it to support fast stacktracing.

- In general, SFrame format relies heavily on ABI and is meant to cater 
to needs of ABI compliant code.  If some information is recoverable 
unambiguously from the ABI, SFrame does not encode it.  This manifests 
itself in what you already observed:

    + SFrame assumes RA is either on stack or a fixed/single designated 
register.
    + SFrame assumes FP is either on stack or a fixed/single designated 
register.
    + SFrame assumes CFA tracking is SP or FP based.

  Since the s390x ABI is flexible on each one of the above aspects, 
SFrame cannot be used easily.

> - SFrame FP/RA tracking assumes the register contents to be saved on
>    the stack (i.e. .cfi_offset). It does not support FP/RA register
>    contents being saved in other registers (i.e. .cfi_register). GCC
>    on s390x can be observed to save the FP/RA register contents in
>    other registers (e.g. floating-point registers).
> 

Is it possible to limit the choice of registers which the compiler uses 
to save the FP ?  If there is one more register to track (apart from 
CFA, RA, FP), we can see if an additional column can be accommodated in 
the format representation.

Is it possible to maintain the role "return address" for the register 
r14 at all times ?

What I am driving to is: If there is some degree of freedom here, is it 
possible to create a compiler option of, say -msframe, so that the 
generated code is more amenable to easier backtracing using SFrame format.

> - SFrame assumes a static RA register number. While the s390x ELF ABI
>    [1] specifies register 14 to contain the return address on entry,
>    GCC can be observed to copy the return address to another register
>    and may even use that to return. Additionally glibc on s390x has
>    two functions (mcount and fentry) that specify register 0 to hold
>    the return address. This would either require a change to glibc (if
>    possible) or SFrame support to track the RA register number specified
>    in CFI directive .cfi_return_column.
> 
> - SFrame assumes a static FP register number. The s390x ELF ABI [1]
>    does not specify any FP register number. GCC and clang on s390x
>    usually use register 11 as frame pointer. GCC on s390x can also be
>    observed to use register 14 (e.g. binutils and glibc builds). glibc
>    on s390x contains code that uses register 12 for the frame pointer.
>    This would require SFrame support to track the SP/FP register number
>    specified in CFI directives .cfi_def_cfa and .cfi_def_cfa_register.
> 
> - SFrame does not support CFI directive .cfi_val_offset. glibc on s390x
>    has two functions (mcount and fentry), that make use of that CFI
>    directive. This would either require a change in glibc (if possible)
>    or SFrame to support CFI directive .cfi_val_offset.
> 
> This s390x support is largely based on the AArch64 support from commit
> b52c4ee46657 ("gas: generate .sframe from CFI directives").
> 
> SFrame ABI/arch identifier SFRAME_ABI_S390_ENDIAN_BIG is introduced
> for s390 and added to the SFrame specification.
> 
> According to the s390x ELF ABI [1] the following calling conventions
> are used on s390x architecture:
> - Register 15 is used as stack pointer (SP). The CFA is initially
>    located at offset +160 from the SP.
> - Register 14 is used as return address (RA).
> - There is no dedicated frame pointer. GCC and LLVM currently use
>    register 11 as frame pointer.

Can FP be pinned to r11 in the hypothetical option of -msframe ?

> 
> The s390x ELF ABI [1] standard stack frame layout has the following
> conventions:
> - The return address (RA, r15) may be saved at offset -40 from the
>    CFA. Unlike x86 AMD64 architecture it is not necessarily saved on
>    the stack. Also compilers may use a non-standard stack frame layout,
>    such as but not limited to GCC with option -mpacked-stack.
>    Therefore SFrame RA tracking is used.

If SFrame RA tracking is enabled, this allows:
   - the return address to be in register (RA, r14), or
   - at an offset from CFA

Does the non-standard stack layout affect the identification of RA as 
CFA+offset ? If not, the remaining thing to worry about here (wrt SFrame 
usage) is if RA is saved in another register.

I see that the s390x does define r14 as return register.  But adds 
"Except at function entry, no special role
is assigned to r14.", which bring the complication for SFrame.

But at least for the packages that you have tested, we do not see 
occurrences of "skipping SFrame FDE due to .cfi_register specifying RA 
register (r14)", which is good to see.

> - The potential frame pointer (FP, r11) may be saved at offset -72
>    from the CFA. It is not necessarily saved on the stack and compilers
>    may use a non-standard stack frame layout (see above).
>    Therefore SFrame FP tracking is used.
> 
> Support for SFrame is only enabled for z/Architecture (s390x) with
> 64-bit architecture mode. It is disabled for 32-bit architecture mode
> and ESA/390 (s390).
> 
> Add s390-specific SFrame test cases. As for the error test cases add
> ones that use a non-default frame pointer (FP) register number and ones
> that save the return address (RA) in a non-default RA register number.
> 
> [1] ELF ABI s390x Supplement:
>      https://github.com/IBM/s390x-abi/releases
> [2] ELF ABI s390 Supplement:
>      https://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_s390.html
>      https://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_s390.pdf
> 
> include/
> 	* sframe.h (SFRAME_ABI_S390_ENDIAN_BIG): Define SFrame ABI/arch
> 	  identifier for s390x. Reference s390x architecture in comments.
> 
> libsframe/
> 	* doc/sframe-spec.texi: Document SFrame ABI/arch identifier for
> 	  s390x and reference s390x architecture.
> 
> gas/
> 	* config/tc-s390.h: s390x support to generate .sframe from CFI
> 	  directives in assembler.
> 	* config/tc-s390.c: Likewise.
> 	* gen-sframe.c: Reference s390x architecture in comments.
> 
> gas/testsuite/
> 	* gas/cfi-sframe/cfi-sframe.exp: Enable common SFrame test cases
> 	  for s390x. Add s390-specific SFrame test cases.
> 	* gas/cfi-sframe/cfi-sframe-s390-1.s: New s390-specific SFrame
> 	  test case.
> 	* gas/cfi-sframe/cfi-sframe-s390-1.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-2.s: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-2.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-1.s: New s390-specific
> 	  SFrame error test case that uses a non-default register number
> 	  for the frame pointer.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-1.l: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-2.s: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-2.l: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-3.s: New s390-specific
> 	  SFrame error test case that uses a non-default register number
> 	  to save the return address.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-3.l: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-4.s: New s390-specific
> 	  SFrame error test case that used a non-default return column
> 	  (return address) register number.
> 	* gas/cfi-sframe/cfi-sframe-s390-err-4.l: Likewise.
> 
> Reviewed-by: Andreas Krebbel <krebbel@linux.ibm.com>
> Signed-off-by: Jens Remus <jremus@linux.ibm.com>
> ---
> 
> Notes (jremus):
>      The SFrame support for s390x provided by this patch still has some open
>      issues, which need to be addressed. Any ideas or assistance to overcome
>      the SFrame limitations listed in the commit description are very
>      welcome.
>      
>      Note that unlike the AArch64 and x68 AMD64 implementation this s390x
>      implementation does statically initialize the architecture-dependent
>      variables s390_sframe_cfa_{sp|fp|ra}_reg, which are referenced by the
>      SFrame interface macros SFRAME_CFA_{SP|FP|RA}_REG. The other
>      implementations do initialize them in md_begin. I verified that all
>      occurrences of the macros SFRAME_CFA_{SP|FP|RA}_REG are in context of
>      test/read and never write.
>      Is there a reason to define the SFrame interface macros
>      SFRAME_CFA_{SP|FP|RA}_REG to variables? For instance should the SFrame
>      common code be able to modify these? Currently I do not see how it
>      would work well, if the architecture-specific code would change these
>      at run time. Similar for the predicate sframe_ra_tracking_p.
>      

No, there is no scenario so far where these variables will be modified. 
So the code can be simplified, yes.

IOW, you are right about that : SFrame format, in its current V2 
representation, does not support the flexibility of changing 
SFRAME_CFA_{SP|FP|RA}_REG dynamically across FDEs.

>      Example #1: Warnings when compiling binutils with SFrame
>      
>      $ ../configure CC="gcc -B$HOME/temp/binutils-gcc/bin -Wa,--gsframe" \
>        CXX="g++ -B$HOME/temp/binutils-gcc/bin -Wa,--gsframe" \
>        --prefix=$HOME/temp/binutils-sframe
>      $ make -j $(nprocs) 2>&1 | tee make.log
>      $ grep --only-matching "Warning:.*" make.log | sort | uniq -c
>            1 Warning: skipping SFrame FDE due to .cfi_def_cfa specifying CFA
>              base register other than SP or FP (14 instead of 15 or 11)
>          205 Warning: skipping SFrame FDE due to .cfi_register specifying FP
>              register (11)
>           56 Warning: skipping SFrame FDE due to .cfi_register specifying SP
>              register (15)
>      
>      Example #2: Warnings when compiling glibc with SFrame
>      
>      $ ../configure CC="gcc -B$HOME/temp/binutils-sframe/bin -Wa,--gsframe" \
>        CXX="g++ -B$HOME/temp/binutils-sframe/bin -Wa,--gsframe" \
>        --prefix=$HOME/temp/glibc-sframe
>      $ make -j $(nprocs) 2>&1 | tee make.log
>      $ grep --only-matching "Warning:.*" make.log | sort | uniq -c
>            2 Warning: skipping SFrame FDE due to .cfi_def_cfa_register
>              specifying CFA base register other than SP or FP (12 instead of
>              15 or 11)
>            7 Warning: skipping SFrame FDE due to .cfi_def_cfa specifying CFA
>              base register other than SP or FP (14 instead of 15 or 11)
>          225 Warning: skipping SFrame FDE due to .cfi_register specifying FP
>              register (11)
>          187 Warning: skipping SFrame FDE due to .cfi_register specifying SP
>              register (15)
>            2 Warning: skipping SFrame FDE due to DWARF CFI op CFI_escape
>              (0x103)
>            2 Warning: skipping SFrame FDE due to non-default DWARF return
>              column (0 instead of 14)
>      
>      .cfi_def_cfa 14, ... originates from GCC generated code, which uses
>      register %r14 as frame pointer (FP).
>      
>      .cfi_def_cfa_register 12 originates from hand-written assembler code
>      sysdeps/s390/s390-64/dl-trampoline.S, which uses register %r12 as frame
>      pointer (FP).
>      
>      .cfi_return_column 0 and .cfi_escape both originate from hand-written
>      assembler code sysdeps/s390/s390-64/s390x-mcount.S, which is compiled
>      twice (with and without -DSHARED).
>      
>      - .cfi_escape 0x14, 0x15, 0x14: Is used to code
>        ".cfi_val_offset r15, -160", which would require binutils 2.28+ (glibc
>        currently supports a minimum binutils 2.25). This CFI directive states
>        that the contents of register %r15 are CFA-160 (not to be confused
>        with saved at CFA-160).
>      

This indirection property is not representable in SFrame format 
currently. BTW, x86, AArch64 also suffer with the negative consequences 
of this limitation, but in practice I have run into very limited 
occurrences of this.

>      - .cfi_return_column 0: The following comment explains why register %r0
>        contains the return address:
>      
>        "The _mcount implementation now has to call __mcount_internal with the
>        address of .LP0 as first parameter and the return address as second
>        parameter. &.LP0 was loaded to %r1 and the return address is in %r14.
>        _mcount may not modify any register.
>      
>        Alternatively, at the start of each function __fentry__ is called
>        using a single
>      
>                brasl  0,__fentry__
>      
>        instruction.  In this case %r0 points to the callee, and %r14 points
>        to the caller.  These values need to be passed to __mcount_internal
>        using the same sequence as for _mcount, so the code below is shared
>        between both functions.
>        The only major difference is that __fentry__ cannot return through
>        %r0, in which the return address is located, because br instruction
>        is a no-op with this register.  Therefore %r1, which is clobbered by
>        the PLT anyway, is used."
>      
>        Excerpt of the relevant glibc source code:
>      
>                .globl C_SYMBOL_NAME(MCOUNT_SYMBOL)
>                .type C_SYMBOL_NAME(MCOUNT_SYMBOL), @function
>                cfi_startproc
>                .align ALIGNARG(4)
>        C_LABEL(MCOUNT_SYMBOL)
>                cfi_return_column (glue(r, MCOUNT_CALLEE_REG))
>                /* Save the caller-clobbered registers.  */
>                aghi  %r15,-224
>                cfi_adjust_cfa_offset (224)
>                /* binutils 2.28+: .cfi_val_offset r15, -160 */
>                .cfi_escape \
>                        /* DW_CFA_val_offset */ 0x14, \
>                        /* r15 */               0x0f, \
>                        /* scaled offset */     0x14
>                stmg  %r14,%r5,160(%r15)
>      
>                cfi_offset (r14, -224)
>                cfi_offset (r0, -224+16)
>        ...
> 

Thanks for your clear notes. They were very helpful.

Indu

  reply	other threads:[~2024-02-29  7:01 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-23 17:07 [RFC PATCH 0/9] s390: Initial support to generate SFrame info " Jens Remus
2024-02-23 17:07 ` [PATCH v2 1/9] x86: Remove unused SFrame CFI RA register variable Jens Remus
2024-02-24  7:38   ` Indu Bhagat
2024-02-26 13:01     ` Jan Beulich
2024-02-26 14:51       ` Jens Remus
2024-02-27  9:08       ` Indu Bhagat
2024-02-27  9:11         ` Jan Beulich
2024-02-26 15:04     ` Jens Remus
2024-02-23 17:07 ` [PATCH v2 2/9] aarch64: Align SFrame terminology in comments to specs and x86 Jens Remus
2024-02-24  7:44   ` Indu Bhagat
2024-02-23 17:07 ` [PATCH v2 3/9] sframe: Enhance comments for SFRAME_CFA_*_REG macros Jens Remus
2024-02-24  7:46   ` Indu Bhagat
2024-02-26 13:51     ` Jan Beulich
2024-02-27  8:53       ` Indu Bhagat
2024-02-27  8:57         ` Jan Beulich
2024-02-27  9:01           ` Indu Bhagat
2024-02-23 17:07 ` [PATCH v2 4/9] readelf/objdump: Dump SFrame CFA fixed FP and RA offsets Jens Remus
2024-02-24  7:48   ` Indu Bhagat
2024-02-23 17:07 ` [PATCH v2 5/9] gas: Print DWARF call frame insn name in SFrame warning message Jens Remus
2024-02-24  7:56   ` Indu Bhagat
2024-02-26 15:37     ` Jens Remus
2024-02-23 17:07 ` [PATCH v2 6/9] gas: Skip SFrame FDE if CFI specifies non-FP/SP base register Jens Remus
2024-02-24  7:57   ` Indu Bhagat
2024-02-23 17:07 ` [PATCH v2 7/9] gas: Warn if SFrame FDE is skipped due to non-default return column Jens Remus
2024-02-24  8:43   ` Indu Bhagat
2024-02-26 16:19     ` Jens Remus
2024-02-23 17:07 ` [PATCH v2 8/9] gas: User readable warnings if SFrame FDE is not generated Jens Remus
2024-02-29  7:39   ` Indu Bhagat
2024-04-09 14:14     ` Jens Remus
2024-02-23 17:08 ` [RFC PATCH 9/9] s390: Initial support to generate .sframe from CFI directives in assembler Jens Remus
2024-02-29  7:01   ` Indu Bhagat [this message]
2024-04-09 15:07     ` Jens Remus
2024-02-23 17:27 ` [RFC PATCH 0/9] s390: Initial support to generate SFrame info " Jens Remus
2024-02-23 21:16 ` Indu Bhagat
2024-04-05 18:26   ` Indu Bhagat
2024-04-09 14:19     ` Jens Remus
  -- strict thread matches above, loose matches on Subject: below --
2024-02-22 16:01 Jens Remus
2024-02-22 16:01 ` [RFC PATCH 9/9] s390: Initial support to generate .sframe " Jens Remus

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=77565421-0d23-4dec-a563-d7ff46a613b4@oracle.com \
    --to=indu.bhagat@oracle.com \
    --cc=binutils@sourceware.org \
    --cc=jremus@linux.ibm.com \
    --cc=krebbel@linux.ibm.com \
    /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 read-only IMAP folder(s) and NNTP newsgroup(s).