[v3,1/4] aarch64: make explicit that CFI gnu_window_save is for Sparc, not AArch64

Message ID 20250113112206.1071596-2-matthieu.longo@arm.com
State New
Headers
Series aarch64: add DWARF and SFrame support for new CFI directive used for PAuth_LR |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

Matthieu Longo Jan. 13, 2025, 11:22 a.m. UTC
  - add a detailed comment when parsing DW_CFA_GNU_window_save in SFrame to
  explain why we are checking whether the targeted architecture is AArch64,
  whereas this CFI is a Sparc extension.
- replace .cfi_gnu_window_save by .cfi_negate_ra_state in existing AArch64
  DWARF tests as this is the preferred directive since GCC 15.
- add a new AARch64 test to check backward compatibility with old GCC
  versions that emits .cfi_gnu_window_save.
---
 gas/gen-sframe.c                              |  8 +++-
 gas/testsuite/gas/aarch64/pac_ab_key.s        |  4 +-
 .../gas/aarch64/pac_compat_cfi_window_save.d  | 44 +++++++++++++++++++
 .../gas/aarch64/pac_compat_cfi_window_save.s  | 20 +++++++++
 4 files changed, 73 insertions(+), 3 deletions(-)
 create mode 100644 gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.d
 create mode 100644 gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.s
  

Comments

Indu Bhagat Jan. 13, 2025, 11:10 p.m. UTC | #1
On 1/13/25 3:22 AM, Matthieu Longo wrote:
> - add a detailed comment when parsing DW_CFA_GNU_window_save in SFrame to
>    explain why we are checking whether the targeted architecture is AArch64,
>    whereas this CFI is a Sparc extension.
> - replace .cfi_gnu_window_save by .cfi_negate_ra_state in existing AArch64
>    DWARF tests as this is the preferred directive since GCC 15.
> - add a new AARch64 test to check backward compatibility with old GCC

Nit: AARch64 -> AArch64

