From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-io1-xd33.google.com (mail-io1-xd33.google.com [IPv6:2607:f8b0:4864:20::d33]) by sourceware.org (Postfix) with ESMTPS id E6B723858425 for ; Mon, 12 Jun 2023 19:36:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E6B723858425 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com Received: by mail-io1-xd33.google.com with SMTP id ca18e2360f4ac-77ad3bba2a9so295701939f.1 for ; Mon, 12 Jun 2023 12:36:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore.com; s=google; t=1686598594; x=1689190594; h=to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=2qMZloQUALFU42e0oBjf0lf36p+l2SaMH3k7MM7eFm0=; b=GDP5ag30zncCDLRoEd/ioMI1yDV629F1B5reDjH2BZ47vpOeJ0/D2v4mvFh7Hkv3x7 bP/lceBHllxXU37sWjSA/undQ7qMtlcZmJYVEyKyHrc8vDDFHf12J1K6kBLlEfrmwwOE wf7lHafUxeRG9anB6xsAtgaFWQ+pHOAbwZ1YJM264+NzPu5DQ5Th6X4SDbP3WLPhUXJ0 q5w/dpOlr/KSnC1zjK3NnBF4FDep2394NA3vts2EXCv+DFFGRLTfske283ug1wQrNl91 my8fgX5DSvhechdTLmO2nycp46zj2LMUxK/iSduHJhrv90i08OcwhJ5T60nonozkF9Pn mVAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686598594; x=1689190594; h=to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2qMZloQUALFU42e0oBjf0lf36p+l2SaMH3k7MM7eFm0=; b=hUAFepTPS60HDeEIMkaoKFBBgriLVfeZi+K5dNh9eYHf7kJODxc3pJygPeAM8hQ/ei qOqrm+2y0rDOdcEq2n/2BwIoNQceIQISWLJiMZCbCaKpv2pHtANqkFvGb4dgM9v/x+CX M6Wp0WENYyWpJ4Zt/N5todm7PkuMd2qzK0xKt1bp6mujjmXSVRWIh3td3I/2flMvqq8r v5VLRNCp96SAaizJXLFEnIN+ZKCvDRaYfH1kxDsO5IAT4A4+VfBoiKFhiZMPFthuM0qT 90OUAGTxKN6xfeo9VYblglAGMEi195DNq5Ir+f5We+xx64gd6TJAnGTcVoMmySKt9cBK utug== X-Gm-Message-State: AC+VfDzzGl2p3lx2Gd2CViM5pmKJEnFvaRhEXQP8VB7h5sLCrEw2HYJO 2jR+QpQEtTDQAuYDma/En3kcDh7k8Gvv50IvKMogTw== X-Google-Smtp-Source: ACHHUZ4o6xhEPCw0eGhmz9B84jHf1R0TgAKUure6MaLmSBNKxHrvRP/WOkrOaJgLDZMuEgs1HtTlog== X-Received: by 2002:a92:db4a:0:b0:33d:6d9f:b65c with SMTP id w10-20020a92db4a000000b0033d6d9fb65cmr8504508ilq.6.1686598594131; Mon, 12 Jun 2023 12:36:34 -0700 (PDT) Received: from localhost.localdomain (75-166-136-83.hlrn.qwest.net. [75.166.136.83]) by smtp.gmail.com with ESMTPSA id m12-20020a056638224c00b00418a5e0e93esm2938091jas.162.2023.06.12.12.36.33 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Jun 2023 12:36:33 -0700 (PDT) From: Tom Tromey Date: Mon, 12 Jun 2023 13:36:33 -0600 Subject: [PATCH 6/7] Implement DAP logging breakpoints MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20230612-more-dap-v1-6-ad868f1a4cc0@adacore.com> References: <20230612-more-dap-v1-0-ad868f1a4cc0@adacore.com> In-Reply-To: <20230612-more-dap-v1-0-ad868f1a4cc0@adacore.com> To: gdb-patches@sourceware.org X-Mailer: b4 0.12.2 X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE 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: DAP allows a source breakpoint to specify a log message. When this is done, the breakpoint acts more like gdb's dprintf: it logs a message but does not cause a stop. I looked into implement this using dprintf with the new %V printf format. However, my initial attempt at this did not work, because when the inferior is continued, the dprintf output is captured by the gdb.execute call. Maybe this could be fixed by having all inferior-continuation commands use the "&" form; the main benefit of this would be that expressions are only parsed a single time. --- gdb/python/lib/gdb/dap/breakpoint.py | 53 +++++++++++++++++++++++++++++++++-- gdb/testsuite/gdb.dap/log-message.c | 31 ++++++++++++++++++++ gdb/testsuite/gdb.dap/log-message.exp | 51 +++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 3 deletions(-) diff --git a/gdb/python/lib/gdb/dap/breakpoint.py b/gdb/python/lib/gdb/dap/breakpoint.py index 227085ad73e..27745ebfd2c 100644 --- a/gdb/python/lib/gdb/dap/breakpoint.py +++ b/gdb/python/lib/gdb/dap/breakpoint.py @@ -15,11 +15,12 @@ import gdb import os +import re # These are deprecated in 3.9, but required in older versions. from typing import Optional, Sequence -from .server import request, capability +from .server import request, capability, send_event from .startup import send_gdb_with_response, in_gdb_thread, log_stack from .typecheck import type_check @@ -136,11 +137,54 @@ def _set_breakpoints_callback(kind, specs, creator): return result -# Helper function to set odinary breakpoints according to a list of +class _PrintBreakpoint(gdb.Breakpoint): + def __init__(self, logMessage, **args): + super().__init__(**args) + # Split the message up for easier processing. + self.message = re.split("{(.*?)}", logMessage) + + def stop(self): + output = "" + for idx, item in enumerate(self.message): + if idx % 2 == 0: + # Even indices are plain text. + output += item + else: + # Odd indices are expressions to substitute. The {} + # have already been stripped by the placement of the + # regex capture in the 'split' call. + try: + val = gdb.parse_and_eval(item) + output += str(val) + except Exception as e: + output += "<" + str(e) + ">" + send_event( + "output", + { + "category": "console", + "output": output, + }, + ) + # Do not stop. + return False + + +# Set a single breakpoint or a log point. Returns the new breakpoint. +# Note that not every spec will pass logMessage, so here we use a +# default. +@in_gdb_thread +def _set_one_breakpoint(*, logMessage=None, **args): + if logMessage is not None: + return _PrintBreakpoint(logMessage, **args) + else: + return gdb.Breakpoint(**args) + + +# Helper function to set ordinary breakpoints according to a list of # specifications. @in_gdb_thread def _set_breakpoints(kind, specs): - return _set_breakpoints_callback(kind, specs, gdb.Breakpoint) + return _set_breakpoints_callback(kind, specs, _set_one_breakpoint) # A helper function that rewrites a SourceBreakpoint into the internal @@ -154,6 +198,7 @@ def _rewrite_src_breakpoint( line: int, condition: Optional[str] = None, hitCondition: Optional[str] = None, + logMessage: Optional[str] = None, **args, ): return { @@ -161,6 +206,7 @@ def _rewrite_src_breakpoint( "line": line, "condition": condition, "hitCondition": hitCondition, + "logMessage": logMessage, } @@ -168,6 +214,7 @@ def _rewrite_src_breakpoint( @request("setBreakpoints") @capability("supportsHitConditionalBreakpoints") @capability("supportsConditionalBreakpoints") +@capability("supportsLogPoints") def set_breakpoint(*, source, breakpoints: Sequence = (), **args): if "path" not in source: result = [] diff --git a/gdb/testsuite/gdb.dap/log-message.c b/gdb/testsuite/gdb.dap/log-message.c new file mode 100644 index 00000000000..d2c746033ad --- /dev/null +++ b/gdb/testsuite/gdb.dap/log-message.c @@ -0,0 +1,31 @@ +/* Copyright 2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +int global_variable; + +int +func (int local) +{ + return global_variable - local; /* HERE */ +} + +int +main () +{ + global_variable = 23; + return func (23); +} diff --git a/gdb/testsuite/gdb.dap/log-message.exp b/gdb/testsuite/gdb.dap/log-message.exp new file mode 100644 index 00000000000..31d5c4a11d4 --- /dev/null +++ b/gdb/testsuite/gdb.dap/log-message.exp @@ -0,0 +1,51 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test DAP logging breakpoints. + +require allow_dap_tests + +load_lib dap-support.exp + +standard_testfile + +if {[build_executable ${testfile}.exp $testfile] == -1} { + return +} + +if {[dap_launch $testfile] == ""} { + return +} + +set line [gdb_get_line_number "HERE"] +set obj [dap_check_request_and_response "set breakpoint" \ + setBreakpoints \ + [format {o source [o path [%s]] \ + breakpoints [a [o line [i %d] \ + logMessage [s "got {global_variable} - {local} = {global_variable - local}"]]]} \ + [list s $srcfile] $line]] +set fn_bpno [dap_get_breakpoint_number $obj] + +dap_check_request_and_response "start inferior" configurationDone +dap_wait_for_event_and_check "inferior started" thread "body reason" started + +dap_wait_for_event_and_check "logging output" output \ + {body category} console \ + {body output} "got 23 - 23 = 0" + +# Check that the breakpoint did not cause a stop. +dap_wait_for_event_and_check "inferior exited" exited + +dap_shutdown -- 2.40.1