From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ej1-x631.google.com (mail-ej1-x631.google.com [IPv6:2a00:1450:4864:20::631]) by sourceware.org (Postfix) with ESMTPS id ED1813858C62 for ; Mon, 6 May 2024 09:30:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org ED1813858C62 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org ED1813858C62 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::631 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1714987805; cv=none; b=kFWKqWhlWC6h5nYGgID8f+G5v6vufF8JZtFh2u+JNr/hN0UI0kpu2fvR9Zk5rTcCyVhwgDp3Vo7/PcbHtZu6zvj/tByVu9LkC2Xyj+cmP+3eUgtMYpb/dRjd4dIMkOTCUGsnycn89MtKP+AMIzYeM0Kxl8IMydNAN+taVgKiij4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1714987805; c=relaxed/simple; bh=lyzOfsHweR1WOnzMJGCpErq4i6HhRquM3OVGbMSTqsQ=; h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To; b=XpM3KLG0mY/IiYrGFbqbtq3PNZjHI6JiZxu/7mhUw7wFsJexhEVpWRIPpDPLVPKhwl7jT/AhKLGzwTHjHSnEqDSRMCUpN8HFbr0k4X1GupcU7m3O785zlWBrirwPn2xSL5XHPB++Utf6RvihFCnOaQa6KEQcUiUqQjn3bAUmsus= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-ej1-x631.google.com with SMTP id a640c23a62f3a-a599c55055dso386073266b.0 for ; Mon, 06 May 2024 02:30:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1714987801; x=1715592601; darn=sourceware.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=Vp2s29bV2UIlH0WHowzZIEbkxXZsht649ipSq44AtG8=; b=J3br3vks6Tp6EZJp6IVeOHZT5H0vusMf10WYYz8ke+wgBbXVLgzbsc95QXNmIWRrYt OHDIjJ2Cc3OMYQIvk0QMiGBMd7dw+cBnTdwXpPHXPHZDSRdpJgWMFe6kYvBr8iATeZep 8TZyDN97olQSNchx5UI7aoVMzqYEFy3uFJcUoBgT/rWvrDKeiFxdGGKADGjQaZf1ziSx ZKPpBU258PuEjHKpULakxjhNnhcYCJxg5mBnzhmuXa8EPmMfdDYLDzonHrq36HiAKDcs /HR6lvf5jtOHaQuM6TYERSpr2KJElPnJTfA0W4d0PvSD+J2RahayjlUwK8B1oqHki0A6 zLoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714987801; x=1715592601; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Vp2s29bV2UIlH0WHowzZIEbkxXZsht649ipSq44AtG8=; b=Qcw5+jJD0oOxjmskW+Jd7I6kKaSkoyab1c5tbriDN6ucTvKCOF8LOyqjWKVwjPrGO/ BKJPJnytkugFLI7WZR43PoQJxUA9JhCumDxEZ3p78t6ZmpSHMcwOQD4ST9NGOBdfqM1r u0DoBAY1RMPAEWZMJlH3V2hpbNIJ2cfmS6TYGK6wuB1RwNeCEbEEDnDUm1gKAvuHmPwY l2tJW9TgS1VHmBZ/YHJt9ouhhJUCmobmppR0grSqGbUqkSe+Ef4Cjpf2LGi7PMiF8h0X 7uT+0k/jwBAeaYf4F2oIavxxtV2sCQJA3HJkAJjy1pNJQCaG4UMvYI1x7HvQ7wFxHuJK XNZw== X-Gm-Message-State: AOJu0YxdbSVEPZGjDev+DPlZZew7wffQoUw5DsIbtKnewu1O0PMXKrCg XIbMSgHFJiSmgoHugP1AanUZSy2FGhP5Dy27crW1yP4gTIVjl+VFKok7QYYVqzH4qC7xvImdddo czrjK2oM82ykkLD92JuI7LdU3x09juB4A7GATkit7yqWLSCyblQs= X-Google-Smtp-Source: AGHT+IHrmOhMpoEiu96he75n2D8ks7dF/xh9+5U3m1FXtQ7oJt4eOy/k+d2OqcjjlogvI1y6h8XDWYT7dihda31TW8I= X-Received: by 2002:a17:907:e86:b0:a59:ca7e:e1f with SMTP id ho6-20020a1709070e8600b00a59ca7e0e1fmr2215159ejc.15.1714987801471; Mon, 06 May 2024 02:30:01 -0700 (PDT) MIME-Version: 1.0 References: <20240504000521.314531-1-thiago.bauermann@linaro.org> <20240504000521.314531-2-thiago.bauermann@linaro.org> In-Reply-To: <20240504000521.314531-2-thiago.bauermann@linaro.org> From: Christophe Lyon Date: Mon, 6 May 2024 11:29:50 +0200 Message-ID: Subject: Re: [PATCH 1/5] gdb/aarch64: Implement software single stepping for MOPS instructions To: Thiago Jung Bauermann Cc: gdb-patches@sourceware.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-10.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Sat, 4 May 2024 at 02:05, Thiago Jung Bauermann wrote: > > The AArch64 MOPS (Memory Operation) instructions provide a standardised > instruction sequence to perform a memset, memcpy or memmove. A sequence is > always composed of three instructions: a prologue instruction, a main > instruction and an epilogue instruction. As an illustration, here are the > implementations of these memory operations in glibc 2.39: > > (gdb) disassemble/r > Dump of assembler code for function __memset_mops: > => 0x0000fffff7e8d780 <+0>: d503201f nop > 0x0000fffff7e8d784 <+4>: aa0003e3 mov x3, x0 > 0x0000fffff7e8d788 <+8>: 19c10443 setp [x3]!, x2!, x1 > 0x0000fffff7e8d78c <+12>: 19c14443 setm [x3]!, x2!, x1 > 0x0000fffff7e8d790 <+16>: 19c18443 sete [x3]!, x2!, x1 > 0x0000fffff7e8d794 <+20>: d65f03c0 ret > End of assembler dump. > > (gdb) disassemble/r > Dump of assembler code for function __memcpy_mops: > => 0x0000fffff7e8c580 <+0>: d503201f nop > 0x0000fffff7e8c584 <+4>: aa0003e3 mov x3, x0 > 0x0000fffff7e8c588 <+8>: 19010443 cpyfp [x3]!, [x1]!, x2! > 0x0000fffff7e8c58c <+12>: 19410443 cpyfm [x3]!, [x1]!, x2! > 0x0000fffff7e8c590 <+16>: 19810443 cpyfe [x3]!, [x1]!, x2! > 0x0000fffff7e8c594 <+20>: d65f03c0 ret > End of assembler dump. > > (gdb) disassemble/r > Dump of assembler code for function __memmove_mops: > => 0x0000fffff7e8d180 <+0>: d503201f nop > 0x0000fffff7e8d184 <+4>: aa0003e3 mov x3, x0 > 0x0000fffff7e8d188 <+8>: 1d010443 cpyp [x3]!, [x1]!, x2! > 0x0000fffff7e8d18c <+12>: 1d410443 cpym [x3]!, [x1]!, x2! > 0x0000fffff7e8d190 <+16>: 1d810443 cpye [x3]!, [x1]!, x2! > 0x0000fffff7e8d194 <+20>: d65f03c0 ret > End of assembler dump. > > The Arm Architecture Reference Manual says that "the prologue, main, and > epilogue instructions are expected to be run in succession and to appear > consecutively in memory". Therefore GDB needs to treat them as an atomic > instruction sequence, and also can't do displaced stepping with them. > > This patch implements support for executing the sequence atomically, and > also disables displaced step on them. > > PR tdep/31666 > Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31666 > --- > gdb/aarch64-tdep.c | 107 ++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 105 insertions(+), 2 deletions(-) > > diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c > index 8d0553f3d7cd..e920cea49066 100644 > --- a/gdb/aarch64-tdep.c > +++ b/gdb/aarch64-tdep.c > @@ -3444,6 +3444,104 @@ value_of_aarch64_user_reg (const frame_info_ptr &frame, const void *baton) > return value_of_register (*reg_p, get_next_frame_sentinel_okay (frame)); > } > > +/* Single step through MOPS instruction sequences on AArch64. */ > + > +static std::vector > +aarch64_software_single_step_mops (struct regcache *regcache, CORE_ADDR loc, > + uint32_t insn) > +{ > + const int insn_size = 4; > + struct gdbarch *gdbarch = regcache->arch (); > + enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch); > + uint8_t o0 = bit (insn, 21); > + uint8_t op1 = bits (insn, 22, 23); > + uint8_t op2 = bits (insn, 12, 15); > + > + /* Look for the prologue instruction that begins the sequence. */ > + > + /* CPYFP* */ > + if (!((o0 == 0 && op1 == 0) > + /* SETP* */ > + || (o0 == 0 && op1 == 3 && op2 < 4) > + /* CPYP* */ > + || (o0 == 1 && op1 == 0) > + /* SETGP* */ > + || (o0 == 1 && op1 == 3 && op2 < 4))) > + /* Prologue instruction not found. */ > + return {}; > + > + /* Now look for the main instruction in the middle of the sequence. */ > + > + loc += insn_size; > + ULONGEST insn_from_memory; > + if (!safe_read_memory_unsigned_integer (loc, insn_size, > + byte_order_for_code, > + &insn_from_memory)) > + { > + /* Assume we don't have a MOPS sequence, as we couldn't read the > + instruction in this location. */ > + return {}; > + } > + > + insn = insn_from_memory; > + aarch64_inst inst; > + if (aarch64_decode_insn (insn, &inst, 1, nullptr) != 0) > + return {}; > + if (!AARCH64_CPU_HAS_FEATURE (*inst.opcode->avariant, MOPS)) > + return {}; > + > + o0 = bit (insn, 21); > + op1 = bits (insn, 22, 23); > + op2 = bits (insn, 12, 15); > + > + /* CPYFM* */ > + if (!((o0 == 0 && op1 == 1) > + /* SETM* */ > + || (o0 == 0 && op1 == 3 && op2 >= 4 && op2 < 8) > + /* CPYM* */ > + || (o0 == 1 && op1 == 1) > + /* SETGM* */ > + || (o0 == 1 && op1 == 3 && op2 >= 4 && op2 < 8))) > + /* Main instruction not found. */ > + return {}; > + > + /* Now look for the epilogue instruction that ends the sequence. */ > + > + loc += insn_size; > + if (!safe_read_memory_unsigned_integer (loc, insn_size, > + byte_order_for_code, > + &insn_from_memory)) > + { > + /* Assume we don't have a MOPS sequence, as we couldn't read the > + instruction in this location. */ > + return {}; > + } > + > + insn = insn_from_memory; > + if (aarch64_decode_insn (insn, &inst, 1, nullptr) != 0) > + return {}; > + if (!AARCH64_CPU_HAS_FEATURE (*inst.opcode->avariant, MOPS)) > + return {}; > + > + o0 = bit (insn, 21); > + op1 = bits (insn, 22, 23); > + op2 = bits (insn, 12, 15); > + > + /* CPYFE* */ > + if (!((o0 == 0 && op1 == 2) > + /* SETE* (op2 >= 12 is unallocated space) */ > + || (o0 == 0 && op1 == 3 && op2 >= 8 && op2 < 12) > + /* CPYE* */ > + || (o0 == 1 && op1 == 2) > + /* SETGE* (op2 >= 12 is unallocated space) */ > + || (o0 == 1 && op1 == 3 && op2 >= 8 && op2 < 12))) > + /* Epilogue instruction not found. */ > + return {}; > + > + /* Insert breakpoint after the end of the atomic sequence. */ > + return { loc + insn_size }; > +} > + > /* Implement the "software_single_step" gdbarch method, needed to > single step through atomic sequences on AArch64. */ > > @@ -3479,6 +3577,9 @@ aarch64_software_single_step (struct regcache *regcache) > if (aarch64_decode_insn (insn, &inst, 1, NULL) != 0) > return {}; > > + if (AARCH64_CPU_HAS_FEATURE (*inst.opcode->avariant, MOPS)) > + return aarch64_software_single_step_mops (regcache, loc, insn); > + > /* Look for a Load Exclusive instruction which begins the sequence. */ > if (inst.opcode->iclass != ldstexcl || bit (insn, 22) == 0) > return {}; > @@ -3808,8 +3909,10 @@ aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch, > if (aarch64_decode_insn (insn, &inst, 1, NULL) != 0) > return NULL; > > - /* Look for a Load Exclusive instruction which begins the sequence. */ > - if (inst.opcode->iclass == ldstexcl && bit (insn, 22)) > + /* Look for a Load Exclusive instruction which begins the sequence, > + or for a MOPS instruction. */ > + if ((inst.opcode->iclass == ldstexcl && bit (insn, 22)) > + || AARCH64_CPU_HAS_FEATURE (*inst.opcode->avariant, MOPS)) Sorry for the naive question: doesn't this check that the CPU supports MOPS, rather than the instruction sequence is a MOPS one? Thanks, Christophe > { > /* We can't displaced step atomic sequences. */ > return NULL;