>    versions that emits .cfi_gnu_window_save.
> ---
>   gas/gen-sframe.c                              |  8 +++-
>   gas/testsuite/gas/aarch64/pac_ab_key.s        |  4 +-
>   .../gas/aarch64/pac_compat_cfi_window_save.d  | 44 +++++++++++++++++++
>   .../gas/aarch64/pac_compat_cfi_window_save.s  | 20 +++++++++
>   4 files changed, 73 insertions(+), 3 deletions(-)
>   create mode 100644 gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.d
>   create mode 100644 gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.s
> 
> diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
> index 71296f2f4fb..a3c40bdd735 100644
> --- a/gas/gen-sframe.c
> +++ b/gas/gen-sframe.c
> @@ -1273,7 +1273,13 @@ sframe_xlate_do_aarch64_negate_ra_state (struct sframe_xlate_ctx *xlate_ctx,
>   }
>   
>   /* Translate DW_CFA_GNU_window_save into SFrame context.
> -   DW_CFA_AARCH64_negate_ra_state is multiplexed with DW_CFA_GNU_window_save.
> +   DW_CFA_GNU_window_save is a DWARF Sparc extension, but is multiplexed with a
> +   directive of DWARF AArch64 extension: DW_CFA_AARCH64_negate_ra_state.
> +   The AArch64 backend of GCC 14 and older versions was emitting mistakenly the
> +   Sparc CFI directive (.cfi_window_save).  From GCC 15, the AArch64 backend
> +   only emits .cfi_negate_ra_state.  For backward compatibility, the handler for
> +   .cfi_window_save needs to check whether the directive was used in a AArch ABI

Nit: AArch -> AArch64 ?

In context of the SFrame changes here,  AArch64 should still make sense 
(although the multiplexing of directives is applicable to the 32-bit Arm 
as well).

OK for the SFrame file changes.

> +   context or not.
>      Return SFRAME_XLATE_OK if success.  */
>   
>   static int
> diff --git a/gas/testsuite/gas/aarch64/pac_ab_key.s b/gas/testsuite/gas/aarch64/pac_ab_key.s
> index 4b328e72ae4..3b81919409d 100644
> --- a/gas/testsuite/gas/aarch64/pac_ab_key.s
> +++ b/gas/testsuite/gas/aarch64/pac_ab_key.s
> @@ -7,7 +7,7 @@ _Z5foo_av:
>   .LFB0:
>   	.cfi_startproc
>   	hint	25 // paciasp
> -	.cfi_window_save
> +	.cfi_negate_ra_state
>   	stp	x29, x30, [sp, -16]!
>   	.cfi_def_cfa_offset 16
>   	.cfi_offset 29, -16
> @@ -23,7 +23,7 @@ _Z5foo_bv:
>   	.cfi_startproc
>   	.cfi_b_key_frame
>   	hint	27 // pacibsp
> -	.cfi_window_save
> +	.cfi_negate_ra_state
>   	stp	x29, x30, [sp, -16]!
>   	.cfi_def_cfa_offset 16
>   	.cfi_offset 29, -16
> diff --git a/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.d b/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.d
> new file mode 100644
> index 00000000000..8e59086c1b4
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.d
> @@ -0,0 +1,44 @@
> +#objdump: --dwarf=frames
> +# This test is only valid on ELF based ports.
> +#notarget: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd
> +
> +## ARMv8.3 adds support for 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 stack trace generator 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 usually used to convey this information.
> +## .cfi_negate_ra_state and .cfi_window_save are both in the processor-specific
> +## numbering space, but use the same code value in the dwarf tables.
> +## In GCC 14 and older, the Sparc DWARF extension .cfi_window_save is emitted
> +## instead of .cfi_negate_ra_state, but it mapped to the same value. GCC 15 fixed
> +## this naming issue and there is no change to the object file created when the
> +## source is assembled. Nevertheless the support for the SPARC directive is
> +## preserved in binutils for backward compatibility with existing GCC releases,
> +## hence this test.
> +
> +.+:     file .+
> +
> +Contents of the .eh_frame section:
> +
> +0+ 0+10 0+ CIE
> +  Version:               1
> +  Augmentation:          "zR"
> +  Code alignment factor: 4
> +  Data alignment factor: -8
> +  Return address column: 30
> +  Augmentation data:     1b
> +  DW_CFA_def_cfa: r31 \(sp\) ofs 0
> +
> +0+14 0+18 0+18 FDE cie=0+ pc=0+\.\.0+8
> +  DW_CFA_advance_loc: 4 to 0+4
> +  DW_CFA_AARCH64_negate_ra_state
> +  DW_CFA_advance_loc: 4 to 0+8
> +  DW_CFA_def_cfa_offset: 16
> +  DW_CFA_offset: r29 \(x29\) at cfa-16
> +  DW_CFA_offset: r30 \(x30\) at cfa-8
> +  DW_CFA_nop
> +  DW_CFA_nop
> diff --git a/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.s b/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.s
> new file mode 100644
> index 00000000000..92a54f3a344
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.s
> @@ -0,0 +1,20 @@
> +	.arch armv8-a
> +	.text
> +	.align	2
> +	.global	_Z5foo_av
> +	.type	_Z5foo_av, %function
> +_Z5foo_av:
> +.LFB0:
> +	.cfi_startproc
> +	hint	25 // paciasp
> +	.cfi_window_save // really .cfi_negate_ra_state
> +	stp	x29, x30, [sp, -16]!
> +	.cfi_def_cfa_offset 16
> +	.cfi_offset 29, -16
> +	.cfi_offset 30, -8
> +	.cfi_endproc
> +.LFE0:
> +	.size	_Z5foo_av, .-_Z5foo_av
> +	.align	2
> +	.global	_Z5foo_bv
> +	.type	_Z5foo_bv, %function
  
