Re: aarch64-tdep.c:379: internal-error: CORE_ADDR aarch64_analyze_prologue(gdbarch*, CORE_ADDR, CORE_ADDR, aarch64_prologue_cache*, {anonymous}::abstract_instruction_reader&): Assertion `inst.operands[0].qualifier == AARCH64_OPND_QLF_S_D' failed

Simon Marchi <[email protected]>
Newsgroups gmane.comp.gdb.devel
Message-ID <[email protected]>
On 2018-04-02 05:13, Dmitry Antipov wrote:
> IIUC a few types of STP and STR instructions are explicitly banned in
> aarch64_analyze_prologue():
> 
> f:
>         stp     x29, x30, [sp, #-160]!
>         mov     x29, sp
>         stp     q0, q1, [sp, #-16]!     ; Hmm...
>         ldp     x29, x30, [sp], #160
>         ret
> .end
> 
> The following dummy self-test...
> 
> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index f08945ea07..42f9d00b64 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -529,6 +529,22 @@ aarch64_analyze_prologue_test (void)
>    struct gdbarch *gdbarch = gdbarch_find_by_info (info);
>    SELF_CHECK (gdbarch != NULL);
> 
> +  {
> +    struct aarch64_prologue_cache cache;
> +    cache.saved_regs = trad_frame_alloc_saved_regs (gdbarch);
> +
> +    static const uint32_t insns[] = {
> +      0xa9b67bfd, /* stp       x29, x30, [sp, #-160]! */
> +      0x910003fd, /* mov       x29, sp */
> +      0xadbf87e0, /* stp       q0, q1, [sp, #-16]! */
> +      0xa8ca7bfd, /* ldp       x29, x30, [sp], #160 */
> +      0xd65f03c0  /* ret */
> +    };
> +
> +    instruction_reader_test reader (insns);
> +    (void)aarch64_analyze_prologue (gdbarch, 0, 128, &cache, reader);
> +  }
> +
> 
> ...raises gdb_assert():
> 
> (gdb) maintenance selftest
> Running selftest aarch64-analyze-prologue.
> ../../gdb/aarch64-tdep.c:379: internal-error: CORE_ADDR
> aarch64_analyze_prologue(gdbarch*, CORE_ADDR, CORE_ADDR,
> aarch64_prologue_cache*, {anonymous}::abstract_instruction_reader&):
> Assertion `inst.operands[0].qualifier == AARCH64_OPND_QLF_S_D' failed.
> 
> Can someone please explain why it is so?
> 
> Dmitry

Hi Dmitry,

My guess is that it follows this sentence from the AArch64 ABI [1]:

Registers v8-v15 must be preserved by a callee across subroutine calls; 
the remaining registers (v0-v7, v16-v31)do not need to be preserved (or 
should be preserved by the caller).  Additionally, only the bottom 
64-bits of each value stored in v8-v15 need to be preserved. The FPSR is 
a status register that holds the cumulative exception bits of the 
floating-point unit.  It contains the fields IDC, IXC, UFC, OFC, DZC, 
IOC and QC.  These fields are not preserved across a public interface 
and may have any value on entry to a subroutine.; it is the 
responsibility of the caller to preserve larger values

So it looks like the GDB code assumes that no-one would ever save the 
whole registers, because it is not necessary.  GDB should not use 
gdb_assert and crash on bad input.  I don't know what it should do 
instead in that specific case, that's the part that takes more time to 
think about :).

Simon

[1] 
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.