From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-il1-x12d.google.com (mail-il1-x12d.google.com [IPv6:2607:f8b0:4864:20::12d]) by sourceware.org (Postfix) with ESMTPS id 899FF385B516 for ; Tue, 22 Aug 2023 15:25:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 899FF385B516 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-il1-x12d.google.com with SMTP id e9e14a558f8ab-34bad46e5a5so15456565ab.1 for ; Tue, 22 Aug 2023 08:25:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore.com; s=google; t=1692717917; x=1693322717; 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=LMUFch5KDBrLdQKT0mpTZJ5IUahs0sofyPdLP9tpUkA=; b=YWrQV1KUPCvXu1WA0Sz5SfoNBm8zPCcOPL2BVhY77jgtr2Zn87xSR9UrdsbzV4DgFh 5vZRjqxr22R3AQlV9gEwoXcYUdDwffcP6ldZaU6jvHlu48aJu39v0LCRh7MkiVYooIwc ddOmH32cgEbEDEDe6MU+O9pQhsBgLRvopiOhWLufmfVeMVEwjxAmI6raRf2t1F6M/bk1 /TBLcvX/CCl0eEqTGXl0yE02Tl+qnJyPTtjQrY3nJlnydWCMvCfXw6lSo1MqRlOoW1yn h4ZtjP/lCz508oZdUFhVvUGZzI9tC2V6pnx+fIAcN9CNQCjhkfnqBS9ees5W6TBCotgA OH7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1692717917; x=1693322717; 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=LMUFch5KDBrLdQKT0mpTZJ5IUahs0sofyPdLP9tpUkA=; b=g/qGRRNRtqboigweZjp/tL0vbVeTalg4PqN0JVzUFAE5wVD1onJNG9uTC9+EH1oPDL yVFlVArUEo1949w8P60iozOiikXnUN3+vkvTjEzgPE5b/Ft1KFge9o7JBkW9XSW9dWoK mjkyJMnkAH908zoJAQqzCWpHOzRHe54SVqe8AWDUhPga5wQ1nSlxNmY44kRLqwe/Csu3 JsCy5fZZuVOqAqCPe/Wrr6TOuLS1czRFV5Rc3B0708p0tIVjRfIGaCdQ3WzWDfmgeLV1 rG9X1zEt+PzM6v1A4tV8+LcgMD/q2UZMpeesxi3eXtWjzy4A+MANGrbEFaU4eYTAw+pz 20FQ== X-Gm-Message-State: AOJu0Yy4paYUyJLfkHbhuqtkWJQJpXqNxdaCBfWaUqFPSnNGp6EKFEu2 tpm/jAWxOTw16jqo3VVQ6LZ1uHnSUxEsAMtlZqg7Dw== X-Google-Smtp-Source: AGHT+IFDii1mpqEo4LABLLLoSNL6td7WduAM0nWjs8CmdoKVmHIvJRSNglKLwXq4Dfvy42KCEE4iTw== X-Received: by 2002:a05:6e02:1a65:b0:34c:ba3b:a532 with SMTP id w5-20020a056e021a6500b0034cba3ba532mr7693ilv.11.1692717916651; Tue, 22 Aug 2023 08:25:16 -0700 (PDT) Received: from localhost.localdomain (75-166-142-177.hlrn.qwest.net. [75.166.142.177]) by smtp.gmail.com with ESMTPSA id e8-20020a92de48000000b003460b8505easm1721608ilr.19.2023.08.22.08.25.16 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Aug 2023 08:25:16 -0700 (PDT) From: Tom Tromey Date: Tue, 22 Aug 2023 09:25:14 -0600 Subject: [PATCH 8/8] Handle array- and string-like values in no-op pretty printers MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20230822-array-and-string-like-v1-8-2dcea29b0567@adacore.com> References: <20230822-array-and-string-like-v1-0-2dcea29b0567@adacore.com> In-Reply-To: <20230822-array-and-string-like-v1-0-2dcea29b0567@adacore.com> To: gdb-patches@sourceware.org X-Mailer: b4 0.12.3 X-Spam-Status: No, score=-11.6 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 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: This changes the no-op pretty printers -- used by DAP -- to handle array- and string-like objects known by the gdb core. Two new tests are added, one for Ada and one for Rust. --- gdb/python/lib/gdb/printing.py | 26 ++++++- gdb/testsuite/gdb.dap/ada-arrays.exp | 123 ++++++++++++++++++++++++++++++ gdb/testsuite/gdb.dap/ada-arrays/cstuff.c | 22 ++++++ gdb/testsuite/gdb.dap/ada-arrays/main.adb | 24 ++++++ gdb/testsuite/gdb.dap/ada-arrays/pck.adb | 21 +++++ gdb/testsuite/gdb.dap/ada-arrays/pck.ads | 51 +++++++++++++ gdb/testsuite/gdb.dap/rust-slices.exp | 119 +++++++++++++++++++++++++++++ gdb/testsuite/gdb.dap/rust-slices.rs | 29 +++++++ 8 files changed, 412 insertions(+), 3 deletions(-) diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py index a668bd0e3fc..1a761a6aa57 100644 --- a/gdb/python/lib/gdb/printing.py +++ b/gdb/python/lib/gdb/printing.py @@ -18,6 +18,7 @@ import gdb import gdb.types +import itertools import re @@ -285,11 +286,24 @@ class NoOpArrayPrinter: def __init__(self, ty, value): self.value = value (low, high) = ty.range() - self.low = low - self.high = high + # In Ada, an array can have an index type that is a + # non-contiguous enum. In this case the indexing must be done + # by using the indices into the enum type, not the underlying + # integer values. + range_type = ty.fields()[0].type + if range_type.target().code == gdb.TYPE_CODE_ENUM: + e_values = range_type.target().fields() + # Drop any values before LOW. + e_values = itertools.dropwhile(lambda x: x.enumval < low, e_values) + # Drop any values after HIGH. + e_values = itertools.takewhile(lambda x: x.enumval <= high, e_values) + low = 0 + high = len(list(e_values)) - 1 # This is a convenience to the DAP code and perhaps other # users. self.num_children = high - low + 1 + self.low = low + self.high = high def to_string(self): return "" @@ -330,7 +344,13 @@ def make_visualizer(value): pass else: ty = value.type.strip_typedefs() - if ty.code == gdb.TYPE_CODE_ARRAY: + if ty.is_string_like: + result = gdb.printing.NoOpScalarPrinter(value) + elif ty.code == gdb.TYPE_CODE_ARRAY: + result = gdb.printing.NoOpArrayPrinter(ty, value) + elif ty.is_array_like: + value = value.to_array() + ty = value.type.strip_typedefs() result = gdb.printing.NoOpArrayPrinter(ty, value) elif ty.code in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION): result = gdb.printing.NoOpStructPrinter(ty, value) diff --git a/gdb/testsuite/gdb.dap/ada-arrays.exp b/gdb/testsuite/gdb.dap/ada-arrays.exp new file mode 100644 index 00000000000..13b5425ded4 --- /dev/null +++ b/gdb/testsuite/gdb.dap/ada-arrays.exp @@ -0,0 +1,123 @@ +# 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 . + +load_lib "ada.exp" +load_lib dap-support.exp + +require allow_dap_tests +require allow_ada_tests + +standard_ada_testfile main +set cfile "cstuff" +set csrcfile ${srcdir}/${subdir}/${testdir}/${cfile}.c +set cobject [standard_output_file ${cfile}.o] + +gdb_compile "${csrcfile}" "${cobject}" object [list debug] +if {[gdb_compile_ada "${srcfile}" "${binfile}" executable debug] != ""} { + return -1 +} + +if {[dap_launch $testfile] == ""} { + return +} + +# Stop in a C frame, but examine values in an Ada frame, to make sure +# cross-language scenarios work correctly. +set line [gdb_get_line_number "STOP" $testdir/cstuff.c] +set obj [dap_check_request_and_response "set breakpoint by line number" \ + setBreakpoints \ + [format {o source [o path [%s]] breakpoints [a [o line [i %d]]]} \ + [list s cstuff.c] $line]] +set line_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 "stopped at line breakpoint" stopped \ + "body reason" breakpoint \ + "body hitBreakpointIds" $line_bpno + +set bt [lindex [dap_check_request_and_response "backtrace" stackTrace \ + {o threadId [i 1]}] \ + 0] +# The Ada frame is frame 1. +set frame_id [dict get [lindex [dict get $bt body stackFrames] 1] id] + +set scopes [dap_check_request_and_response "get scopes" scopes \ + [format {o frameId [i %d]} $frame_id]] +set scopes [dict get [lindex $scopes 0] body scopes] + +gdb_assert {[llength $scopes] == 2} "two scopes" + +lassign $scopes scope ignore +gdb_assert {[dict get $scope name] == "Arguments"} "scope is arguments" +gdb_assert {[dict get $scope presentationHint] == "arguments"} \ + "arguments presentation hint" +gdb_assert {[dict get $scope namedVariables] == 3} "three vars in scope" + +set num [dict get $scope variablesReference] +set refs [lindex [dap_check_request_and_response "fetch arguments" \ + "variables" \ + [format {o variablesReference [i %d]} $num]] \ + 0] + +# Helper to check the contents of a single array-like object. VAR is +# the variable entry. NAME is the name of the variable, pulled out +# for convenience.# ARGS are the expected child values. +proc check_array_contents {var name args} { + set len [llength $args] + gdb_assert {[dict get $var indexedVariables] == $len} \ + "check length of $name variable" + + set num [dict get $var variablesReference] + set refs [lindex [dap_check_request_and_response \ + "fetch contents of $name" \ + "variables" \ + [format {o variablesReference [i %d]} $num]] \ + 0] + + foreach subvar [dict get $refs body variables] subvalue $args { + set subname [dict get $subvar name] + gdb_assert {[dict get $subvar value] == $subvalue} \ + "check value of $name entry $subname" + } +} + +foreach var [dict get $refs body variables] { + set name [dict get $var name] + switch $name { + "the_buffer" { + check_array_contents $var $name 1 2 3 4 + } + + "the_ar" { + check_array_contents $var $name 5 6 7 8 9 + } + + "hello" { + # Note that the expected value looks strange here -- there + # are too many backslashes. This is a TON issue, as the + # JSON looks ok: "value": "\"hello\"". + gdb_assert {[dict get $var value] == "\\\"hello\\\""} \ + "value of hello variable" + } + + default { + fail "unknown variable $name" + } + } +} + +dap_shutdown diff --git a/gdb/testsuite/gdb.dap/ada-arrays/cstuff.c b/gdb/testsuite/gdb.dap/ada-arrays/cstuff.c new file mode 100644 index 00000000000..af87082401c --- /dev/null +++ b/gdb/testsuite/gdb.dap/ada-arrays/cstuff.c @@ -0,0 +1,22 @@ +/* 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 . */ + +void +c_procedure (int x) +{ + /* STOP */ +} diff --git a/gdb/testsuite/gdb.dap/ada-arrays/main.adb b/gdb/testsuite/gdb.dap/ada-arrays/main.adb new file mode 100644 index 00000000000..c9e98c4a249 --- /dev/null +++ b/gdb/testsuite/gdb.dap/ada-arrays/main.adb @@ -0,0 +1,24 @@ +-- 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 . + +with Pck; use Pck; + +procedure Main is + Value : Buffer (1 .. 4) := (1, 2, 3, 4); + Another_Value : AR := (5, 6, 7, 8, 9); + Hello: String := "hello"; +begin + Do_Nothing (Value, Another_Value, Hello); +end Main; diff --git a/gdb/testsuite/gdb.dap/ada-arrays/pck.adb b/gdb/testsuite/gdb.dap/ada-arrays/pck.adb new file mode 100644 index 00000000000..7efa8930af8 --- /dev/null +++ b/gdb/testsuite/gdb.dap/ada-arrays/pck.adb @@ -0,0 +1,21 @@ +-- 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 . + +package body Pck is + procedure Do_Nothing (The_Buffer : in out Buffer; The_AR : in out AR; Hello: in out String) is + begin + C_Procedure (23); + end Do_Nothing; +end Pck; diff --git a/gdb/testsuite/gdb.dap/ada-arrays/pck.ads b/gdb/testsuite/gdb.dap/ada-arrays/pck.ads new file mode 100644 index 00000000000..475bb7bf1e9 --- /dev/null +++ b/gdb/testsuite/gdb.dap/ada-arrays/pck.ads @@ -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 . + +package Pck is + pragma Linker_Options ("cstuff.o"); + + procedure C_Procedure (Value : Integer); + pragma Import(C, C_Procedure, "c_procedure"); + + type Small is new Integer range 0 .. 2 ** 6 - 1; + + type Buffer is array (Integer range <>) of Small; + pragma Pack (Buffer); + + type Enum_With_Gaps is + ( + LIT0, + LIT1, + LIT2, + LIT3, + LIT4 + ); + + for Enum_With_Gaps use + ( + LIT0 => 3, + LIT1 => 5, + LIT2 => 8, + LIT3 => 13, + LIT4 => 21 + ); + for Enum_With_Gaps'size use 16; + + type Enum_Subrange is new Enum_With_Gaps range Lit1 .. Lit3; + + type AR is array (Enum_With_Gaps range <>) of Integer; + + procedure Do_Nothing (The_Buffer : in out Buffer; The_AR : in out AR; Hello: in out String); +end Pck; diff --git a/gdb/testsuite/gdb.dap/rust-slices.exp b/gdb/testsuite/gdb.dap/rust-slices.exp new file mode 100644 index 00000000000..96ed5dac8d3 --- /dev/null +++ b/gdb/testsuite/gdb.dap/rust-slices.exp @@ -0,0 +1,119 @@ +# 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 "scopes" and "variables". + +load_lib rust-support.exp +load_lib dap-support.exp + +require allow_dap_tests +require allow_rust_tests +require {can_compile rust} + +standard_testfile .rs + +if {[build_executable ${testfile}.exp $testfile $srcfile {debug rust}] == -1} { + return +} + +if {[dap_launch $testfile] == ""} { + return +} + +set line [gdb_get_line_number "STOP"] +set obj [dap_check_request_and_response "set breakpoint by line number" \ + setBreakpoints \ + [format {o source [o path [%s]] breakpoints [a [o line [i %d]]]} \ + [list s $srcfile] $line]] +set line_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 "stopped at line breakpoint" stopped \ + "body reason" breakpoint \ + "body hitBreakpointIds" $line_bpno + +set bt [lindex [dap_check_request_and_response "backtrace" stackTrace \ + {o threadId [i 1]}] \ + 0] +set frame_id [dict get [lindex [dict get $bt body stackFrames] 0] id] + +set scopes [dap_check_request_and_response "get scopes" scopes \ + [format {o frameId [i %d]} $frame_id]] +set scopes [dict get [lindex $scopes 0] body scopes] + +gdb_assert {[llength $scopes] == 2} "two scopes" + +lassign $scopes scope ignore +gdb_assert {[dict get $scope name] == "Locals"} "scope is locals" +gdb_assert {[dict get $scope presentationHint] == "locals"} \ + "locals presentation hint" +gdb_assert {[dict get $scope namedVariables] == 3} "three vars in scope" + +set num [dict get $scope variablesReference] +set refs [lindex [dap_check_request_and_response "fetch variables" \ + "variables" \ + [format {o variablesReference [i %d]} $num]] \ + 0] + +# Helper to check the contents of a single array-like object. VAR is +# the variable entry. NAME is the name of the variable, pulled out +# for convenience. ARGS are the expected child values. +proc check_array_contents {var name args} { + set len [llength $args] + gdb_assert {[dict get $var indexedVariables] == $len} \ + "check length of $name variable" + + set num [dict get $var variablesReference] + set refs [lindex [dap_check_request_and_response \ + "fetch contents of $name" \ + "variables" \ + [format {o variablesReference [i %d]} $num]] \ + 0] + + foreach subvar [dict get $refs body variables] subvalue $args { + set subname [dict get $subvar name] + gdb_assert {[dict get $subvar value] == $subvalue} \ + "check value of $name entry $subname" + } +} + +foreach var [dict get $refs body variables] { + set name [dict get $var name] + switch $name { + "array" { + check_array_contents $var $name 1 2 3 4 + } + + "slice" { + check_array_contents $var $name 2 + } + + "hello" { + # Note that the expected value looks strange here -- there + # are too many backslashes. This is a TON issue, as the + # JSON looks ok: "value": "\"hello\"". + gdb_assert {[dict get $var value] == "\\\"hello\\\""} \ + "value of hello variable" + } + + default { + fail "unknown variable $name" + } + } +} + +dap_shutdown diff --git a/gdb/testsuite/gdb.dap/rust-slices.rs b/gdb/testsuite/gdb.dap/rust-slices.rs new file mode 100644 index 00000000000..0f06a75cfa7 --- /dev/null +++ b/gdb/testsuite/gdb.dap/rust-slices.rs @@ -0,0 +1,29 @@ +// Copyright (C) 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 . + +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_assignments)] + +fn empty () { +} + +fn main () { + let array = [1,2,3,4]; + let slice = &array[1..2]; + let hello = "hello"; + + empty(); // STOP +} -- 2.40.1