From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id XUcQCNl8F2maIgIAWB0awg (envelope-from ) for ; Fri, 14 Nov 2025 14:02:49 -0500 Authentication-Results: simark.ca; dkim=pass (2048-bit key; secure) header.d=adacore.com header.i=@adacore.com header.a=rsa-sha256 header.s=google header.b=AWBUCneB; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 0C6A11E04C; Fri, 14 Nov 2025 14:02:49 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-2.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id C11661E04C for ; Fri, 14 Nov 2025 14:02:44 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 279753858C53 for ; Fri, 14 Nov 2025 19:02:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 279753858C53 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, secure) header.d=adacore.com header.i=@adacore.com header.a=rsa-sha256 header.s=google header.b=AWBUCneB Received: from mail-io1-xd2c.google.com (mail-io1-xd2c.google.com [IPv6:2607:f8b0:4864:20::d2c]) by sourceware.org (Postfix) with ESMTPS id 7844E3858D20 for ; Fri, 14 Nov 2025 19:02:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7844E3858D20 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 7844E3858D20 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::d2c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1763146926; cv=none; b=KzzUZozypB5GBhD/PXIP9EldR4Uv0YqEccdnlwE6T8r5ACwbmUkyH66TTr3ZUDiDoforI3lKou1frdrwgYViER1VedGLKM0GwQgEcjPuqCo2Z0W1f4yHn/VC5vJvlWfZb5D2hf9Hy50LQC6eWYUbsERAFCpwdFULyl9Z0bsNuH0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1763146926; c=relaxed/simple; bh=doRHh11g3oiBhZFUey7gt+i4x3ueL8AhwwZZELteFzg=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=l//3JRRa1g5owsMLU2CBM0f9A6Fry38i3fGSjbzRTFfXFQsQq3anjYiTkm1wouwLoHAj7S125Bn9YXuEXKIx/auh9WnhjSDGCrhl/Lzf1fw4ylbz/0tqaNyT8OeGjWaLWvr4z+u0iuxRjwWYFNgEPOpYCPrVxMbjsMGSj76b8Eo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7844E3858D20 Received: by mail-io1-xd2c.google.com with SMTP id ca18e2360f4ac-94861514a5cso187800739f.1 for ; Fri, 14 Nov 2025 11:02:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore.com; s=google; t=1763146925; x=1763751725; darn=sourceware.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=1WLj9ifScograwRAzAf6B4T0Lnch7uVbaiAnPpjX3H0=; b=AWBUCneB0Mh3TzTeF8TA7dw6dJTFOLIvLZ9Z37bpWpNLFi+lHDtGN5TOXsdFTvy3ld SFRokUXBXajD9tNc3GaAChyFBfZvACqF5ZsK8Xuzuxi+0ImnMCKm8a2qtWyRsFg1hQez sU6JgcVmE0IvTJV2RV95vqroNXX+ZD+2YxI2Bvdc4bnNJjMDKRSOGgP1gjvmEcET1RrQ oLx35eJcEB0lxxjNHuKfWU0JhBQIUztAEaFFWcfZSGult4eoXaMjOXxnAueC5PinJe3U KWnsZmOspdy/tUy/qUe8CsunbplC6pZtYEaganIMF5OXFN4ywmazYDx/r5Pbrn64JJzJ hRWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763146925; x=1763751725; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=1WLj9ifScograwRAzAf6B4T0Lnch7uVbaiAnPpjX3H0=; b=parrIu5sMph3CTQULSzeA9dNVhf7L3SqckG/NeeDfQdKu/GdK9k8Qli+2YcAwhDok7 Sr1mh2V07SpjDgHmwXuARPjbUrhaxH/XuRCTMI3WfSq5IWLK3z1kMzM/DqTo22yYvSnz Cg3rkTQHGZEgu1SNwWFtkIBeBRPfS603zyyQah95DXh6rmKEn4p1qXj+/3YT482nEUZj 0yT9mDaLk1ck9ZRMEQ+XX5mJ8AV7pIdUDjuAtuEG8V9jfJjfDRBlI1ss0txsBaYbXw+u Ikt2KBSXdwJX3/zrLe30/HwOgLrfBxgCL1lJ6g5ZERHbCNZSCoW3ok/OIRD9tZ6G2aeB sO8g== X-Gm-Message-State: AOJu0Yw67E8oDCqcUEA9qdqSb8kUa887kWP3dQUcPVeTncEOrLLBOpEs SaIZq5x9dIQRS6zrrgUteo73FC97VfkSMuyd8melfhPy0gmdPGejo/2BMRYzVLhiGITvnY/kfYN Dq44= X-Gm-Gg: ASbGncvxAcAJ97bkrbijP3yYFdtdogFhAhpvp7dzW/TuoMxODFOLpMrKb7oOcMwjvIi 4BuVb5N5O7IlKrUSR4md7cc348BV/CrDPaMJWzbMkBGWp5UA42zoLvcHw1oh5ZXAV343PTUa1YF WdWJsFU+kW4vcon+4bnCGrj2DlV0l6sYvwxcyQnsYk3QpqSYSMpvqvBK+frAodLhHS0dz/n4hoa BaBMh4hvh4mV3rhlRQSWpeNNUkEJ3gbmN+nknVp56yVrTykJTs/iLUPi+FxTLhpu+Roi3FwZ89O lO24pW95JPY6KrZuELyQJEIiOYaY2C5FuUE3Nin9+GlZ/upX9JtlVNqwKwMuwzRF/icDYMH/Cu9 xusukjDTOnN9jIjMTXLtZvUdl9Dcp6Xbgeq/BZCAsvDHY+1ZDyE4l/pXSx6RYcqiZXNCMT2RGzR y8mtLzE07BKW/umnntAmtV5BCKmDw8TeVudw== X-Google-Smtp-Source: AGHT+IHc9aE4owB73yHybZWgt8P6KClY/sHehWwWEDGNhfVpSDGPClXIFMnMMIgTirPnVkdip5CpdA== X-Received: by 2002:a05:6e02:12ea:b0:433:7818:d1c8 with SMTP id e9e14a558f8ab-4348c95d814mr67740355ab.32.1763146925440; Fri, 14 Nov 2025 11:02:05 -0800 (PST) Received: from bapiya (97-122-120-205.hlrn.qwest.net. [97.122.120.205]) by smtp.gmail.com with ESMTPSA id e9e14a558f8ab-434838c24a1sm31474805ab.15.2025.11.14.11.02.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Nov 2025 11:02:05 -0800 (PST) From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH] Do not crash on recursive pointer types Date: Fri, 14 Nov 2025 12:02:03 -0700 Message-ID: <20251114190203.2369142-1-tromey@adacore.com> X-Mailer: git-send-email 2.51.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org In Ada, it's possible to create a recursive pointer type, or two mutually recursive pointer types. gdb will crash when reading the DWARF for these. These types aren't actually useful, and so are unlikely to appear in real code. Still, gdb shouldn't crash. This patch handles this case by noticing recursive pointer types and representing them as pointer-to-void. --- gdb/dwarf2/read.c | 84 ++++++++++++++++++- gdb/testsuite/gdb.ada/recursive-access.exp | 31 +++++++ .../gdb.ada/recursive-access/pack.ads | 26 ++++++ .../gdb.ada/recursive-access/prog.adb | 23 +++++ 4 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.ada/recursive-access.exp create mode 100644 gdb/testsuite/gdb.ada/recursive-access/pack.ads create mode 100644 gdb/testsuite/gdb.ada/recursive-access/prog.adb diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 29f100b7638..f31f0b30858 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -916,6 +916,9 @@ static const char *dwarf2_physname (const char *name, struct die_info *die, static struct die_info *dwarf2_extension (struct die_info *die, struct dwarf2_cu **); +static die_info *follow_die_offset (const section_and_offset &target, + dwarf2_cu **ref_cu); + static struct die_info *follow_die_ref_or_sig (struct die_info *, const struct attribute *, struct dwarf2_cu **); @@ -12725,6 +12728,75 @@ namespace_name (struct die_info *die, int *is_anonymous, struct dwarf2_cu *cu) return name; } +/* A convenience structure that holds a CU and a DIE. */ + +struct cu_die_pair +{ + die_info *die; + dwarf2_cu *cu; + + /* Return true if this object holds a valid DIE. */ + bool valid () const + { + return die != nullptr; + } + + /* Compare two cu_die_pair objects. */ + bool operator!= (const cu_die_pair &other) const + { + return die != other.die || cu != other.cu; + } +}; + +/* Follow the DW_AT_type reference, if any, from ORIG. The return + value will be valid only when DW_AT_type exists. In other cases, + including when the incoming ORIG is not valid, an invalid + cu_die_pair is returned. */ + +static cu_die_pair +follow_type (cu_die_pair orig) +{ + /* This simplifies the caller a little. */ + if (!orig.valid ()) + return {}; + + attribute *type_attr = dwarf2_attr (orig.die, DW_AT_type, orig.cu); + if (type_attr == nullptr || !type_attr->form_is_ref ()) + return {}; + + cu_die_pair result = orig; + sect_offset sect_off = type_attr->get_ref_die_offset (); + const dwarf2_section_info §ion = get_section_for_ref (*type_attr, + orig.cu); + result.die = follow_die_offset ({ §ion, sect_off }, &result.cu); + + /* Note that we do not check for DW_TAG_pointer_type here. GNAT, at + least, will emit recursive pointers that "indirect" via typedefs, + so checkpoint purely for pointer types would not find these. */ + return result; +} + +/* Return true if DIE is a self-referential pointer type; false + otherwise. CU is the origin of DIE. */ + +static bool +is_recursive_pointer (die_info *die, dwarf2_cu *cu) +{ + cu_die_pair tortoise { die, cu }; + gdb_assert (tortoise.valid ()); + cu_die_pair hare = follow_type (tortoise); + + while (tortoise != hare) + { + tortoise = follow_type (tortoise); + hare = follow_type (follow_type (hare)); + if (!tortoise.valid () || !hare.valid ()) + return false; + } + + return true; +} + /* Extract all information from a DW_TAG_pointer_type DIE and add to the user defined type vector. */ @@ -12739,7 +12811,17 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu) int byte_size; struct type *target_type; - target_type = die_type (die, cu); + /* In Ada, it's possible to create a self-referential pointer type. + These aren't useful, but nevertheless we take care to avoid a gdb + crash in this situation. Instead just turn these into a + pointer-to-void. */ + if (is_recursive_pointer (die, cu)) + { + type_allocator alloc (cu->per_objfile->objfile, cu->lang ()); + target_type = alloc.new_type (TYPE_CODE_VOID, 0, nullptr); + } + else + target_type = die_type (die, cu); /* The die_type call above may have already set the type for this DIE. */ type = get_die_type (die, cu); diff --git a/gdb/testsuite/gdb.ada/recursive-access.exp b/gdb/testsuite/gdb.ada/recursive-access.exp new file mode 100644 index 00000000000..833be936a10 --- /dev/null +++ b/gdb/testsuite/gdb.ada/recursive-access.exp @@ -0,0 +1,31 @@ +# Copyright 2025 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 that recursive access types do not cause a crash. + +load_lib "ada.exp" + +require allow_ada_tests + +standard_ada_testfile prog + +if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} { + return +} + +clean_restart ${testfile} + +# The bug was that even reading these types caused a crash. +gdb_test_no_output "maint expand-symtabs" diff --git a/gdb/testsuite/gdb.ada/recursive-access/pack.ads b/gdb/testsuite/gdb.ada/recursive-access/pack.ads new file mode 100644 index 00000000000..fe06edc56e5 --- /dev/null +++ b/gdb/testsuite/gdb.ada/recursive-access/pack.ads @@ -0,0 +1,26 @@ +-- Copyright 2025 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 Pack is + -- With GCC, this makes a directly self-referential pointer type. + type Direct; + subtype Sub is Direct; + type Direct is access Sub; + + -- With GCC, this makes two mutually recursive pointer types. + type Second; + type First is access Second; + type Second is access First; +end Pack; diff --git a/gdb/testsuite/gdb.ada/recursive-access/prog.adb b/gdb/testsuite/gdb.ada/recursive-access/prog.adb new file mode 100644 index 00000000000..f740343feb8 --- /dev/null +++ b/gdb/testsuite/gdb.ada/recursive-access/prog.adb @@ -0,0 +1,23 @@ +-- Copyright 2025 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 Pack; use Pack; + +procedure Prog is + X : Direct := null; + Y : Second := new First; +begin + null; +end Prog; base-commit: 24e9fdc6ef2c27fab8416737d4ed8129accdc551 -- 2.51.1