Matthieu Longo Jan. 14, 2025, 10:55 a.m. UTC | #2
On 2025-01-13 23:10, Indu Bhagat wrote:
> On 1/13/25 3:22 AM, Matthieu Longo wrote:
>> - add a detailed comment when parsing DW_CFA_GNU_window_save in SFrame to
>>    explain why we are checking whether the targeted architecture is 
>> AArch64,
>>    whereas this CFI is a Sparc extension.
>> - replace .cfi_gnu_window_save by .cfi_negate_ra_state in existing 
>> AArch64
>>    DWARF tests as this is the preferred directive since GCC 15.
>> - add a new AARch64 test to check backward compatibility with old GCC
> 
> Nit: AARch64 -> AArch64
> 

Fixed.

>>    versions that emits .cfi_gnu_window_save.
>> ---
>>   gas/gen-sframe.c                              |  8 +++-
>>   gas/testsuite/gas/aarch64/pac_ab_key.s        |  4 +-
>>   .../gas/aarch64/pac_compat_cfi_window_save.d  | 44 +++++++++++++++++++
>>   .../gas/aarch64/pac_compat_cfi_window_save.s  | 20 +++++++++
>>   4 files changed, 73 insertions(+), 3 deletions(-)
>>   create mode 100644 gas/testsuite/gas/aarch64/ 
>> pac_compat_cfi_window_save.d
>>   create mode 100644 gas/testsuite/gas/aarch64/ 
>> pac_compat_cfi_window_save.s
>>
>> diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
>> index 71296f2f4fb..a3c40bdd735 100644
>> --- a/gas/gen-sframe.c
>> +++ b/gas/gen-sframe.c
>> @@ -1273,7 +1273,13 @@ sframe_xlate_do_aarch64_negate_ra_state (struct 
>> sframe_xlate_ctx *xlate_ctx,
>>   }
>>   /* Translate DW_CFA_GNU_window_save into SFrame context.
>> -   DW_CFA_AARCH64_negate_ra_state is multiplexed with 
>> DW_CFA_GNU_window_save.
>> +   DW_CFA_GNU_window_save is a DWARF Sparc extension, but is 
>> multiplexed with a
>> +   directive of DWARF AArch64 extension: DW_CFA_AARCH64_negate_ra_state.
>> +   The AArch64 backend of GCC 14 and older versions was emitting 
>> mistakenly the
>> +   Sparc CFI directive (.cfi_window_save).  From GCC 15, the AArch64 
>> backend
>> +   only emits .cfi_negate_ra_state.  For backward compatibility, the 
>> handler for
>> +   .cfi_window_save needs to check whether the directive was used in 
>> a AArch ABI
> 
> Nit: AArch -> AArch64 ?

Fixed.

> In context of the SFrame changes here,  AArch64 should still make sense 
> (although the multiplexing of directives is applicable to the 32-bit Arm 
> as well).
> 
> OK for the SFrame file changes.

Thanks.

>> +   context or not.
>>      Return SFRAME_XLATE_OK if success.  */
>>   static int
>> diff --git a/gas/testsuite/gas/aarch64/pac_ab_key.s b/gas/testsuite/ 
>> gas/aarch64/pac_ab_key.s
>> index 4b328e72ae4..3b81919409d 100644
>> --- a/gas/testsuite/gas/aarch64/pac_ab_key.s
>> +++ b/gas/testsuite/gas/aarch64/pac_ab_key.s
>> @@ -7,7 +7,7 @@ _Z5foo_av:
>>   .LFB0:
>>       .cfi_startproc
>>       hint    25 // paciasp
>> -    .cfi_window_save
>> +    .cfi_negate_ra_state
>>       stp    x29, x30, [sp, -16]!
>>       .cfi_def_cfa_offset 16
>>       .cfi_offset 29, -16
>> @@ -23,7 +23,7 @@ _Z5foo_bv:
>>       .cfi_startproc
>>       .cfi_b_key_frame
>>       hint    27 // pacibsp
>> -    .cfi_window_save
>> +    .cfi_negate_ra_state
>>       stp    x29, x30, [sp, -16]!
>>       .cfi_def_cfa_offset 16
>>       .cfi_offset 29, -16
>> diff --git a/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.d b/ 
>> gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.d
>> new file mode 100644
>> index 00000000000..8e59086c1b4
>> --- /dev/null
>> +++ b/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.d
>> @@ -0,0 +1,44 @@
>> +#objdump: --dwarf=frames
>> +# This test is only valid on ELF based ports.
>> +#notarget: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd
>> +
>> +## ARMv8.3 adds support for 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 stack trace generator 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 usually used to convey this 
>> information.
>> +## .cfi_negate_ra_state and .cfi_window_save are both in the 
>> processor-specific
>> +## numbering space, but use the same code value in the dwarf tables.
>> +## In GCC 14 and older, the Sparc DWARF extension .cfi_window_save is 
>> emitted
>> +## instead of .cfi_negate_ra_state, but it mapped to the same value. 
>> GCC 15 fixed
>> +## this naming issue and there is no change to the object file 
>> created when the
>> +## source is assembled. Nevertheless the support for the SPARC 
>> directive is
>> +## preserved in binutils for backward compatibility with existing GCC 
>> releases,
>> +## hence this test.
>> +
>> +.+:     file .+
>> +
>> +Contents of the .eh_frame section:
>> +
>> +0+ 0+10 0+ CIE
>> +  Version:               1
>> +  Augmentation:          "zR"
>> +  Code alignment factor: 4
>> +  Data alignment factor: -8
>> +  Return address column: 30
>> +  Augmentation data:     1b
>> +  DW_CFA_def_cfa: r31 \(sp\) ofs 0
>> +
>> +0+14 0+18 0+18 FDE cie=0+ pc=0+\.\.0+8
>> +  DW_CFA_advance_loc: 4 to 0+4
>> +  DW_CFA_AARCH64_negate_ra_state
>> +  DW_CFA_advance_loc: 4 to 0+8
>> +  DW_CFA_def_cfa_offset: 16
>> +  DW_CFA_offset: r29 \(x29\) at cfa-16
>> +  DW_CFA_offset: r30 \(x30\) at cfa-8
>> +  DW_CFA_nop
>> +  DW_CFA_nop
>> diff --git a/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.s b/ 
>> gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.s
>> new file mode 100644
>> index 00000000000..92a54f3a344
>> --- /dev/null
>> +++ b/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.s
>> @@ -0,0 +1,20 @@
>> +    .arch armv8-a
>> +    .text
>> +    .align    2
>> +    .global    _Z5foo_av
>> +    .type    _Z5foo_av, %function
>> +_Z5foo_av:
>> +.LFB0:
>> +    .cfi_startproc
>> +    hint    25 // paciasp
>> +    .cfi_window_save // really .cfi_negate_ra_state
>> +    stp    x29, x30, [sp, -16]!
>> +    .cfi_def_cfa_offset 16
>> +    .cfi_offset 29, -16
>> +    .cfi_offset 30, -8
>> +    .cfi_endproc
>> +.LFE0:
>> +    .size    _Z5foo_av, .-_Z5foo_av
>> +    .align    2
>> +    .global    _Z5foo_bv
>> +    .type    _Z5foo_bv, %function
>
  

