--- /dev/null
+#as:
+#objdump: --sframe=.sframe
+#name: SFrame generation on aarch64
+#...
+Contents of the SFrame section .sframe:
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 1
+    Num FREs: 3
+
+  Function Index :
+
+    func idx \[0\]: pc = 0x0, size = 80 bytes
+    STARTPC +CFA +FP +RA +
+    0+0000 +sp\+0 +u +u +
+    0+0004 +sp\+144 +u +u +
+    0+004c +sp\+0 +u +u +
+#pass
 
--- /dev/null
+        .cfi_sections .sframe
+       .cfi_startproc
+       stp     x19, x20, [sp, -144]!
+       .cfi_def_cfa_offset 144
+       .cfi_offset 19, -144
+       .cfi_offset 20, -136
+       stp     x21, x22, [sp, 16]
+       stp     x23, x24, [sp, 32]
+       stp     x25, x26, [sp, 48]
+       stp     x27, x28, [sp, 64]
+       stp     d8, d9, [sp, 80]
+       stp     d10, d11, [sp, 96]
+       stp     d12, d13, [sp, 112]
+       stp     d14, d15, [sp, 128]
+       .cfi_offset 21, -128
+       .cfi_offset 22, -120
+       .cfi_offset 23, -112
+       .cfi_offset 24, -104
+       .cfi_offset 25, -96
+       .cfi_offset 26, -88
+       .cfi_offset 27, -80
+       .cfi_offset 28, -72
+       .cfi_offset 72, -64
+       .cfi_offset 73, -56
+       .cfi_offset 74, -48
+       .cfi_offset 75, -40
+       .cfi_offset 76, -32
+       .cfi_offset 77, -24
+       .cfi_offset 78, -16
+       .cfi_offset 79, -8
+       nop
+       ldp     x21, x22, [sp, 16]
+       ldp     x23, x24, [sp, 32]
+       ldp     x25, x26, [sp, 48]
+       ldp     x27, x28, [sp, 64]
+       ldp     d8, d9, [sp, 80]
+       ldp     d10, d11, [sp, 96]
+       ldp     d12, d13, [sp, 112]
+       ldp     d14, d15, [sp, 128]
+       ldp     x19, x20, [sp], 144
+       .cfi_restore 20
+       .cfi_restore 19
+       .cfi_restore 78
+       .cfi_restore 79
+       .cfi_restore 76
+       .cfi_restore 77
+       .cfi_restore 74
+       .cfi_restore 75
+       .cfi_restore 72
+       .cfi_restore 73
+       .cfi_restore 27
+       .cfi_restore 28
+       .cfi_restore 25
+       .cfi_restore 26
+       .cfi_restore 23
+       .cfi_restore 24
+       .cfi_restore 21
+       .cfi_restore 22
+       .cfi_def_cfa_offset 0
+       ret
+       .cfi_endproc
 
--- /dev/null
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame generation using CFI directive .cfi_sections
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 1
+    Num FREs: 1
+
+  Function Index :
+    func idx \[0\]: pc = 0x0, size = 0 bytes
+    STARTPC + CFA + FP + RA +
+#pass
 
--- /dev/null
+       .cfi_sections .sframe
+       .cfi_startproc
+       .cfi_endproc
 
--- /dev/null
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: Command line option for generating SFrame
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 1
+    Num FREs: 1
+
+  Function Index :
+    func idx \[0\]: pc = 0x0, size = 0 bytes
+    STARTPC + CFA + FP + RA +
+#pass
 
--- /dev/null
+       .cfi_startproc
+       .cfi_endproc
 
--- /dev/null
+#as:
+#objdump: --sframe=.sframe
+#name: SFrame can co-exist with EH Frame
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 1
+    Num FREs: 1
+
+  Function Index :
+    func idx \[0\]: pc = 0x0, size = 0 bytes
+    STARTPC + CFA + FP + RA +
+#pass
 
--- /dev/null
+       .cfi_sections .eh_frame
+       .cfi_sections .sframe
+       .cfi_startproc
+       .cfi_endproc
 
--- /dev/null
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame cfi_def_cfa_offset test
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 1
+    Num FREs: 3
+
+  Function Index :
+    func idx \[0\]: pc = 0x0, size = 12 bytes
+    STARTPC + CFA + FP + RA +
+#...
+    0+0004 +sp\+16 +u +u +
+    0+0008 +sp\+32 +u +u +
+
+#pass
 
--- /dev/null
+## Testcase for cfi_def_cfa_offset
+       .cfi_startproc
+       .long 0
+       .cfi_def_cfa_offset 16
+       .long 0
+       .cfi_def_cfa_offset 32
+       .long 0
+       .cfi_endproc
 
