This is an archive of the discontinued LLVM Phabricator instance.

[AArch64] fix bug #55005 handle DW_CFA_GNU_window_save
ClosedPublic

Authored by sebpop on Jan 25 2023, 11:35 AM.

Details

Summary

GCC on AArch64 uses DW_CFA_GNU_window_save for return address signing.

In architecture revisions prior to ARMv8.3-A the pointer authentication
HINT instructions operate as NOPs.

Diff Detail

Event Timeline

Amir created this revision.Jan 25 2023, 11:35 AM
Herald added a reviewer: maksfb. · View Herald Transcript
Herald added a project: Restricted Project. · View Herald Transcript
Amir requested review of this revision.Jan 25 2023, 11:35 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 25 2023, 11:35 AM
danielkiss added inline comments.
bolt/lib/Core/Exceptions.cpp
630

on AArch64 I'd call the createNegateRAState. DW_CFA_GNU_window_save and DW_CFA_GNU_NegateRAState just use the same id but mean different things.

Amir added a subscriber: sebpop.Jan 25 2023, 11:46 AM
sebpop commandeered this revision.Jan 25 2023, 12:00 PM
sebpop updated this revision to Diff 492216.
sebpop added a reviewer: Amir.
sebpop retitled this revision from [AArch64] fix bug #55005 to [AArch64] fix bug #55005 handle DW_CFA_GNU_window_save.
sebpop marked an inline comment as done.Jan 25 2023, 12:03 PM
sebpop updated this revision to Diff 492467.Jan 26 2023, 8:49 AM

I added a testcase, however I was not able to check if the test catches the issue.

I need some help on how to run the bolt tests.
I did a make check-all in a build with -DLLVM_ENABLE_PROJECTS="clang;bolt" however that did not include the test that I added, as it is supposed to fail without the current patch.
I also tried to run the test directly with lit, and that failed as well.
Could somebody point me to the docs that describe how to run the bolt tests?

Thank you.

yota9 added a comment.Jan 26 2023, 8:52 AM

Please try make check-bolt. Although test seems to be too easy, I doubt that it could check the problem..

Recommended check-bolt fails with:

$ make check-bolt
make: *** No rule to make target 'check-bolt'.  Stop.

