From patchwork Mon Jul 10 13:55:21 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 21499 Received: (qmail 28381 invoked by alias); 10 Jul 2017 13:56:00 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 27878 invoked by uid 89); 10 Jul 2017 13:55:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.4 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy=negatives X-HELO: mail-it0-f51.google.com Received: from mail-it0-f51.google.com (HELO mail-it0-f51.google.com) (209.85.214.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 10 Jul 2017 13:55:55 +0000 Received: by mail-it0-f51.google.com with SMTP id 188so10620127itx.0 for ; Mon, 10 Jul 2017 06:55:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=Hg4ufk8UJ2cBec+E6Pk7y7DJAtINLz5ukxOhw5NPGgY=; b=aiG4KGJP1ICTy4lx6a/isWpBtRpqUiFR37ckI9jc07IF2Vdpn13XaqYt/H6Dc/eMdg SWH5pIyq2zd8+4jCNv/wbz6g8MOKIJyIp07ui3UYyLl+evBPJgkbB7yG31pQHxDKGBB9 rqDCgHG2KRnv1NSv0mBzQq1FU1QxHgG6U84j5vkDQDNYx6Yn/lDHQcTCZEaQnqjWrBAw JYkO1Csesf8BN72gkCmJOZdP1dysSxVwmIswqSna2P1er3J6QayKTr/HHhv8IntGRToG fLnRuNnt100s/X6PagkTH7vIDA218hXsSbq/3zKCqF/uZpJSNIjpOmYk2+2caneF4YMn HtVg== X-Gm-Message-State: AIVw112AKlxSqz9sH4EDuIJ2l4UnCbXQz2rVAIN8iu9h/yZw5vh6mfRj F3PHpZfKkU5n5mZw X-Received: by 10.36.23.134 with SMTP id 128mr11079785ith.68.1499694952736; Mon, 10 Jul 2017 06:55:52 -0700 (PDT) Received: from E107787-LIN.cambridge.arm.com (static.42.136.251.148.clients.your-server.de. [148.251.136.42]) by smtp.gmail.com with ESMTPSA id v96sm5973996ioi.50.2017.07.10.06.55.51 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 10 Jul 2017 06:55:51 -0700 (PDT) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH 07/26] Lazily and dynamically create i386-linux target descriptions Date: Mon, 10 Jul 2017 14:55:21 +0100 Message-Id: <1499694940-23564-8-git-send-email-yao.qi@linaro.org> In-Reply-To: <1499694940-23564-1-git-send-email-yao.qi@linaro.org> References: <1499694940-23564-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes Instead of using pre-generated target descriptions, this patch changes GDB to lazily and dynamically create target descriptions according to the target hardware capability (xcr0 in i386). This support any combination of target features. Some reg in target description has "regnum" attribute, so its register number is got from the attribute value instead from sequential allocation. when target description is created, it should match the regnum, so this patch adds a new field m_next_regnum to track it, if attribute number is greater than the m_next_regnum, print the code to set register number explicitly. v3: - Add sanity check, use error rather than gdb_assert, because it checks GDB input (The invalid input shouldn't trigger gdb internal error). - Add comments, gdb: 2017-07-07 Yao Qi * i386-linux-tdep.c: Don't include features/i386/i386-*linux.c. Include features/i386/32bit-*.c. (i386_linux_read_description): Generate target description if it doesn't exist. (_initialize_i386_linux_tdep): Don't call _initialize_tdesc_i386 functions. * features/i386/32bit-linux.c: Re-generated. * features/i386/32bit-sse.c: Likewise. * target-descriptions.c (print_c_feature::visit): Print code to set register number if needed. (print_c_feature) : New field. --- gdb/features/i386/32bit-linux.c | 1 + gdb/features/i386/32bit-sse.c | 1 + gdb/i386-linux-tdep.c | 83 ++++++++++++++++++++++++----------------- gdb/target-descriptions.c | 47 +++++++++++++++++++++++ 4 files changed, 98 insertions(+), 34 deletions(-) diff --git a/gdb/features/i386/32bit-linux.c b/gdb/features/i386/32bit-linux.c index 686a2f1..1b50882 100644 --- a/gdb/features/i386/32bit-linux.c +++ b/gdb/features/i386/32bit-linux.c @@ -9,6 +9,7 @@ create_feature_i386_32bit_linux (struct target_desc *result, long regnum) struct tdesc_feature *feature; feature = tdesc_create_feature (result, "org.gnu.gdb.i386.linux"); + regnum = 41; tdesc_create_reg (feature, "orig_eax", regnum++, 1, NULL, 32, "int"); return regnum; } diff --git a/gdb/features/i386/32bit-sse.c b/gdb/features/i386/32bit-sse.c index 032623e..c0684fb 100644 --- a/gdb/features/i386/32bit-sse.c +++ b/gdb/features/i386/32bit-sse.c @@ -61,6 +61,7 @@ create_feature_i386_32bit_sse (struct target_desc *result, long regnum) tdesc_add_flag (type, 12, "PM"); tdesc_add_flag (type, 15, "FZ"); + regnum = 32; tdesc_create_reg (feature, "xmm0", regnum++, 1, NULL, 128, "vec128"); tdesc_create_reg (feature, "xmm1", regnum++, 1, NULL, 128, "vec128"); tdesc_create_reg (feature, "xmm2", regnum++, 1, NULL, 128, "vec128"); diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index e986d6f..4c0f597 100644 --- a/gdb/i386-linux-tdep.c +++ b/gdb/i386-linux-tdep.c @@ -45,13 +45,14 @@ #include "record-full.h" #include "linux-record.h" -#include "features/i386/i386-linux.c" -#include "features/i386/i386-mmx-linux.c" -#include "features/i386/i386-mpx-linux.c" -#include "features/i386/i386-avx-mpx-linux.c" -#include "features/i386/i386-avx-linux.c" -#include "features/i386/i386-avx-avx512-linux.c" -#include "features/i386/i386-avx-mpx-avx512-pku-linux.c" + +#include "features/i386/32bit-core.c" +#include "features/i386/32bit-sse.c" +#include "features/i386/32bit-linux.c" +#include "features/i386/32bit-avx.c" +#include "features/i386/32bit-mpx.c" +#include "features/i386/32bit-avx512.c" +#include "features/i386/32bit-pkeys.c" /* Return non-zero, when the register is in the corresponding register group. Put the LINUX_ORIG_EAX register in the system group. */ @@ -683,27 +684,50 @@ i386_linux_core_read_xcr0 (bfd *abfd) const struct target_desc * i386_linux_read_description (uint64_t xcr0) { - switch ((xcr0 & X86_XSTATE_ALL_MASK)) + if (xcr0 == 0) + return NULL; + + static struct target_desc *i386_linux_tdescs \ + [2/*X87*/][2/*SSE*/][2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/] = {}; + struct target_desc **tdesc; + + tdesc = &i386_linux_tdescs[(xcr0 & X86_XSTATE_X87) ? 1 : 0] + [(xcr0 & X86_XSTATE_SSE) ? 1 : 0] + [(xcr0 & X86_XSTATE_AVX) ? 1 : 0] + [(xcr0 & X86_XSTATE_MPX) ? 1 : 0] + [(xcr0 & X86_XSTATE_AVX512) ? 1 : 0] + [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]; + + if (*tdesc == NULL) { - case X86_XSTATE_AVX_MPX_AVX512_PKU_MASK: - return tdesc_i386_avx_mpx_avx512_pku_linux; - case X86_XSTATE_AVX_AVX512_MASK: - return tdesc_i386_avx_avx512_linux; - case X86_XSTATE_MPX_MASK: - return tdesc_i386_mpx_linux; - case X86_XSTATE_AVX_MPX_MASK: - return tdesc_i386_avx_mpx_linux; - case X86_XSTATE_AVX_MASK: - return tdesc_i386_avx_linux; - case X86_XSTATE_SSE_MASK: - return tdesc_i386_linux; - case X86_XSTATE_X87_MASK: - return tdesc_i386_mmx_linux; - default: - break; + *tdesc = allocate_target_description (); + set_tdesc_architecture (*tdesc, bfd_scan_arch ("i386")); + set_tdesc_osabi (*tdesc, osabi_from_tdesc_string ("GNU/Linux")); + + long regnum = 0; + + if (xcr0 & X86_XSTATE_X87) + regnum = create_feature_i386_32bit_core (*tdesc, regnum); + + if (xcr0 & X86_XSTATE_SSE) + regnum = create_feature_i386_32bit_sse (*tdesc, regnum); + + regnum = create_feature_i386_32bit_linux (*tdesc, regnum); + + if (xcr0 & X86_XSTATE_AVX) + regnum = create_feature_i386_32bit_avx (*tdesc, regnum); + + if (xcr0 & X86_XSTATE_MPX) + regnum = create_feature_i386_32bit_mpx (*tdesc, regnum); + + if (xcr0 & X86_XSTATE_AVX512) + regnum = create_feature_i386_32bit_avx512 (*tdesc, regnum); + + if (xcr0 & X86_XSTATE_PKRU) + regnum = create_feature_i386_32bit_pkeys (*tdesc, regnum); } - return NULL; + return *tdesc; } /* Get Linux/x86 target description from core dump. */ @@ -1092,13 +1116,4 @@ _initialize_i386_linux_tdep (void) { gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_LINUX, i386_linux_init_abi); - - /* Initialize the Linux target description. */ - initialize_tdesc_i386_linux (); - initialize_tdesc_i386_mmx_linux (); - initialize_tdesc_i386_avx_linux (); - initialize_tdesc_i386_mpx_linux (); - initialize_tdesc_i386_avx_mpx_linux (); - initialize_tdesc_i386_avx_avx512_linux (); - initialize_tdesc_i386_avx_mpx_avx512_pku_linux (); } diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index 518f2dc..d1755f4 100644 --- a/gdb/target-descriptions.c +++ b/gdb/target-descriptions.c @@ -2101,6 +2101,48 @@ public: void visit (const tdesc_reg *reg) override { + /* Most "reg" in XML target descriptions don't have "regnum" + attribute, so the register number is allocated sequentially. + In case that reg has "regnum" attribute, register number + should be set by that explicitly. */ + + if (reg->target_regnum < m_next_regnum) + { + /* The integrity check, it can catch some errors on register + number collision, like this, + + + + + + + + but it also has false negatives. The target description + below is correct, + + + + + + + but it is not a good practice, so still error on this, + and also print the message so that it can be saved in the + generated c file. */ + + printf_unfiltered ("ERROR: \"regnum\" attribute %ld ", + reg->target_regnum); + printf_unfiltered ("is not the largest number (%d).\n", + m_next_regnum); + error (_("\"regnum\" attribute %ld is not the largest number (%d)."), + reg->target_regnum, m_next_regnum); + } + + if (reg->target_regnum > m_next_regnum) + { + printf_unfiltered (" regnum = %ld;\n", reg->target_regnum); + m_next_regnum = reg->target_regnum; + } + printf_unfiltered (" tdesc_create_reg (feature, \"%s\", regnum++, %d, ", reg->name, reg->save_restore); if (reg->group) @@ -2108,8 +2150,13 @@ public: else printf_unfiltered ("NULL, "); printf_unfiltered ("%d, \"%s\");\n", reg->bitsize, reg->type); + + m_next_regnum++; } +private: + /* The register number to use for the next register we see. */ + int m_next_regnum = 0; }; static void