From patchwork Thu Jul 13 19:58:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 21608 Received: (qmail 57512 invoked by alias); 13 Jul 2017 19:59:06 -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 56174 invoked by uid 89); 13 Jul 2017 19:59:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 13 Jul 2017 19:59:02 +0000 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4B9B02DE3F; Thu, 13 Jul 2017 19:59:01 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 4B9B02DE3F Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=palves@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 4B9B02DE3F Received: from [127.0.0.1] (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id B600260BEC; Thu, 13 Jul 2017 19:58:59 +0000 (UTC) Subject: Re: [PATCH 1/2] Include the fs_base and gs_base registers in amd64 target descriptions. To: Yao Qi , John Baldwin References: <20170627224948.99138-1-jhb@FreeBSD.org> <2907792.3mtlvelY3m@ralph.baldwin.cx> <86y3rsp991.fsf@gmail.com> <9fcc9ea0-da6b-10fa-8a8e-022aa82893c9@redhat.com> Cc: gdb-patches@sourceware.org, Simon Marchi , Phil Muldoon From: Pedro Alves Message-ID: <8ac553a1-bc0c-92f4-64b1-633ca6a5ce9b@redhat.com> Date: Thu, 13 Jul 2017 20:58:57 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 In-Reply-To: <9fcc9ea0-da6b-10fa-8a8e-022aa82893c9@redhat.com> On 07/13/2017 07:40 PM, Pedro Alves wrote: > It seems to me that the proper fix is to make sure > that amd64_linux_init_abi and amd64_init_abi agree. Something like > this patch below. Fixes the crash for me. OK, as discussed on IRC, I've pushed this in. From c55a47e7237ebac17df73183d214d90400a49455 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Thu, 13 Jul 2017 20:56:42 +0100 Subject: [PATCH] Fix x86-64 GNU/Linux crashes Ref: https://sourceware.org/ml/gdb-patches/2017-07/msg00162.html Debugging x86-64 GNU/Linux programs currently crashes GDB in tdesc_use_registers during gdbarch initialization: Program received signal SIGSEGV, Segmentation fault. 0x0000000001093eaf in htab_remove_elt_with_hash (htab=0x2ef9fa0, element=0x26af960, hash=557151073) at src/libiberty/hashtab.c:728 728 if (*slot == HTAB_EMPTY_ENTRY) (top-gdb) p slot $1 = (void **) 0x0 (top-gdb) bt #0 0x0000000001093eaf in htab_remove_elt_with_hash (htab=0x2ef9fa0, element=0x26af960, hash=557151073) at src/libiberty/hashtab.c:728 #1 0x0000000001093e79 in htab_remove_elt (htab=0x2ef9fa0, element=0x26af960) at src/libiberty/hashtab.c:714 #2 0x00000000009121b0 in tdesc_use_registers (gdbarch=0x3001240, target_desc=0x2659cb0, early_data=0x2881cb0) at src/gdb/target-descriptions.c:1328 #3 0x000000000047c93e in i386_gdbarch_init (info=..., arches=0x0) at src/gdb/i386-tdep.c:8634 #4 0x0000000000818d5f in gdbarch_find_by_info (info=...) at src/gdb/gdbarch.c:5394 #5 0x00000000007198a8 in set_gdbarch_from_file (abfd=0x2f48250) at src/gdb/arch-utils.c:618 #6 0x00000000007f21cb in exec_file_attach (filename=0x7fffffffddb0 "/home/pedro/gdb/tests/threads", from_tty=1) at src/gdb/exec.c:380 #7 0x0000000000865c18 in catch_command_errors_const (command=0x7f1d83 , arg=0x7fffffffddb0 "/home/pedro/gdb/tests/threads", from_tty=1) at src/gdb/main.c:403 #8 0x00000000008669cf in captured_main_1 (context=0x7fffffffd860) at src/gdb/main.c:1035 #9 0x0000000000866de2 in captured_main (data=0x7fffffffd860) at src/gdb/main.c:1142 #10 0x0000000000866e24 in gdb_main (args=0x7fffffffd860) at src/gdb/main.c:1160 #11 0x000000000041312d in main (argc=3, argv=0x7fffffffd968) at src/gdb/gdb.c:32 The direct cause of the crash is that we tried to remove an element from the hash which supposedly exists, but does not. (htab_remove_elt shouldn't really crash in this case, but that's secondary.) The real problem is that early_data passed to tdesc_use_registers includes regs from a target description that is not the target_desc, which violates its assumptions. The registers in question are the fs_base/gs_base registers, added by amd64_init_abi: tdesc_numbered_register (feature, tdesc_data_segments, AMD64_FSBASE_REGNUM, "fs_base"); tdesc_numbered_register (feature, tdesc_data_segments, AMD64_GSBASE_REGNUM, "gs_base"); and that happens because amd64_linux_init_abi uses amd64_init_abi as helper, but they don't coordinate on which fallback tdesc to use. amd64_init_abi does: if (! tdesc_has_registers (tdesc)) tdesc = tdesc_amd64; and then adds the fs_base/gs_base registers of the "tdesc_amd64" tdesc to the tdesc_arch_data. After amd64_init_abi returns, amd64_linux_init_abi does: if (! tdesc_has_registers (tdesc)) tdesc = tdesc_amd64_linux; tdep->tdesc = tdesc; and we end up tdesc_amd64_linux installed in tdep->tdesc. The fix is to make sure that amd64_linux_init_abi and amd64_init_abi agree on default tdesc, by adding a "default tdesc" parameter to amd64_init_abi, instead of having amd64_init_abi hardcode a default. With this, amd64_init_abi creates the fs_base/gs_base registers using the tdesc_amd64_linux tdesc. Tested on x86-64 GNU/Linux, -m64. I don't have an x32 setup handy. Thanks to John Baldwin, Yao Qi and Simon Marchi for the investigation. gdb/ChangeLog: 2017-07-13 Pedro Alves * amd64-darwin-tdep.c (x86_darwin_init_abi_64): Pass tdesc_amd64 as default tdesc. * amd64-dicos-tdep.c (amd64_dicos_init_abi): * amd64-fbsd-tdep.c (amd64fbsd_init_abi): * amd64-linux-tdep.c (amd64_linux_init_abi): Pass tdesc_amd64_linux as default tdesc. Get final tdesc from the tdep. (amd64_x32_linux_init_abi): Pass tdesc_x32_linux as default tdesc. Get final tdesc from the tdep. * amd64-nbsd-tdep.c (amd64nbsd_init_abi): Pass tdesc_amd64 as default tdesc. * amd64-obsd-tdep.c (amd64obsd_init_abi): Likewise. * amd64-sol2-tdep.c (amd64_sol2_init_abi): Likewise. * amd64-tdep.c (amd64_init_abi): Add 'default_tdesc' parameter. Use it as default tdesc. (amd64_x32_init_abi): Add 'default_tdesc' parameter, and pass it down to amd_init_abi. No longer handle fallback tdesc here. * amd64-tdep.h (tdesc_x32): Declare. (amd64_init_abi, amd64_x32_init_abi): Add 'default_tdesc' parameter. * amd64-windows-tdep.c (amd64_windows_init_abi): Pass tdesc_amd64 as default tdesc. --- gdb/ChangeLog | 25 +++++++++++++++++++++++++ gdb/amd64-darwin-tdep.c | 2 +- gdb/amd64-dicos-tdep.c | 2 +- gdb/amd64-fbsd-tdep.c | 2 +- gdb/amd64-linux-tdep.c | 16 +++++----------- gdb/amd64-nbsd-tdep.c | 2 +- gdb/amd64-obsd-tdep.c | 2 +- gdb/amd64-sol2-tdep.c | 2 +- gdb/amd64-tdep.c | 15 ++++++--------- gdb/amd64-tdep.h | 13 +++++++++++-- gdb/amd64-windows-tdep.c | 2 +- 11 files changed, 54 insertions(+), 29 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 37fe06e..3210957 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,28 @@ +2017-07-13 Pedro Alves + + * amd64-darwin-tdep.c (x86_darwin_init_abi_64): Pass tdesc_amd64 + as default tdesc. + * amd64-dicos-tdep.c (amd64_dicos_init_abi): + * amd64-fbsd-tdep.c (amd64fbsd_init_abi): + * amd64-linux-tdep.c (amd64_linux_init_abi): Pass + tdesc_amd64_linux as default tdesc. Get final tdesc from the + tdep. + (amd64_x32_linux_init_abi): Pass tdesc_x32_linux as default tdesc. + Get final tdesc from the tdep. + * amd64-nbsd-tdep.c (amd64nbsd_init_abi): Pass tdesc_amd64 as + default tdesc. + * amd64-obsd-tdep.c (amd64obsd_init_abi): Likewise. + * amd64-sol2-tdep.c (amd64_sol2_init_abi): Likewise. + * amd64-tdep.c (amd64_init_abi): Add 'default_tdesc' parameter. + Use it as default tdesc. + (amd64_x32_init_abi): Add 'default_tdesc' parameter, and pass it + down to amd_init_abi. No longer handle fallback tdesc here. + * amd64-tdep.h (tdesc_x32): Declare. + (amd64_init_abi, amd64_x32_init_abi): Add 'default_tdesc' + parameter. + * amd64-windows-tdep.c (amd64_windows_init_abi): Pass tdesc_amd64 + as default tdesc. + 2017-07-13 Andreas Arnez * s390-linux-tdep.c (s390_process_record): Add support for diff --git a/gdb/amd64-darwin-tdep.c b/gdb/amd64-darwin-tdep.c index db400cd..be26d9e 100644 --- a/gdb/amd64-darwin-tdep.c +++ b/gdb/amd64-darwin-tdep.c @@ -99,7 +99,7 @@ x86_darwin_init_abi_64 (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - amd64_init_abi (info, gdbarch); + amd64_init_abi (info, gdbarch, tdesc_amd64); tdep->struct_return = reg_struct_return; diff --git a/gdb/amd64-dicos-tdep.c b/gdb/amd64-dicos-tdep.c index ee40891..7bdb167 100644 --- a/gdb/amd64-dicos-tdep.c +++ b/gdb/amd64-dicos-tdep.c @@ -25,7 +25,7 @@ static void amd64_dicos_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { - amd64_init_abi (info, gdbarch); + amd64_init_abi (info, gdbarch, tdesc_amd64); dicos_init_abi (gdbarch); } diff --git a/gdb/amd64-fbsd-tdep.c b/gdb/amd64-fbsd-tdep.c index 48bb209..ad4d787 100644 --- a/gdb/amd64-fbsd-tdep.c +++ b/gdb/amd64-fbsd-tdep.c @@ -217,7 +217,7 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->gregset_num_regs = ARRAY_SIZE (amd64fbsd_r_reg_offset); tdep->sizeof_gregset = 22 * 8; - amd64_init_abi (info, gdbarch); + amd64_init_abi (info, gdbarch, tdesc_amd64); tdep->sigtramp_p = amd64fbsd_sigtramp_p; tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr; diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index 4ef0f78..cf24789 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -1863,7 +1863,6 @@ static void amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const struct target_desc *tdesc = info.target_desc; struct tdesc_arch_data *tdesc_data = (struct tdesc_arch_data *) info.tdep_info; const struct tdesc_feature *feature; @@ -1875,15 +1874,13 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset); tdep->sizeof_gregset = 27 * 8; - amd64_init_abi (info, gdbarch); + amd64_init_abi (info, gdbarch, tdesc_amd64_linux); + + const target_desc *tdesc = tdep->tdesc; /* Reserve a number for orig_rax. */ set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS); - if (! tdesc_has_registers (tdesc)) - tdesc = tdesc_amd64_linux; - tdep->tdesc = tdesc; - feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux"); if (feature == NULL) return; @@ -2080,7 +2077,6 @@ static void amd64_x32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const struct target_desc *tdesc = info.target_desc; struct tdesc_arch_data *tdesc_data = (struct tdesc_arch_data *) info.tdep_info; const struct tdesc_feature *feature; @@ -2092,14 +2088,12 @@ amd64_x32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset); tdep->sizeof_gregset = 27 * 8; - amd64_x32_init_abi (info, gdbarch); + amd64_x32_init_abi (info, gdbarch, tdesc_x32_linux); /* Reserve a number for orig_rax. */ set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS); - if (! tdesc_has_registers (tdesc)) - tdesc = tdesc_x32_linux; - tdep->tdesc = tdesc; + const target_desc *tdesc = tdep->tdesc; feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux"); if (feature == NULL) diff --git a/gdb/amd64-nbsd-tdep.c b/gdb/amd64-nbsd-tdep.c index db6f19f..02bf427 100644 --- a/gdb/amd64-nbsd-tdep.c +++ b/gdb/amd64-nbsd-tdep.c @@ -103,7 +103,7 @@ amd64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->gregset_num_regs = ARRAY_SIZE (amd64nbsd_r_reg_offset); tdep->sizeof_gregset = 26 * 8; - amd64_init_abi (info, gdbarch); + amd64_init_abi (info, gdbarch, tdesc_amd64); tdep->jb_pc_offset = 7 * 8; diff --git a/gdb/amd64-obsd-tdep.c b/gdb/amd64-obsd-tdep.c index 72895b6..ad90c20 100644 --- a/gdb/amd64-obsd-tdep.c +++ b/gdb/amd64-obsd-tdep.c @@ -419,7 +419,7 @@ amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - amd64_init_abi (info, gdbarch); + amd64_init_abi (info, gdbarch, tdesc_amd64); obsd_init_abi (info, gdbarch); /* Initialize general-purpose register set details. */ diff --git a/gdb/amd64-sol2-tdep.c b/gdb/amd64-sol2-tdep.c index 51fe9db..ca474db 100644 --- a/gdb/amd64-sol2-tdep.c +++ b/gdb/amd64-sol2-tdep.c @@ -99,7 +99,7 @@ amd64_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->gregset_num_regs = ARRAY_SIZE (amd64_sol2_gregset_reg_offset); tdep->sizeof_gregset = 28 * 8; - amd64_init_abi (info, gdbarch); + amd64_init_abi (info, gdbarch, tdesc_amd64); tdep->sigtramp_p = amd64_sol2_sigtramp_p; tdep->sigcontext_addr = amd64_sol2_mcontext_addr; diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 9ff7dfc..6171bc5 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -3005,7 +3005,8 @@ static const int amd64_record_regmap[] = }; void -amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch, + target_desc *default_tdesc) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); const struct target_desc *tdesc = info.target_desc; @@ -3022,7 +3023,7 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->fpregset = &amd64_fpregset; if (! tdesc_has_registers (tdesc)) - tdesc = tdesc_amd64; + tdesc = default_tdesc; tdep->tdesc = tdesc; tdep->num_core_regs = AMD64_NUM_GREGS + I387_NUM_REGS; @@ -3196,16 +3197,12 @@ amd64_x32_pseudo_register_type (struct gdbarch *gdbarch, int regnum) } void -amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch, + target_desc *default_tdesc) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const struct target_desc *tdesc = info.target_desc; - - amd64_init_abi (info, gdbarch); - if (! tdesc_has_registers (tdesc)) - tdesc = tdesc_x32; - tdep->tdesc = tdesc; + amd64_init_abi (info, gdbarch, default_tdesc); tdep->num_dword_regs = 17; set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_type); diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h index 87f0ba3..d4c6c9a 100644 --- a/gdb/amd64-tdep.h +++ b/gdb/amd64-tdep.h @@ -88,6 +88,7 @@ enum amd64_regnum #define AMD64_NUM_REGS (AMD64_GSBASE_REGNUM + 1) extern struct target_desc *tdesc_amd64; +extern struct target_desc *tdesc_x32; extern struct displaced_step_closure *amd64_displaced_step_copy_insn (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, @@ -97,9 +98,17 @@ extern void amd64_displaced_step_fixup (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, struct regcache *regs); -extern void amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch); +/* Initialize the ABI for amd64. Uses DEFAULT_TDESC as fallback + tdesc, if INFO does not specify one. */ +extern void amd64_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch, + target_desc *default_tdesc); + +/* Initialize the ABI for x32. Uses DEFAULT_TDESC as fallback tdesc, + if INFO does not specify one. */ extern void amd64_x32_init_abi (struct gdbarch_info info, - struct gdbarch *gdbarch); + struct gdbarch *gdbarch, + target_desc *default_tdesc); extern const struct target_desc *amd64_target_description (uint64_t xcr0); /* Fill register REGNUM in REGCACHE with the appropriate diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c index f1acdb9..9158282 100644 --- a/gdb/amd64-windows-tdep.c +++ b/gdb/amd64-windows-tdep.c @@ -1224,7 +1224,7 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) */ frame_unwind_append_unwinder (gdbarch, &amd64_windows_frame_unwind); - amd64_init_abi (info, gdbarch); + amd64_init_abi (info, gdbarch, tdesc_amd64); windows_init_abi (info, gdbarch);