Bug 26310 - [aarch64] Prologue analyzer considers user code part of prologue
Summary: [aarch64] Prologue analyzer considers user code part of prologue
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: tdep (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: ---
Assignee: Luis Machado
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-07-29 06:22 UTC by Tom de Vries
Modified: 2020-08-10 14:59 UTC (History)
2 users (show)

See Also:
Host: aarch64-linux-gnu
Target: aarch64-linux-gnu
Build: aarch64-linux-gnu
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tom de Vries 2020-07-29 06:22:48 UTC
[ Refiling of PR testsuite/26308 as tdep PR. ]

Test-case gdb.dwarf2/dw2-line-number-zero.exp has the following FAILs on aarch64:
...
FAIL: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar1
FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar1, 1st next
FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar1, 2nd next
FAIL: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar2
FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar2, 1st next
FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar2, 2nd next
...

The test-case has a function bar1:
...
    23  void
    24  bar1 (void)
    25  {
    26    asm ("bar1_label: .globl bar1_label");
    27    foo (1);
    28    asm ("bar1_label_2: .globl bar1_label_2");
    29    foo (2);
    30    asm ("bar1_label_3: .globl bar1_label_3");
    31    foo (3);
    32    asm ("bar1_label_4: .globl bar1_label_4");
    33    foo (4);
    34    asm ("bar1_label_5: .globl bar1_label_5");
    35  }
...

And the corresponding assembly code is:
...
Dump of assembler code for function bar1:
   0x00000000000006f8 <+0>:	stp	x29, x30, [sp, #-16]!
   0x00000000000006fc <+4>:	mov	x29, sp
   0x0000000000000700 <+8>:	mov	w0, #0x1                   	// #1
   0x0000000000000704 <+12>:	bl	0x6e4 <foo>
   0x0000000000000708 <+16>:	mov	w0, #0x2                   	// #2
...

A break on bar1 does not use 0x700 (the first insn after the prologue), but 0x708:
...
(gdb) break bar1
Breakpoint 2 at 0xaaaaaaaaa708: file dw2-line-number-zero.c, line 29.
...

As PR 26308 comment 8 states:
...
I think there is a hidden bug in the prologue analyzer for aarch64 and this testcase just happened to expose it given it uses movz. The current code assumes movz is part of the prologue, but it does not seem to be used that often (or at all) for that purpose.
...
Comment 1 Luis Machado 2020-07-29 11:01:00 UTC
aarch64's prologue analyzer considers movz part of the prologue. The problem is that there is no clearly defined boundary of the prologue. We can, however, use a better heuristic to determine when a movz is within the prologue.

I have a fix in test.
Comment 2 cvs-commit@gcc.gnu.org 2020-08-10 14:57:20 UTC
The master branch has been updated by Luis Machado <luisgpm@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f8e3fe0d2764e2976fec6a0ac48921893dc62bbf

commit f8e3fe0d2764e2976fec6a0ac48921893dc62bbf
Author: Luis Machado <luis.machado@linaro.org>
Date:   Mon Aug 10 11:56:19 2020 -0300

    [AArch64] Improve prologue handling (and fix PR26310)
    
    I initially noticed the problem with the addition of
    gdb.dwarf2/dw2-line-number-zero.exp.  The following failures showed up:
    
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar1
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar1, 1st next
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar1, 2nd next
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar2
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar2, 1st next
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar2, 2nd next
    
    They happen because AArch64's prologue analyzer skips too many instructions
    and ends up indicating a stopping point further into user code.
    
    Dump of assembler code for function bar1:
       0x00000000000006f8 <+0>:     stp     x29, x30, [sp, #-16]!
       0x00000000000006fc <+4>:     mov     x29, sp
       0x0000000000000700 <+8>:     mov     w0, #0x1                        // #1
       0x0000000000000704 <+12>:    bl      0x6e4 <foo>
       0x0000000000000708 <+16>:    mov     w0, #0x2                        // #2
    
    We should've stopped at 0x700, but the analyzer actually skips
    that instruction and stops at 0x704.  Then GDB ends up adjusting
    the address further, and pushes the stopping point to 0x708 based on the
    SAL information.
    
    I'm not sure if this adjustment to 0x708 is correct though, as it ends up
    skipping past a branch. But I'm leaving that aside for now.
    
    One other complicating factor is that GCC seems to be hoisting up instructions
    from user code, mixing them up with prologue instructions.
    
    The following patch adjusts the heuristics a little bit, and tracks when the
    SP and FP get used.  If we notice an instruction that is not supposed to be
    in the prologue, and this happens *after* SP/FP adjustments and saving of
    registers, we stop the analysis.
    
    This means, for PR26310, that we will now stop at 0x700.
    
    I've also added a few more unit tests to make sure the updated behavior is
    validated.
    
    gdb/ChangeLog:
    
    2020-08-10  Luis Machado  <luis.machado@linaro.org>
    
            PR gdb/26310
    
            * aarch64-tdep.c (aarch64_analyze_prologue): Track use of SP/FP and
            act accordingly.
            (aarch64_analyze_prologue_test): Add more unit tests to exercise
            movz/str/stur/stp skipping behavior.
Comment 3 Luis Machado 2020-08-10 14:59:13 UTC
Fixed with the pushed patch.