--- /dev/null
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame cfi_adjust_cfa_offset test
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 1
+    Num FREs: 3
+
+  Function Index :
+    func idx \[0\]: pc = 0x0, size = 12 bytes
+    STARTPC + CFA + FP + RA +
+#...
+    0+0004 +sp\+16 +u +u +
+    0+0008 +sp\+24 +u +u +
+
+#pass
 
--- /dev/null
+       .cfi_startproc
+       .long 0
+       .cfi_def_cfa_offset 16
+       .long 0
+       .cfi_adjust_cfa_offset 8
+       .long 0
+       .cfi_endproc
 
--- /dev/null
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame cfi_offset test
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 1
+    Num FREs: 3
+
+  Function Index :
+    func idx \[0\]: pc = 0x0, size = 12 bytes
+    STARTPC + CFA + FP + RA +
+#...
+    0+0004 +sp\+8 +u +u +
+    0+0008 +sp\+8 +u +u +
+
+#pass
 
--- /dev/null
+       .cfi_startproc
+       .long 0
+       .cfi_def_cfa_offset 8
+       .long 0
+       .cfi_offset 0, 8
+       .long 0
+       .cfi_endproc
 
--- /dev/null
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame cfi_rel_offset test
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 1
+    Num FREs: 3
+
+  Function Index :
+    func idx \[0\]: pc = 0x0, size = 12 bytes
+    STARTPC + CFA + FP + RA +
+#...
+    0+0004 +sp\+8 +u +u +
+    0+0008 +sp\+8 +u +u +
+
+#pass
 
--- /dev/null
+       .cfi_startproc
+       .long 0
+       .cfi_def_cfa_offset 8
+       .long 0
+       .cfi_rel_offset 1, 8
+       .long 0
+       .cfi_endproc
 
--- /dev/null
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame cfi_val_offset test
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 1
+    Num FREs: 2
+
+  Function Index :
+    func idx \[0\]: pc = 0x0, size = 8 bytes
+    STARTPC + CFA + FP + RA +
+#...
+    0+0004 +sp\+16 +u +u +
+
+#pass
 
--- /dev/null
+## cfi_val_offset when used with "not interesting" registers (from the
+## perspective of SFrame section, non FP/RA registers are not
+## interesting) does not affect the asynchronicity of the SFrame
+## unwind information.  Such CFI directives can be skipped for SFrame
+## unwind info generation.
+       .cfi_startproc
+       .long 0
+       .cfi_def_cfa_offset 16
+       .cfi_val_offset 1, 8
+       .cfi_val_offset 2, -32
+       .long 0
+       .cfi_endproc
 
--- /dev/null
+#as: -O0
+#objdump: --sframe=.sframe
+#name: SFrame generation on x86_64
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 1
+    Num FREs: 4
+
+  Function Index :
+
+    func idx \[0\]: pc = 0x0, size = 25 bytes
+    STARTPC +CFA +FP +RA +
+    0+0000 +sp\+8 +u +u +
+    0+0001 +sp\+16 +c\-16 +u +
+    0+0004 +fp\+16 +c\-16 +u +
+    0+0018 +sp\+8 +c\-16 +u +
+#pass
 
--- /dev/null
+        .cfi_sections .sframe
+       .cfi_startproc
+        pushq   %rbp
+        .cfi_def_cfa_offset 16
+        .cfi_offset 6, -16
+        movq    %rsp, %rbp
+        .cfi_def_cfa_register 6
+        pushq   %r15
+        pushq   %r14
+        pushq   %r13
+        pushq   %r12
+        pushq   %rbx
+  ## These CFI opcodes are not interesting
+  ## for SFrame generation and will be
+  ## skipped.
+        .cfi_offset 15, -24
+        .cfi_offset 14, -32
+        .cfi_offset 13, -40
+        .cfi_offset 12, -48
+        .cfi_offset 3, -56
+        nop
+        popq    %rbx
+        popq    %r12
+        popq    %r13
+        popq    %r14
+        popq    %r15
+        popq    %rbp
+        .cfi_def_cfa 7, 8
+        ret
+        .cfi_endproc
 
