Skip to content

[aadwarf64]] Add DW_CFA_AARCH64_set_ra_state stack frame operation - #346

Merged
stuij merged 6 commits into
ARM-software:mainfrom
walkerkd:master
Jan 19, 2026
Merged

stuij merged 6 commits into
ARM-software:mainfrom
walkerkd:master

Conversation

@walkerkd

Copy link
Copy Markdown
Contributor

The DW_CFA_AARCH64_set_ra_state operation updates the RA_SIGN_STATE pseudo register with the current signing state. If the signing state includes signing is DW_AARCH64_RA_SIGNED_SP_PC, then it also provides the offset to the signing instruction so that the PC value used in the signing can be calculated.

The DW_CFA_AARCH64_negate_ra_state_with_pc operation has been marked as deprecated. This is because it has been found that it is not suitable for describing all cases where the PC was used to sign the return address (see #327)

The contents of the RA_SIGN_STATE pseudo register is also changed from being described in terms of a set of bits to being a series of defined values.

Previously the state of the RA_SIGN_STATE pseudo register was changed implicitly by the DW_CFA_AARCH64_negate_ra_state and DW_CFA_AARCH64_set_ra_state operations. This meant that the actual encoding was actually internal to any implementation.

Now with the introduction of the DW_CFA_AARCH64_set_ra_state operation the encoding has been made externally visible. So the opportunity has been taken now to change the encoding to a simpler form.

The DW_CFA_AARCH64_set_ra_state operation updates the RA_SIGN_STATE
pseudo register with the current signing state. If the signing
state includes signing is DW_AARCH64_RA_SIGNED_SP_PC, then it also
provides the offset to the signing instruction so that the PC value
used in the signing can be calculated.

The DW_CFA_AARCH64_negate_ra_state_with_pc operation has
been marked as deprecated.  This is because it has been
found that it is not suitable for describing all cases
where the PC was used to sign the return address (see
ARM-software#327)

The contents of the RA_SIGN_STATE pseudo register is also changed
from being described in terms of a set of bits to being a series
of defined values.

Previously the state of the RA_SIGN_STATE pseudo register was
changed implicitly by the DW_CFA_AARCH64_negate_ra_state and
DW_CFA_AARCH64_set_ra_state operations. This meant that the actual
encoding was actually internal to any implementation.

Now with the introduction of the DW_CFA_AARCH64_set_ra_state
operation the encoding has been made externally visible.  So the
opportunity has been taken now to change the encoding to a simpler
form.
Comment thread aadwarf64/aadwarf64.rst Outdated
Comment on lines +251 to +252
| | | - Deprecated |
| | | DW_CFA_AARCH64_negate_ra_state. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this should be DW_CFA_AARCH64_negate_ra_state_with_pc.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for spotting that. I'll fix it.

walkerkd and others added 3 commits September 23, 2025 09:57
Incorrect change history deprecated state
DW_CFA_AARCH64_negate_ra_state corrected to
DW_CFA_AARCH64_negate_ra_state_with_pc

@rearnsha rearnsha left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of grammatical nits/comments and I think we should add some background to the deprecation of ...negate_ra_state_with_pc

Comment thread aadwarf64/aadwarf64.rst Outdated

9. Normally, the program counter is restored from the return address, however
having both LR and PC columns is useful for describing asynchronously
having both LR and PC diversifiers are useful for describing asynchronously

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in this context, 'having both ... is useful' is the correct form. 'having both' here creates a singular subject for the sentence.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread aadwarf64/aadwarf64.rst Outdated
Comment on lines +641 to +643
The ``DW_CFA_AARCH64_set_ra_state`` instruction takes two operands; an unsigned
LEB128 value representing a return address state ra_state and a signed LEB128
factored offset. The required action is to set the RA_SIGN_STATE pseudo-register

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use '...takes two operands: an unsigned ...; and a signed ...' to

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. The current style is what is used in the base DWARF specification. But the suggested change does make it clearer what are the 2 operands.

Comment thread aadwarf64/aadwarf64.rst Outdated
as the signing/authenticating PAC instruction, otherwise it is has the value 0.
The code location information can be used for authenticating the return address.

The ``DW_CFA_AARCH64_negate_ra_state_with_pc`` operation toggles between the

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this re-emphasize that this is deprecated (and perhaps explain why)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a statement to re-emphasize that this instruction is deprecate and a short explanation in non-normative text (the base DWARF specification does this by using italics for non-normative text so I have used the same convention here).

walkerkd and others added 2 commits January 7, 2026 15:03
- Fixes some minor grammatical issues.
- Add an explicit deprecation statement for the
  DW_CFA_AARCH64_negate_ra_state_with_pc instruction in the
  section describing the instruction.  It has already been
  marked as deprecated in the AArch64 vendor CFA operations
  table.

@Stylie777 Stylie777 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a Compiler Development POV this change makes sense, and addresses the issue of the CFI collecting an incorrect PC value.

Have you got an example that demonstrates the change in Assembly that will be generated? Would be helpful for me so I can visualise the changes being made.

@walkerkd

Copy link
Copy Markdown
Contributor Author

So the example from the original defect pseudo-assembler report #327 where I have also added the PACPC / AUTPC instructions:

  .cfi_startproc 
func:
   // Frame setup
   .cfi_save ...
   PACPC
   .cfi_negate_ra_with_pc  // Save auth state and remember location
   some code
   CBZ L0
   some more code
   // Restore frame
   AUTPC SIGNED 
   .cfi_negate_ra_with_pc  // Restore state (using previously stored location)
   .cfi_restore ...
   RET
L0:
   .cfi_save ...
   .cfi_negate_ra_with_pc  // ERROR - this saves the wrong location
   Some additional code
   AUTPC SIGNED 
   .cfi_negate_ra_with_pc     // Uses wrong location.
   RET
...

This updated form using the new DW_CFA_AARCH64_set_ra_state instruction would be:

  .cfi_startproc 
func:
   // Frame setup
   .cfi_save ...
SIGNED:
   PACPC
   cfi_set_ra_state DW_AARCH64_RA_SIGNED_SP, factored_offset_SIGNED  // Auth state LR & PC (signed with SIGNED)
   some code
   CBZ L0
   some more code
   // Restore frame
   AUTPC SIGNED 
   .cfi_set_ra_state DW_AARCH64_RA_NOT_SIGNED, factored_offset_SIGNED  // Auth state unsigned
   .cfi_restore ...
   RET
L0:
   .cfi_save ...
   .cfi_set_ra_state DW_AARCH64_RA_SIGNED_SP, factored_offset_SIGNED  // Auth state LR & PC (signed with SIGNED)
   Some additional code
   AUTPC SIGNED 
   .cfi_set_ra_state DW_AARCH64_RA_NOT_SIGNED, factored_offset_SIGNED  // Auth state unsigned
   RET
...

where factored_offset_SIGNED is (SIGNED-currentPC)/code_alignment_factor.
code_alignment_factor is defined in the CFI header.

Hopefully this makes it clearer what the change means to an implementation using the new instruction.

@Stylie777 Stylie777 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @walkerkd, this looks good and makes sense from my POV

@stuij
stuij merged commit 1d6cf2e into ARM-software:main Jan 19, 2026
1 check passed
jroelofs added a commit to jroelofs/llvm-project that referenced this pull request Jun 23, 2026
The new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE
DWARF pseudo-register for use when unwinding, to indicate whether the value of
PC has been used as a diversifier for return address signing. The new directive
subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be
unsuitable for descibing some block layouts [1], particularly in hot-cold-split
functions.

1: ARM-software/abi-aa#346
jroelofs added a commit to jroelofs/llvm-project that referenced this pull request Jun 23, 2026
The new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE
DWARF pseudo-register for use when unwinding, to indicate whether the value of
PC has been used as a diversifier for return address signing. The new directive
subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be
unsuitable for descibing some block layouts [1], particularly in hot-cold-split
functions.

1: ARM-software/abi-aa#346
jroelofs added a commit to llvm/llvm-project that referenced this pull request Jun 24, 2026
…198677)

The toggle semantics of DW_CFA_AARCH64_negate_ra_state_with_pc are
evaluated over a linear stream of CFI opcodes, rather than along control
flow edges, making it impossible to faithfully represent the RA state
across all CFG paths for functions with non-trivial block layouts (for
example hot-cold-splitting, or doubly-shrinkwrapped functions with
multiple independent frames).

libunwind works around this by recording the signing address at the
FrameSetup site, and not validating that the CFI state has toggled back
to "unsigned" after authentication. We can therefore omit the
FrameDestroy emission, treating the marker solely as a marker for the
signing site. This holds so long as each function has at most one
signing location, which is currently guaranteed since shrinkwrapping
does not yet create functions with more than one frame.

DW_CFA_AARCH64_set_ra_state is the correct long-term fix, but cannot be
used exclusively due to unwinder compatability concerns.

See: ARM-software/abi-aa#327
     ARM-software/abi-aa#346

rdar://174074919
llvm-upstreamsync Bot pushed a commit to qualcomm/cpullvm-toolchain that referenced this pull request Jun 24, 2026
…_with_pc (#198677)

The toggle semantics of DW_CFA_AARCH64_negate_ra_state_with_pc are
evaluated over a linear stream of CFI opcodes, rather than along control
flow edges, making it impossible to faithfully represent the RA state
across all CFG paths for functions with non-trivial block layouts (for
example hot-cold-splitting, or doubly-shrinkwrapped functions with
multiple independent frames).

libunwind works around this by recording the signing address at the
FrameSetup site, and not validating that the CFI state has toggled back
to "unsigned" after authentication. We can therefore omit the
FrameDestroy emission, treating the marker solely as a marker for the
signing site. This holds so long as each function has at most one
signing location, which is currently guaranteed since shrinkwrapping
does not yet create functions with more than one frame.

DW_CFA_AARCH64_set_ra_state is the correct long-term fix, but cannot be
used exclusively due to unwinder compatability concerns.

See: ARM-software/abi-aa#327
     ARM-software/abi-aa#346

rdar://174074919
llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Jun 24, 2026
…_with_pc (#198677)

The toggle semantics of DW_CFA_AARCH64_negate_ra_state_with_pc are
evaluated over a linear stream of CFI opcodes, rather than along control
flow edges, making it impossible to faithfully represent the RA state
across all CFG paths for functions with non-trivial block layouts (for
example hot-cold-splitting, or doubly-shrinkwrapped functions with
multiple independent frames).

libunwind works around this by recording the signing address at the
FrameSetup site, and not validating that the CFI state has toggled back
to "unsigned" after authentication. We can therefore omit the
FrameDestroy emission, treating the marker solely as a marker for the
signing site. This holds so long as each function has at most one
signing location, which is currently guaranteed since shrinkwrapping
does not yet create functions with more than one frame.

DW_CFA_AARCH64_set_ra_state is the correct long-term fix, but cannot be
used exclusively due to unwinder compatability concerns.

See: ARM-software/abi-aa#327
     ARM-software/abi-aa#346

rdar://174074919
wenju-he pushed a commit to intel/llvm that referenced this pull request Jun 26, 2026
…198677)

The toggle semantics of DW_CFA_AARCH64_negate_ra_state_with_pc are
evaluated over a linear stream of CFI opcodes, rather than along control
flow edges, making it impossible to faithfully represent the RA state
across all CFG paths for functions with non-trivial block layouts (for
example hot-cold-splitting, or doubly-shrinkwrapped functions with
multiple independent frames).

libunwind works around this by recording the signing address at the
FrameSetup site, and not validating that the CFI state has toggled back
to "unsigned" after authentication. We can therefore omit the
FrameDestroy emission, treating the marker solely as a marker for the
signing site. This holds so long as each function has at most one
signing location, which is currently guaranteed since shrinkwrapping
does not yet create functions with more than one frame.

DW_CFA_AARCH64_set_ra_state is the correct long-term fix, but cannot be
used exclusively due to unwinder compatability concerns.

See: ARM-software/abi-aa#327
     ARM-software/abi-aa#346

rdar://174074919
maarcosrmz pushed a commit to maarcosrmz/llvm-project that referenced this pull request Jul 1, 2026
…lvm#198677)

The toggle semantics of DW_CFA_AARCH64_negate_ra_state_with_pc are
evaluated over a linear stream of CFI opcodes, rather than along control
flow edges, making it impossible to faithfully represent the RA state
across all CFG paths for functions with non-trivial block layouts (for
example hot-cold-splitting, or doubly-shrinkwrapped functions with
multiple independent frames).

libunwind works around this by recording the signing address at the
FrameSetup site, and not validating that the CFI state has toggled back
to "unsigned" after authentication. We can therefore omit the
FrameDestroy emission, treating the marker solely as a marker for the
signing site. This holds so long as each function has at most one
signing location, which is currently guaranteed since shrinkwrapping
does not yet create functions with more than one frame.

DW_CFA_AARCH64_set_ra_state is the correct long-term fix, but cannot be
used exclusively due to unwinder compatability concerns.

See: ARM-software/abi-aa#327
     ARM-software/abi-aa#346

rdar://174074919
jroelofs added a commit to llvm/llvm-project that referenced this pull request Jul 21, 2026
The new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.

1: ARM-software/abi-aa#346
llvm-upstreamsync Bot pushed a commit to qualcomm/cpullvm-toolchain that referenced this pull request Jul 21, 2026
The new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.

1: ARM-software/abi-aa#346
llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Jul 21, 2026
The new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.

1: ARM-software/abi-aa#346
jroelofs added a commit to llvm/llvm-project that referenced this pull request Jul 23, 2026
This new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.

1: ARM-software/abi-aa#346
llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Jul 23, 2026
This new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.

1: ARM-software/abi-aa#346
llvm-upstreamsync Bot pushed a commit to qualcomm/cpullvm-toolchain that referenced this pull request Jul 23, 2026
This new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.

1: ARM-software/abi-aa#346
midhuncodes7 pushed a commit to midhuncodes7/llvm-project that referenced this pull request Jul 28, 2026
The new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.

1: ARM-software/abi-aa#346
midhuncodes7 pushed a commit to midhuncodes7/llvm-project that referenced this pull request Jul 28, 2026
This new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.

1: ARM-software/abi-aa#346
asudarsa-qti pushed a commit to asudarsa-qti/llvm-project that referenced this pull request Jul 29, 2026
This new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.

1: ARM-software/abi-aa#346
nekoshirro pushed a commit to nekoshirro/Alchemist-LLVM that referenced this pull request Jul 30, 2026
This new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.

1: ARM-software/abi-aa#346
Signed-off-by: Hafidz Muzakky <ais.muzakky@gmail.com>
qiongsiwu pushed a commit to qiongsiwu/llvm-project that referenced this pull request Sep 26, 2026
The new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE
DWARF pseudo-register for use when unwinding, to indicate whether the value of
PC has been used as a diversifier for return address signing. The new directive
subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be
unsuitable for descibing some block layouts [1], particularly in hot-cold-split
functions.

1: ARM-software/abi-aa#346
(cherry picked from commit 3421dc2)
hukeyue pushed a commit to hukeyue/libunwind that referenced this pull request Oct 26, 2026
This new CFI directive directly assigns an RA signing state to the RA_SIGN_STATE DWARF pseudo-register for use when unwinding, to indicate whether the value of PC has been used as a diversifier for return address signing. The new directive subsumes and replaces .cfi_negate_ra_state_with_pc, which was found to be unsuitable for descibing some block layouts [1], particularly in hot-cold-split functions.

1: ARM-software/abi-aa#346
NOKEYCHECK=True
GitOrigin-RevId: 77e879f967294d76376bf7a022092a1d6f3ed583
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants