From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from barracuda.ebox.ca (barracuda.ebox.ca [96.127.255.19]) by sourceware.org (Postfix) with ESMTPS id 85933385BF84 for ; Thu, 15 Jul 2021 19:53:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 85933385BF84 X-ASG-Debug-ID: 1626378793-0c856e67e21a3f6c0001-fS2M51 Received: from smtp.ebox.ca (smtp.ebox.ca [96.127.255.82]) by barracuda.ebox.ca with ESMTP id wGcYPKBestAYPHS4 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 15 Jul 2021 15:53:13 -0400 (EDT) X-Barracuda-Envelope-From: simon.marchi@polymtl.ca X-Barracuda-RBL-Trusted-Forwarder: 96.127.255.82 Received: from simark.localdomain (192-222-157-6.qc.cable.ebox.net [192.222.157.6]) by smtp.ebox.ca (Postfix) with ESMTP id 444A8441B21; Thu, 15 Jul 2021 15:53:13 -0400 (EDT) From: Simon Marchi X-Barracuda-RBL-IP: 192.222.157.6 X-Barracuda-Effective-Source-IP: 192-222-157-6.qc.cable.ebox.net[192.222.157.6] X-Barracuda-Apparent-Source-IP: 192.222.157.6 To: gdb-patches@sourceware.org Subject: [PATCH] gdb: nat/x86-dregs.c: add and use x86_dr_low_can_get_status Date: Thu, 15 Jul 2021 15:53:12 -0400 X-ASG-Orig-Subj: [PATCH] gdb: nat/x86-dregs.c: add and use x86_dr_low_can_get_status Message-Id: <20210715195312.2105187-1-simon.marchi@polymtl.ca> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: smtp.ebox.ca[96.127.255.82] X-Barracuda-Start-Time: 1626378793 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://96.127.255.19:443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at ebox.ca X-Barracuda-Scan-Msg-Size: 4427 X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.00 X-Barracuda-Spam-Status: No, SCORE=1.00 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=8.0 tests=BSF_RULE7568M, WEIRD_PORT X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.91228 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.50 WEIRD_PORT URI: Uses non-standard port number for HTTP 0.50 BSF_RULE7568M Custom Rule 7568M X-Spam-Status: No, score=-16.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_QUARANTINE, KAM_DMARC_STATUS, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 15 Jul 2021 19:53:16 -0000 I built and tried gdb on OpenBSD, and it immediately segfaults when running a program. I tracked down the problem to x86_dr_low.get_status being nullptr at this point: (lldb) print x86_dr_low.get_status (unsigned long (*)()) $0 = 0x0000000000000000 (lldb) bt * thread #1, stop reason = step over * frame #0: 0x0000033b64b764aa gdb`x86_dr_stopped_data_address(state=0x0000033d7162a310, addr_p=0x00007f7ffffc5688) at x86-dregs.c:645:12 frame #1: 0x0000033b64b766de gdb`x86_dr_stopped_by_watchpoint(state=0x0000033d7162a310) at x86-dregs.c:687:10 frame #2: 0x0000033b64ea5f72 gdb`x86_stopped_by_watchpoint() at x86-nat.c:206:10 frame #3: 0x0000033b64637fbb gdb`x86_nat_target::stopped_by_watchpoint(this=0x0000033b65252820) at x86-nat.h:100:12 frame #4: 0x0000033b64d3ff11 gdb`target_stopped_by_watchpoint() at target.c:468:46 frame #5: 0x0000033b6469b001 gdb`watchpoints_triggered(ws=0x00007f7ffffc61c8) at breakpoint.c:4790:32 frame #6: 0x0000033b64a8bb8b gdb`handle_signal_stop(ecs=0x00007f7ffffc61a0) at infrun.c:6072:29 frame #7: 0x0000033b64a7e3a7 gdb`handle_inferior_event(ecs=0x00007f7ffffc61a0) at infrun.c:5694:7 frame #8: 0x0000033b64a7c1a0 gdb`fetch_inferior_event() at infrun.c:4090:5 frame #9: 0x0000033b64a51921 gdb`inferior_event_handler(event_type=INF_REG_EVENT) at inf-loop.c:41:7 frame #10: 0x0000033b64a827c9 gdb`infrun_async_inferior_event_handler(data=0x0000000000000000) at infrun.c:9384:3 frame #11: 0x0000033b6465bd4f gdb`check_async_event_handlers() at async-event.c:335:4 frame #12: 0x0000033b65070917 gdb`gdb_do_one_event() at event-loop.cc:216:10 frame #13: 0x0000033b64af0db1 gdb`start_event_loop() at main.c:421:13 frame #14: 0x0000033b64aefe9a gdb`captured_command_loop() at main.c:481:3 frame #15: 0x0000033b64aed5c2 gdb`captured_main(data=0x00007f7ffffc6470) at main.c:1353:4 frame #16: 0x0000033b64aed4f2 gdb`gdb_main(args=0x00007f7ffffc6470) at main.c:1368:7 frame #17: 0x0000033b6459d787 gdb`main(argc=5, argv=0x00007f7ffffc6518) at gdb.c:32:10 frame #18: 0x0000033b6459d521 gdb`___start + 321 On BSDs, get_status is set in _initialize_x86_bsd_nat, but only if HAVE_PT_GETDBREGS is defined. PT_GETDBREGS doesn't exist on OpenBSD, so get_status (and the other fields of x86_dr_low) is left nullptr. I don't know if there is a way to get the DR6 / status register on OpenBSD, but even if there is, GDB doesn't leverage it as of today. Since there's no way of getting the status register, it's ok that x86_dr_low.get_status is nullptr, but code using it should be aware that it can be nullptr. Add a x86_dr_low_can_get_status function and use it it functions that call x86_dr_low_get_status. With this, running a program gets a bit further, but we hit this: (gdb) r Starting program: /home/simark/build/binutils-gdb/gdb/a.out Child process unexpectedly missing: No child processes. /home/simark/src/binutils-gdb/gdb/inferior.c:303: internal-error: struct inferior *find_inferior_pid(process_stratum_target *, int): Assertion `pid != 0' failed That will be the topic for another patch. Change-Id: Ibbf6ec02469c80c1a7ab34e71d503779c9ae840c --- gdb/nat/x86-dregs.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/gdb/nat/x86-dregs.c b/gdb/nat/x86-dregs.c index cf8e517eb0d6..699918674547 100644 --- a/gdb/nat/x86-dregs.c +++ b/gdb/nat/x86-dregs.c @@ -82,6 +82,14 @@ x86_dr_low_get_control () return x86_dr_low.get_control (); } +/* Can we read the status (DR6) register? */ + +static bool +x86_dr_low_can_get_status () +{ + return x86_dr_low.get_status != nullptr; +} + /* Return the value of the inferior's DR6 debug status register. */ static unsigned long @@ -604,6 +612,9 @@ int x86_dr_stopped_data_address (struct x86_debug_reg_state *state, CORE_ADDR *addr_p) { + if (!x86_dr_low_can_get_status ()) + return 0; + CORE_ADDR addr = 0; int i; int rc = 0; @@ -693,6 +704,9 @@ x86_dr_stopped_by_watchpoint (struct x86_debug_reg_state *state) int x86_dr_stopped_by_hw_breakpoint (struct x86_debug_reg_state *state) { + if (!x86_dr_low_can_get_status ()) + return 0; + CORE_ADDR addr = 0; int i; int rc = 0; -- 2.32.0