Patch

diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index 71296f2f4fb..a3c40bdd735 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -1273,7 +1273,13 @@  sframe_xlate_do_aarch64_negate_ra_state (struct sframe_xlate_ctx *xlate_ctx,
 }
 
 /* Translate DW_CFA_GNU_window_save into SFrame context.
-   DW_CFA_AARCH64_negate_ra_state is multiplexed with DW_CFA_GNU_window_save.
+   DW_CFA_GNU_window_save is a DWARF Sparc extension, but is multiplexed with a
+   directive of DWARF AArch64 extension: DW_CFA_AARCH64_negate_ra_state.
+   The AArch64 backend of GCC 14 and older versions was emitting mistakenly the
+   Sparc CFI directive (.cfi_window_save).  From GCC 15, the AArch64 backend
+   only emits .cfi_negate_ra_state.  For backward compatibility, the handler for
+   .cfi_window_save needs to check whether the directive was used in a AArch ABI
+   context or not.
    Return SFRAME_XLATE_OK if success.  */
 
 static int
diff --git a/gas/testsuite/gas/aarch64/pac_ab_key.s b/gas/testsuite/gas/aarch64/pac_ab_key.s
index 4b328e72ae4..3b81919409d 100644
--- a/gas/testsuite/gas/aarch64/pac_ab_key.s
+++ b/gas/testsuite/gas/aarch64/pac_ab_key.s
@@ -7,7 +7,7 @@  _Z5foo_av:
 .LFB0:
 	.cfi_startproc
 	hint	25 // paciasp
