Skip to content

builtin trap placed after frame pop on Arm 32-bit #113154

Closed
@DavidSpickett

Description

@DavidSpickett

Since #109628, we have had an lldb test failure on 32 bit Arm:
https://lab.llvm.org/buildbot/#/builders/18/builds/5545

# CHECK: frame #{{.*}}`g() at verbose_trap-in-stl.cpp
         ^
<stdin>:11:88: note: scanning from here
* thread #1, name = 'verbose_trap-in', stop reason = Bounds error: out-of-bounds access
                                                                                       ^
<stdin>:12:44: note: possible intended match here
 frame #2: 0x00410694 verbose_trap-in-stl.test.tmp.out`main at verbose_trap-in-stl.cpp:15:3
                                           ^
Input file: <stdin>
Check file: /home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/Shell/Recognizer/verbose_trap-in-stl.test

-dump-input=help explains the following input dump.

This test checks that lldb can show the first frame of user written code when there's an error in the STL. So in this case we expect to see g() in the backtrace, rather than the operator[], or main as we now get.

This appears to be because the trap instruction generated by __builtin_trap is put after the frame information is reset:

(lldb) dis
verbose_trap-in-stl.test.tmp.out`std::__1::vector<int>::operator[]:
    0x400558 <+0>:  push   {r11, lr}
    0x40055c <+4>:  mov    r11, sp
    0x400560 <+8>:  sub    sp, sp, #8
    0x400564 <+12>: str    r0, [sp, #0x4]
    0x400568 <+16>: str    r1, [sp]
    0x40056c <+20>: mov    sp, r11
    0x400570 <+24>: pop    {r11, lr}
->  0x400574 <+28>: trap
    0x400578 <+32>: bx     lr

I can show this with another example: https://godbolt.org/z/jnGWh1Wqh

void fn() {
    __builtin_trap();
}

Produces:

fn():
  push {r11, lr}
  mov r11, sp
  pop {r11, lr}
  .inst 0xe7ffdefe
  bx lr

fn has the trap after the frame pointer and link register is reset. This is not the case on RISC-V:

fn():
  addi sp, sp, -16
  sw ra, 12(sp)
  sw s0, 8(sp)
  addi s0, sp, 16
  unimp                          <<<<<<<<< trap is here
  lw ra, 12(sp)
  lw s0, 8(sp)
  addi sp, sp, 16
  ret

And I think changing the frame information before the trap is misleading because a debugger will see a PC within fn but the unwind information will look as if it is already in the caller of fn.

I don't know right now whether the linked change has caused the problem or merely exposed the problem by changing how leaf functions are handled.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions