From patchwork Wed Oct 23 16:51:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guinevere Larsen X-Patchwork-Id: 99444 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 44D783858427 for ; Wed, 23 Oct 2024 16:52:33 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 27F373858D33 for ; Wed, 23 Oct 2024 16:51:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 27F373858D33 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 27F373858D33 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729702313; cv=none; b=uGWMfWZatu7qFM6Z87fNRfb50rAnnL+ka6YuNYTV7F3l2+JnsarqHpw1lPU7vDRFf7NNR/IMY9bBj0kIrI2TYitPU80FN+gmY/gJHbA8c3hXk3WUo87rXXfKqvMYoGVuiO3+33XdAZnDyhz8fecnJD2WeZpduS3nAKpRvlPJTek= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729702313; c=relaxed/simple; bh=nquUWJLmG+OJoWu9q1JcssTt87Iz+f+RJzSe4+ChGQk=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Nq3nwstIByHiXM5VEDco/tGXyK/ov8SUg3Kg7cnzIsMzHujwsvcATWyHLzVNzCdu4RA6MzXslA1LtQbefKLdJzz/ft9L7uCULnusdRCDIL0y1S+W8ll+0+YMSQQ6+9LG/ZQAMeIpdXBKXNNlHMDBalIuFSp3I7A8XqAyzY0qsKQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729702310; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=meJH/UniuB6bbDXXegeGV9Q3b7rOc0s5wrbP/Ko896k=; b=RKjzHNY6HAJTehzJkNsNSA4tG1nQFD+IFN7OJbNZs+aUdxxySW2dJ/539PAxQGc8lq0rQn HUvnI4J8Vu7u5FKaUDQ8coemc3kwt83zBV09eDxFS5FbQj7xGkiCrzi51uOYcoZbyYp4ao vP63KHy2hPUpg3Q43qNPJXHgUzcwiHY= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-438-PyeVxa8jOmKzjGsB-zILDQ-1; Wed, 23 Oct 2024 12:51:49 -0400 X-MC-Unique: PyeVxa8jOmKzjGsB-zILDQ-1 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A00F8197702B for ; Wed, 23 Oct 2024 16:51:48 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.96.134.67]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5815B300018D; Wed, 23 Oct 2024 16:51:47 +0000 (UTC) From: Guinevere Larsen To: gdb-patches@sourceware.org Cc: Guinevere Larsen Subject: [PATCH v5 2/7] gdb: Start supporting AVX instruction Date: Wed, 23 Oct 2024 13:51:12 -0300 Message-ID: <20241023165117.4051131-3-guinevere@redhat.com> In-Reply-To: <20241023165117.4051131-1-guinevere@redhat.com> References: <20241023165117.4051131-1-guinevere@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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 X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~patchwork=sourceware.org@sourceware.org This patch introduces the information needed to properly identify the VEX prefix, used to signal an AVX and AVX2 instruction, and introduces a helper function to handle all AVX instruction, instead of adding to the 3000 line long recording function. This new function will temporarily set the current thread as "not executing" so that it can read from pseudo registers as we record, since most AVX/AVX2 instructions would benefit from recording ymm registers. The new helper also handles unsupported instructions so that the largest part of the i386_process_record doesn't have to be shifted by 2 spaces, which made an unreadably big patch file. The only expected difference to the end user added by this patch is a small change to the unsupported message. This patch also updates the test gdb.reverse/step-precsave.exp, by recognizing the new output. As a note for the future, we don't handle xmm16-31 and ymm16-31 because those require the EVEX prefix, meaning avx512 support. --- gdb/amd64-tdep.c | 3 +- gdb/i386-tdep.c | 103 +++++++++++++++++++- gdb/i386-tdep.h | 1 + gdb/testsuite/gdb.reverse/step-precsave.exp | 2 +- 4 files changed, 105 insertions(+), 4 deletions(-) diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index b63e35d522a..c17b5f7f6f3 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -3122,7 +3122,8 @@ static const int amd64_record_regmap[] = AMD64_R8_REGNUM, AMD64_R9_REGNUM, AMD64_R10_REGNUM, AMD64_R11_REGNUM, AMD64_R12_REGNUM, AMD64_R13_REGNUM, AMD64_R14_REGNUM, AMD64_R15_REGNUM, AMD64_RIP_REGNUM, AMD64_EFLAGS_REGNUM, AMD64_CS_REGNUM, AMD64_SS_REGNUM, - AMD64_DS_REGNUM, AMD64_ES_REGNUM, AMD64_FS_REGNUM, AMD64_GS_REGNUM + AMD64_DS_REGNUM, AMD64_ES_REGNUM, AMD64_FS_REGNUM, AMD64_GS_REGNUM, + AMD64_XMM0_REGNUM }; /* Implement the "in_indirect_branch_thunk" gdbarch function. */ diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index d2c3efbc5af..0ff380728c1 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -4451,6 +4451,12 @@ struct i386_record_s int rip_offset; int popl_esp_hack; const int *regmap; + + /* These are used by VEX and XOP prefixes. */ + uint8_t map_select; + uint8_t vvvv; + uint8_t pp; + uint8_t l; }; /* Parse the "modrm" part of the memory address irp->addr points at. @@ -4789,6 +4795,43 @@ static int i386_record_floats (struct gdbarch *gdbarch, return 0; } +/* i386_process_record helper to deal with instructions that start + with VEX prefix. */ + +static int +i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r, + int opcode, struct gdbarch *gdbarch) +{ + /* We need this to find YMM (and once AVX-512 is supported, ZMM) registers. + We should always save the largest available register, since an + instruction that handles a smaller reg may zero out the higher bits, + so we must have them saved. */ + i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Since we are reading pseudo registers, we need to tell GDB that it is + safe to do so, by saying we aren't _really_ running the inferior right + now. */ + SCOPE_EXIT { inferior_thread ()->set_executing (true); }; + inferior_thread () -> set_executing (false); + + switch (opcode) + { + default: + gdb_printf (gdb_stderr, + _("Process record does not support VEX instruction 0x%02x " + "at address %s.\n"), + (unsigned int) (opcode), + paddress (gdbarch, ir->orig_addr)); + return -1; + } + + record_full_arch_list_add_reg (ir->regcache, ir->regmap[X86_RECORD_REIP_REGNUM]); + if (record_full_arch_list_add_end ()) + return -1; + + return 0; +} + /* Parse the current instruction, and record the values of the registers and memory that will be changed by the current instruction. Returns -1 if something goes wrong, 0 otherwise. */ @@ -4811,6 +4854,7 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache, i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); uint8_t rex_w = -1; uint8_t rex_r = 0; + bool vex_prefix = false; memset (&ir, 0, sizeof (struct i386_record_s)); ir.regcache = regcache; @@ -4896,6 +4940,53 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache, else /* 32 bit target */ goto out_prefixes; break; + case 0xc4: /* 3-byte VEX prefixes (for AVX/AVX2 instructions). */ + { + /* The first byte just identifies the VEX prefix. Data is stored + on the following 2 bytes. */ + uint8_t byte; + if (record_read_memory (gdbarch, ir.addr, &byte, 1)) + return -1; + ir.addr++; + + rex_r = !((byte >> 7) & 0x1); + ir.rex_x = !((byte >> 6) & 0x1); + ir.rex_b = !((byte >> 5) & 0x1); + ir.map_select = byte & 0x1f; + /* Collect the last byte of the prefix. */ + if (record_read_memory (gdbarch, ir.addr, &byte, 1)) + return -1; + ir.addr++; + rex_w = (byte >> 7) & 0x1; + ir.vvvv = (~(byte >> 3) & 0xf); + ir.l = (byte >> 2) & 0x1; + ir.pp = byte & 0x3; + vex_prefix = true; + + break; + } + case 0xc5: /* 2-byte VEX prefix for AVX/AVX2 instructions. */ + { + /* The first byte just identifies the VEX prefix. Data is stored + on the following 2 bytes. */ + uint8_t byte; + if (record_read_memory (gdbarch, ir.addr, &byte, 1)) + return -1; + ir.addr++; + + /* On the 2-byte versions, these are pre-defined. */ + ir.rex_x = 0; + ir.rex_b = 0; + rex_w = 0; + ir.map_select = 1; + + rex_r = !((byte >> 7) & 0x1); + ir.vvvv = (~(byte >> 3) & 0xf); + ir.l = (byte >> 2) & 0x1; + ir.pp = byte & 0x3; + vex_prefix = true; + break; + } default: goto out_prefixes; break; @@ -4918,6 +5009,12 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache, /* Now check op code. */ opcode = (uint32_t) opcode8; + if (vex_prefix) + { + /* If we found the VEX prefix, i386 will either record or warn that + the instruction isn't supported, so we can return the VEX result. */ + return i386_record_vex (&ir, rex_w, rex_r, opcode, gdbarch); + } reswitch: switch (opcode) { @@ -7902,9 +7999,11 @@ static const int i386_record_regmap[] = { I386_EAX_REGNUM, I386_ECX_REGNUM, I386_EDX_REGNUM, I386_EBX_REGNUM, I386_ESP_REGNUM, I386_EBP_REGNUM, I386_ESI_REGNUM, I386_EDI_REGNUM, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, I386_EIP_REGNUM, I386_EFLAGS_REGNUM, I386_CS_REGNUM, I386_SS_REGNUM, - I386_DS_REGNUM, I386_ES_REGNUM, I386_FS_REGNUM, I386_GS_REGNUM + I386_DS_REGNUM, I386_ES_REGNUM, I386_FS_REGNUM, I386_GS_REGNUM, + /* xmm0_regnum */ 0 }; /* Check that the given address appears suitable for a fast diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index 82676c24056..9df8611b553 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -325,6 +325,7 @@ enum record_i386_regnum X86_RECORD_ES_REGNUM, X86_RECORD_FS_REGNUM, X86_RECORD_GS_REGNUM, + X86_RECORD_XMM0_REGNUM, }; #define I386_NUM_GREGS 16 diff --git a/gdb/testsuite/gdb.reverse/step-precsave.exp b/gdb/testsuite/gdb.reverse/step-precsave.exp index a3979b7afd4..1dc42518ba7 100644 --- a/gdb/testsuite/gdb.reverse/step-precsave.exp +++ b/gdb/testsuite/gdb.reverse/step-precsave.exp @@ -46,7 +46,7 @@ with_timeout_factor 20 { -re -wrap "Breakpoint .* end of main .*" { pass $gdb_test_name } - -re -wrap "Process record does not support instruction 0xc5 at.*" { + -re -wrap "Process record does not support VEX instruction.*" { kfail "record/23188" $gdb_test_name } -re -wrap "Process record does not support instruction 0xfae64 at.*" {