Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Incorrect unwind tables when saving high register on Thumb1 target #41376

Closed Quuxplusone closed 5 years ago

Quuxplusone commented 5 years ago
Bugzilla Link PR42408
Status RESOLVED FIXED
Importance P enhancement
Reported by Oliver Stannard (oliver.stannard@arm.com)
Reported on 2019-06-26 06:30:26 -0700
Last modified on 2019-07-02 14:35:30 -0700
Version trunk
Hardware PC Linux
CC efriedma@quicinc.com, llvm-bugs@lists.llvm.org, smithp352@googlemail.com, Ties.Stuij@arm.com
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
For Thumb1-only targets (e.g. Armv6M) we emit incorrect unwind tables when
saving high registers (which aren't normally allocatable, but can be usind in
inline assembly):

  // test.cpp
  extern void foo();
  void bar() {
    asm("" : : : "r8");
    foo();
  }

  $ clang   --target=arm-arm-none-eabi -march=armv6-m -c test.cpp -Os -o - -S
  ...
 _Z3barv:
         .fnstart
  @ %bb.0:                                @ %entry
         .save   {lr}
         push    {lr}
         mov     lr, r8
         push    {lr}
         @APP
         @NO_APP
         bl      _Z3foov
         pop     {r0}
         mov     r8, r0
         pop     {pc}
   .Lfunc_end0:
         .size   _Z3barv, .Lfunc_end0-_Z3barv
         .fnend
  ...

This means that debuggers and the C++ exception unwinder won't be able to
unwind through functions like this.
Quuxplusone commented 5 years ago

I'll probably look into this; I've been looking at this code anyway.

Quuxplusone commented 5 years ago

More complicated than I'd hoped for.

If you use -fdwarf-exceptions, we correctly emit ".cfi_offset r8, -16". (I guess this was implemented for the sake of Thumb2 on iOS, but the stack layout is the same as Thumb1, so it just works.) But ARM exception data uses a completely different mechanism to pass the unwind information to the assembler.

There are two issues here: one, we aren't marking some of the relevant instructions as "FrameSetup", and two, ARMAsmPrinter::EmitUnwindingInstruction isn't expecting the "mov lr, r8; push {lr}" sequence.

EmitUnwindingInstruction is so messy at this point, it might be easier to just rewrite the whole mechanism from scratch: prologue emission should emit an appropriate pseudo-instructions, rather than making the asmprinter try to reverse-engineer the unwind information.

Quuxplusone commented 5 years ago

https://reviews.llvm.org/D63964

Quuxplusone commented 5 years ago

r364970