If I execute the following sequence before the patch, the test will fail (also as described in the bug report https://github.com/llvm/llvm-project/issues/55005 )

$ clang -O2 -Wl,-q -o a.out dw_cfa_gnu_window_save.cc
$ llvm-bolt a.out -o a.bolt
BOLT-INFO: Target architecture: aarch64
BOLT-INFO: BOLT version: 5de6b94f856f696832ce7df167e1dbc096fbe598
BOLT-INFO: first alloc address is 0x400000
BOLT-INFO: creating new program header table at address 0x600000, offset 0x200000
BOLT-INFO: enabling relocation mode
BOLT-INFO: disabling -align-macro-fusion on non-x86 platform
=======================================
BOLT is unable to proceed because it couldn't properly understand this function.
If you are running the most recent version of BOLT, you may want to report this and paste this dump.
Please check that there is no sensitive contents being shared in this dump.

Offending function: __do_global_dtors_aux/1(*2)

Function contents (
  0000: 3F2303D5 FD7BBEA9 FD030091 F30B00F9  |?#...{..........|
  0010: 93010090 60824039 80000035 DEFFFF97  |....`.@9...5....|
  0020: 20008052 60820039 F30B40F9 FD7BC2A8  | ..R`..9..@..{..|
  0030: BF2303D5 C0035FD6                    |.#...._.|
)

Binary Function "__do_global_dtors_aux/1(*2)"  {
  All names   : __do_global_dtors_aux/1
                __do_global_dtors_aux/crtstuff.c/1
  Number      : 8
  State       : disassembled
  Address     : 0x41014c
  Size        : 0x38
  MaxSize     : 0x38
  Offset      : 0x1014c
  Section     : .text
  Orc Section : .local.text.__do_global_dtors_aux/1
  LSDA        : 0x0
  IsSimple    : 1
  IsMultiEntry: 0
  IsSplit     : 0
  BB Count    : 0
}
.LBB07:
    00000000: 	paciasp
    00000004: 	stp	x29, x30, [sp, #-0x20]!
    00000008: 	mov	x29, sp
    0000000c: 	str	x19, [sp, #0x10]
    00000010: 	adrp	x19, "__TMC_LIST__/1"
    00000014: 	ldrb	w0, [x19, :lo12:"__TMC_LIST__/1"]
    00000018: 	cbnz	w0, .Ltmp4 # Offset: 24
    0000001c: 	bl	"deregister_tm_clones/1" # Offset: 28
    00000020: 	mov	w0, #0x1
    00000024: 	strb	w0, [x19, :lo12:"__TMC_LIST__/1"]
.Ltmp4:
    00000028: 	ldr	x19, [sp, #0x10]
    0000002c: 	ldp	x29, x30, [sp], #0x20
    00000030: 	autiasp
    00000034: 	ret	x30 # Offset: 52
DWARF CFI Instructions:
    <empty>
End of Function "__do_global_dtors_aux/1(*2)"

ERROR: unable to fill CFI.
=======================================
yota9 added a comment.Jan 26 2023, 9:18 AM

I'm not sure why check-bolt doesn't work for you, it works fine for me..
Plus we've got more complicated tests than this one, probably it is something in env causes the problem. I don't say that there is no problem, but I would say that probably we need another test or maybe pre-built binary in yaml format, we have some tests like that. Also be aware that %cflags contains nostdlib, so no startup files (that seems to have a problem) would be linked in...

Amir added a comment.Jan 26 2023, 10:40 AM

I added a testcase, however I was not able to check if the test catches the issue.

I need some help on how to run the bolt tests.
I did a make check-all in a build with -DLLVM_ENABLE_PROJECTS="clang;bolt" however that did not include the test that I added, as it is supposed to fail without the current patch.
I also tried to run the test directly with lit, and that failed as well.
Could somebody point me to the docs that describe how to run the bolt tests?

Thank you.

Please also enable lld project.

sebpop updated this revision to Diff 492954.Jan 27 2023, 5:12 PM

Added testcase that passes with the patch.
Tested on arm64-linux (Graviton3 Neoverse-V1.)

Thanks Amir for the tip, configuring with -DLLVM_ENABLE_PROJECTS="clang;bolt;lld" enabled check-bolt target.
Thanks yota9 for pointing out the format for the test "pre-built binary in yaml format", I adapted my test following one of your previous tests.

rafauler added inline comments.Jan 30 2023, 10:54 AM
bolt/lib/Core/Exceptions.cpp
629

Can you add a comment here explaining why you're calling createNegateRAState? Something like

"DW_CFA_GNU_window_save and DW_CFA_GNU_NegateRAState just use the same id but mean different things. The latter is used in AArch64".

Also, guard this code under AArch64 (from what I understand, this is an AArch64-only thing)

if (Function.getBinaryContext().isAArch64)
bolt/test/AArch64/dw_cfa_gnu_window_save.cc
1 ↗(On Diff #492954)

I guess we can drop this test? Since you already added the yaml file and another test

sebpop updated this revision to Diff 493828.Jan 31 2023, 10:47 PM
yota9 added a comment.Feb 1 2023, 8:39 AM

Overall LGTM, although usually we have a policy to minimise yaml tests as much as we can, removing unneeded for the tests sections, symbols, data & etc.

sebpop updated this revision to Diff 494357.Feb 2 2023, 10:22 AM
sebpop marked an inline comment as done.

Reduced yaml input file.
Tested with and without the patch for the pattern.

ayermolo added inline comments.Feb 2 2023, 10:25 AM
bolt/lib/Core/Exceptions.cpp
636

small nit. I don't think {} is necessary here according to coding style guide.

sebpop updated this revision to Diff 494391.Feb 2 2023, 11:48 AM
sebpop marked an inline comment as done.
yota9 accepted this revision as: yota9.Feb 2 2023, 11:49 AM

LGTM

This revision is now accepted and ready to land.Feb 2 2023, 11:49 AM