-	.cfi_window_save
+	.cfi_negate_ra_state
 	stp	x29, x30, [sp, -16]!
 	.cfi_def_cfa_offset 16
 	.cfi_offset 29, -16
@@ -23,7 +23,7 @@  _Z5foo_bv:
 	.cfi_startproc
 	.cfi_b_key_frame
 	hint	27 // pacibsp
-	.cfi_window_save
+	.cfi_negate_ra_state
 	stp	x29, x30, [sp, -16]!
 	.cfi_def_cfa_offset 16
 	.cfi_offset 29, -16
diff --git a/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.d b/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.d
new file mode 100644
index 00000000000..8e59086c1b4
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.d
@@ -0,0 +1,44 @@ 
+#objdump: --dwarf=frames
+# This test is only valid on ELF based ports.
+#notarget: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd
+
+## ARMv8.3 adds support for 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 stack trace generator 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 usually used to convey this information.
+## .cfi_negate_ra_state and .cfi_window_save are both in the processor-specific
+## numbering space, but use the same code value in the dwarf tables.
+## In GCC 14 and older, the Sparc DWARF extension .cfi_window_save is emitted
+## instead of .cfi_negate_ra_state, but it mapped to the same value. GCC 15 fixed
+## this naming issue and there is no change to the object file created when the
+## source is assembled. Nevertheless the support for the SPARC directive is
+## preserved in binutils for backward compatibility with existing GCC releases,
+## hence this test.
+
+.+:     file .+
+
+Contents of the .eh_frame section:
+
+0+ 0+10 0+ CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 4
+  Data alignment factor: -8
+  Return address column: 30
+  Augmentation data:     1b
+  DW_CFA_def_cfa: r31 \(sp\) ofs 0
+
+0+14 0+18 0+18 FDE cie=0+ pc=0+\.\.0+8
+  DW_CFA_advance_loc: 4 to 0+4
+  DW_CFA_AARCH64_negate_ra_state
+  DW_CFA_advance_loc: 4 to 0+8
+  DW_CFA_def_cfa_offset: 16
+  DW_CFA_offset: r29 \(x29\) at cfa-16
+  DW_CFA_offset: r30 \(x30\) at cfa-8
+  DW_CFA_nop
+  DW_CFA_nop
diff --git a/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.s b/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.s
new file mode 100644
index 00000000000..92a54f3a344
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/pac_compat_cfi_window_save.s
@@ -0,0 +1,20 @@ 
+	.arch armv8-a
+	.text
+	.align	2
+	.global	_Z5foo_av
+	.type	_Z5foo_av, %function
+_Z5foo_av:
+.LFB0:
+	.cfi_startproc
+	hint	25 // paciasp
+	.cfi_window_save // really .cfi_negate_ra_state
+	stp	x29, x30, [sp, -16]!
+	.cfi_def_cfa_offset 16
+	.cfi_offset 29, -16
+	.cfi_offset 30, -8
+	.cfi_endproc
+.LFE0:
+	.size	_Z5foo_av, .-_Z5foo_av
+	.align	2
+	.global	_Z5foo_bv
+	.type	_Z5foo_bv, %function