--- /dev/null
+# Copyright (C) 2022 Free Software Foundation, Inc.
+
+# 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 3 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+if { ![is_elf_format] } then {
+    return
+}
+
+proc gas_sframe_check { } {
+    global check_as_sframe_result
+    global AS
+    global ASFLAGS
+    if [info exists check_as_sframe_result] {
+       return $check_as_sframe_result
+    }
+
+    set as_file "tmpdir/check_as_sframe.s"
+    set as_fh [open $as_file w 0666]
+    puts $as_fh "# Generated file. DO NOT EDIT"
+    puts $as_fh "\t.cfi_startproc"
+    puts $as_fh "\t.cfi_endproc"
+    close $as_fh
+    remote_download host $as_file
+    verbose -log "Checking SFrame support in AS:"
+
+    set old_ASFLAGS "$ASFLAGS"
+    set ASFLAGS "$ASFLAGS --gsframe"
+
+    global comp_output
+
+    set output_file "tmpdir/check_as_sframe.out"
+    set status [gas_host_run "$AS $ASFLAGS $as_file" "2>$output_file"]
+    set comp_output [file_contents "$output_file"]
+    set ASFLAGS "$old_ASFLAGS"
+
+    if { ![string match "" $comp_output]
+        || [string match "*sframe not supported for target*" $comp_output] } then {
+       verbose -log "SFrame not supported in AS"
+       return 0
+    } else {
+       verbose -log "SFrame supported in AS"
+       return 1
+    }
+}
+
+proc gas_x86_64_check { } {
+    global NM
+    global NMFLAGS
+
+    set status [gas_host_run "$NM $NMFLAGS --help" ""]
+    return [regexp "targets:.*x86-64" [lindex $status 1]];
+}
+
+# common tests
+if  { ([istarget "x86_64-*-*"] || [istarget "aarch64*-*-*"]) \
+       && [gas_sframe_check] } then {
+
+    global ASFLAGS
+    set old_ASFLAGS "$ASFLAGS"
+
+    run_dump_test "cfi-sframe-common-1"
+    run_dump_test "cfi-sframe-common-2"
+    run_dump_test "cfi-sframe-common-3"
+    run_dump_test "cfi-sframe-common-4"
+    run_dump_test "cfi-sframe-common-5"
+    run_dump_test "cfi-sframe-common-6"
+    run_dump_test "cfi-sframe-common-7"
+    run_dump_test "cfi-sframe-common-8"
+
+    run_dump_test "common-empty-1"
+    run_dump_test "common-empty-2"
+    run_dump_test "common-empty-3"
+    run_dump_test "common-empty-4"
+}
+
+# x86-64 specific tests
+if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
+    if { [gas_x86_64_check] } then {
+       set ASFLAGS "$ASFLAGS --64"
+       run_dump_test "cfi-sframe-x86_64-1"
+       set ASFLAGS "$old_ASFLAGS"
+    }
+}
+
+# aarch64 specific tests
+if { [istarget "aarch64*-*-*"] && [gas_sframe_check] } then {
+    run_dump_test "cfi-sframe-aarch64-1"
+}
 
--- /dev/null
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: Uninteresting cfi directives generate an empty SFrame section
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 0
+    Num FREs: 0
+
+#pass
 
--- /dev/null
+      .cfi_sections .sframe
+      .cfi_startproc
+      .cfi_remember_state
+      .cfi_restore_state
+      .cfi_endproc
 
--- /dev/null
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame supports only FP/SP based CFA
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 0
+    Num FREs: 0
+
+#pass
 
--- /dev/null
+## CFA register is not defined to be SP/FP.
+## No SFrame unwind info for this function will be generated.
+       .cfi_startproc simple
+       .long 0
+       .long 0
+       .cfi_adjust_cfa_offset 16
+       .long 0
+       .cfi_endproc
 
--- /dev/null
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame supports only default return column
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 0
+    Num FREs: 0
+
+#pass
 
--- /dev/null
+## The return column is not the default value.
+## No SFrame unwind info for this function will be generated.
+       .cfi_startproc
+       .cfi_return_column 0
+       .long 0
+       .long 0
+       .cfi_adjust_cfa_offset 16
+       .long 0
+       .cfi_endproc
 
--- /dev/null
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame supports only default return column
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_1
+    Flags: NONE
+    Num FDEs: 0
+    Num FREs: 0
+
+#pass
 
--- /dev/null
+## ARMv8.3 addded support a new security feature named Pointer Authentication. The
+## main idea behind this is to use the unused bits in the pointer values.
+## Each pointer is patched with a PAC before writing to memory, and is verified
+## before using it.
+## When the pointers are mangled, the unwinder needs to know so it can mask off
+## the PAC from the pointer value to recover the return address, and
+## conversely, skip doing so if the pointers are not mangled.
+##
+## .cfi_negate_ra_state CFI directive is used to convey this information.
+##
+## SFrame does not have any means to represent this information at this time.
+       .cfi_startproc
+       .long 0
+       .cfi_def_cfa_offset 16
+       .cfi_negate_ra_state
+       .long 0
+       .cfi_endproc