From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 6zKgC3M4M2ksYBsAWB0awg (envelope-from ) for ; Fri, 05 Dec 2025 14:54:27 -0500 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=IJWI5M7C; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 1EB3B1E08D; Fri, 05 Dec 2025 14:54:27 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-1.1 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=no autolearn_force=no version=4.0.1 Received: from sourceware.org (vm01.sourceware.org [38.145.34.32]) (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 124B11E08D for ; Fri, 05 Dec 2025 14:54:26 -0500 (EST) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8C6FE4D1085B for ; Fri, 5 Dec 2025 19:54:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8C6FE4D1085B Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=IJWI5M7C Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id B6C274CD2006 for ; Fri, 5 Dec 2025 19:53:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B6C274CD2006 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B6C274CD2006 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1764964408; cv=none; b=dAsZw7vqOyvtlvWcqpeOZ9s4GzrXwTJYFi2IgYUutl/wkWXWdU/0XgAQKqeqfBrajaAeUEtz9Cemod/oX0yVC0SbN755/ymf0XMUOHeHfj9CiG3TgSvryNBjz1vnBl+5CBmRJG8q5w7f7u+AHjxvHHnJq1Sorj+m4Xwi9NVa7OA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1764964408; c=relaxed/simple; bh=EJXC+vI5SiR9/8NZCLLTaXx40G+9mBgLlm3HEOu9zhg=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=dcf2pB+WLgrTFeFNJQ0Og2a6liLrHJOOZi/Nh6NUxUhTJNt/ip1zjTuOw0BsGt8AYAnWy2m6iSDha3Ob++0R9z0sPT73vlPQ1LamEKN2dNvtHuqfFLntuq6vR0HNoZixUFpeFcB/geUtd4qfBToyMV+0aDLX3q0Zx9oh5ipfvOw= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B6C274CD2006 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764964408; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=E2Ele6H2NKCMzgpiIgk2/nhZOcxku8JRdsLMdOTSgQA=; b=IJWI5M7Cf6gpr2NAN/jbZdQmjbn5+91BA+bODxrF5un5sZul+F5u0PdJ6c4eITSgTfCWLK O7oDiqis/vzSmDGhTXIhdTB/8SVFSFkfEtzaofJtP2uWaNQk0iNGsPUnNnFxgFvveVvGf8 K43kcpPei5lx+bzHiv6ugAwjsn+z03w= Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-204-rIPHA0dTMpqaV9VWP5ggsg-1; Fri, 05 Dec 2025 14:53:26 -0500 X-MC-Unique: rIPHA0dTMpqaV9VWP5ggsg-1 X-Mimecast-MFC-AGG-ID: rIPHA0dTMpqaV9VWP5ggsg_1764964405 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-42e2973a812so1493047f8f.0 for ; Fri, 05 Dec 2025 11:53:26 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764964405; x=1765569205; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=E2Ele6H2NKCMzgpiIgk2/nhZOcxku8JRdsLMdOTSgQA=; b=jeI1wC2UalTSaMXSoQOx6x92aL4bTTyD2pwIdAz7aw/vdM1JfXSUhZ0xdQWybZvGYR hIKT/FaiMI1vODXXvh6DOZ/XWhFR0pXTDTqN2eGMiIJWZcsT0fxNGo3iCHNb/KIRIZWp 2uMgAjbvyJXjPZtAgFjNhwdlInTBLUwWWuP+xx+zKiuFCGAHnfxf+xuFDm1rEVfWCMgX 1YVla3QBV10u4he5dltsVESGtZAkxRidNBmZ8RoZsHU4LMSldEb7W5bMGjSVqqN6Wor3 XSpe24K4iWap1slTFFVtPF1LkXrubP6nOugkXChRezheHbcWFaJIBCXkQ5h31WGQcyBW uYfw== X-Gm-Message-State: AOJu0YycbaLfqRWiiTbdy8/SQPaeVK+AB4W1qEbzq8DdaVHPMhC9vzJS uiAI7hd3DjcTLMHUUxQY3xzVnZH4OcVXPbd6eZaEIBoSO4Vq7QrxNfmIBfNKAP/HPZWGz7EFalG qqVk+cpOSAtAMW+/iaZv07MdlgLX9FRTbTy6h3lnJUGsBx7T5ym/E82ebim2l5pCOWhJ6oDp81E r0s4E8UDOMh3wNakqmliSsFst2nmTJR+EsSaYEIywEin6wBdk= X-Gm-Gg: ASbGncvQLtcr/AQqE7V0DtDT19DBdHs9fPGlowHQc9q+I038VEdQyO379gF+pPd/4vz hDL3VJJ2l9DasFAVszwSx3B9YNtXWZVA3j95oilX68QtWZHhpKjOSsQTQtC81Cm+6uoAc2sY9k2 gViN833W9RzAdd5k3gG5MF6kU7KNlXj9wl5aMSlfc+WLq75emJcpZVz8UUsL3AdQHvE7SCgx/7W tGWL3gOpbZkdNxPGSQ8npBIj8IgCOUk0aHqlkCx6hrmpsOlwhK03KKfTU3D+Bpmx2mLpttshsv6 iEf1PlmsSv85KXMGY5jkz2MCuJ/WddA3eDV9G+WzDYDBcpd/dS2bOXbQ+oSIWh6KmQ7I7rpmvPQ bM3+G X-Received: by 2002:a05:6000:220b:b0:42f:7686:5693 with SMTP id ffacd0b85a97d-42f89eeb233mr495741f8f.16.1764964404943; Fri, 05 Dec 2025 11:53:24 -0800 (PST) X-Google-Smtp-Source: AGHT+IEkP4pUXw+UwFeJCkMOlgxmmGi5JPvdBY+CVJnhNccZT09/MIV5yIC7qsglm15iC1Ahn+QXHA== X-Received: by 2002:a05:6000:220b:b0:42f:7686:5693 with SMTP id ffacd0b85a97d-42f89eeb233mr495678f8f.16.1764964404252; Fri, 05 Dec 2025 11:53:24 -0800 (PST) Received: from localhost ([31.111.84.207]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42f7cbff320sm10607499f8f.18.2025.12.05.11.53.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Dec 2025 11:53:23 -0800 (PST) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess , Guinevere Larsen Subject: [PATCHv3 2/3] gdb: fix crashes and weird output from new boxed hint text Date: Fri, 5 Dec 2025 19:53:16 +0000 Message-ID: <34f4ef88d31ad2274f50d3f6f35437e814183713.1764964133.git.aburgess@redhat.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 7-osmJLPkfkTKM3JdVi-vf-l1T5UhTm2dLAUtPKCIRY_1764964405 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=UTF-8 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 After the commit: commit f6df8aa48f120b78f0670b429f8a3363020a47dc Date: Mon Sep 15 11:56:17 2025 -0300 gdb: Make startup message more user friendly I noticed, that when I start GDB with a file on the command line, I was seeing some stray '..'. Like this: $ gdb -nw -nh /tmp/hello.x GNU gdb (GDB) 18.0.50.20251202-git Copyright (C) 2025 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-pc-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: . ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ Find the GDB manual online at: ┃ ┃ http://www.gnu.org/software/gdb/documentation/. ┃ ┃ For help, type "help". ┃ ┃ Type "apropos " to search for commands related to ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ .. Reading symbols from /tmp/hello.x... Notice the '..' after the boxed hint text, that's what I'm complaining about. Also, notice that the last line within the box is missing its period. Before the above commit the last line would appear like this when no file was loaded: Type "apropos " to search for commands related to . And like this when a file was being loaded: Type "apropos " to search for commands related to ... The extra '..' are added to show that a file is being loaded, and that this might take some time. But we have the 'Reading symbols from ...' text to indicate this now, so I think the extra '..' are redundant. Lets just drop them. This will leave just a single period at the end of the sentence. The above commit unfortunately, didn't include any tests, so I thought I'd write some to cover this fix.... and that uncovered a bug where the box around the startup hints could be corrupted: $ gdb -eiex 'set width 50' -nw -nh GNU gdb (GDB) 18.0.50.20251202-git Copyright (C) 2025 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-pc-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: . ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ Find the GDB manual online at: ┃ ┃ http://www.gnu.org/software/gdb/documentation/. ┃ ┃ For help, type "help". ┃ ┃ Type "apropos " to ┃ ┃ search for commands related to ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ (gdb) This was caused by a mistake on the line where we choose whether to box or not. The line is currently: if (width - 3 <= docs_url.length ()) There are two problems here, the '3' should be '4'. The box adds 4 characters '| ' and ' |'. But also, the WIDTH can be very small, less than 4 even, which means that the subtraction can underflow, wrapping around and giving a very large value. I plan to rewrite the line to: if (width < docs_url.length () + 1 + 4) The '+ 1' accounts for the period at the end of the URL line (which was previously handled by the '<=', and the '+ 4' accounts for the box borders. By making it a '+ 4' on the URL, rather than '- 4' from the width, we avoid underflow. This is fine so long as the URL to our documentation doesn't approach UINT_MAX in length. Which I hope it never does. I've added a couple of asserts to print_gdb_hints to reflect things that must be true. The first is that get_chars_per_line never returns 0. And later on, I assert that 'width > 4' in a place where we are about to do 'width - 4'. If the assert triggers then underflow would have occurred. Reviewed-By: Guinevere Larsen --- gdb/main.c | 5 +- gdb/testsuite/gdb.base/startup-hints.exp | 144 +++++++++++++++++++++++ gdb/top.c | 21 +++- 3 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 gdb/testsuite/gdb.base/startup-hints.exp diff --git a/gdb/main.c b/gdb/main.c index 0fa2b0ecbe4..e4da715134b 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -1197,13 +1197,10 @@ captured_main_1 (struct captured_main_args *context) if (!quiet) { - /* Print all the junk at the top, with trailing "..." if we are - about to read a symbol file (possibly slowly). */ + /* Print the version, copyright information, and hint text. */ print_gdb_version (gdb_stdout, true); gdb_printf ("\n"); print_gdb_hints (gdb_stdout); - if (symarg) - gdb_printf (".."); gdb_printf ("\n"); gdb_flush (gdb_stdout); /* Force to screen during slow operations. */ diff --git a/gdb/testsuite/gdb.base/startup-hints.exp b/gdb/testsuite/gdb.base/startup-hints.exp new file mode 100644 index 00000000000..0addf3769a2 --- /dev/null +++ b/gdb/testsuite/gdb.base/startup-hints.exp @@ -0,0 +1,144 @@ +# 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 the start up hint text. Check that it is boxed (or not) +# correctly. + +# Test assumes host == build. +require {!is_remote host} + +# Just use a simple empty 'main' function. +standard_testfile main.c + +if { [build_executable "build" $testfile $srcfile] != 0 } { + return +} + +# Return a single regexp string for the startup hint text when the +# terminal width is WIDTH. For narrow terminals GDB will just print +# the hint text. For wider terminals GDB places the hint into a box. +proc build_hint_re { width } { + # GDB imposes a maximum width of 80. + if { $width > 80 || $width == 0 } { + set width 80 + } + + if { $width > 50 } { + + # These lines are shorter than 50 characters, and so are never + # wrapped. + set msg { + {Find the GDB manual online at:} + {http://www.gnu.org/software/gdb/documentation/.} + {For help, type "help".} + } + + # The final line is wrapped based on the terminal width. + if { $width > 66 } { + lappend msg {Type "apropos " to search for commands related to .} + } elseif { $width > 58 } { + lappend msg {Type "apropos " to search for commands related to} {.} + } elseif { $width > 55 } { + lappend msg {Type "apropos " to search for commands related} {to .} + } elseif { $width > 47 } { + lappend msg {Type "apropos " to search for commands} { related to .} + } + + # Place the lines into a box, padding with whitespace so that + # the sides are correctly aligned. + set top_bottom "+[string repeat "-" [expr $width - 2]]+" + set lines [list $top_bottom] + foreach m $msg { + set space_count [expr $width - 4 - [string length $m]] + set spaces [string repeat " " $space_count] + lappend lines "| $m$spaces |" + } + lappend lines $top_bottom + } else { + # We tell GDB that the terminal width is WIDTH, but in reality + # the actual terminal width is unlimited. As such, GDB drops + # the box around the hint, but doesn't inject any additional + # newlines (it assumes the terminal will break the lines for + # us). This is why, despite the narrow terminal, we expect + # each line without any line breaks. + set lines {{Find the GDB manual online at:} \ + {http://www.gnu.org/software/gdb/documentation/.} \ + {For help, type "help".} \ + {Type "apropos " to search for commands related to .}} + } + + # Add blank line before and after current lines. + set lines [linsert $lines 0 ""] + lappend lines "" + + # Convert every line to a regexp. Also log the expected output + # for debugging. + set lines_re {} + verbose -log -- "Expected message format:" + foreach l $lines { + verbose -log -- "$l" + lappend lines_re [string_to_regexp $l] + } + + # Join the regexp together. + return [multi_line {*}$lines_re] +} + +# Tell GDB to start with a terminal width of WIDTH, then start GDB. +# Check that the hint text is formatted correctly. +proc_with_prefix test_for_hint_with_width { width load_exec } { + global GDBFLAGS + + save_vars { GDBFLAGS } { + append GDBFLAGS " -eiex \"set width $width\" -eiex \"set height 0\"" + if { $load_exec } { + append GDBFLAGS " \"$::binfile\"" + } + gdb_exit + gdb_spawn + } + + set hint_re [build_hint_re $width] + + if { $load_exec } { + append hint_re "\r\nReading symbols from [string_to_regexp $::binfile]\\.\\.\\." + } + + gdb_test "" $hint_re \ + "check for hint with width $width" +} + +save_vars { INTERNAL_GDBFLAGS } { + set INTERNAL_GDBFLAGS [string map {"-q" ""} $INTERNAL_GDBFLAGS] + + foreach_with_prefix load_exec { false true } { + + # Width 0 actually means unlimited. The other small sizes + # check that GDB doesn't trigger undefined behaviour by trying + # to create strings with a negative length. + for { set width 0 } { $width <= 5 } { incr width } { + test_for_hint_with_width $width $load_exec + } + + # These widths cover the point where we transition from using + # an unboxed hint to a boxed hint. + for { set width 45 } { $width <= 55 } { incr width } { + test_for_hint_with_width $width $load_exec + } + + # Very large widths are treated like a width of 80. + test_for_hint_with_width 100 $load_exec + } +} diff --git a/gdb/top.c b/gdb/top.c index 1aefe74b394..10366f98df1 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -1421,6 +1421,8 @@ print_gdb_hints (struct ui_file *stream) if (80 < width) width = 80; + gdb_assert (width > 0); + std::string docs_url = "http://www.gnu.org/software/gdb/documentation/"; std::array styled_msg { string_file (true), @@ -1435,20 +1437,29 @@ print_gdb_hints (struct ui_file *stream) gdb_printf (&styled_msg[2], _("For help, type \"%ps\"."), styled_string (command_style.style (), "help")); gdb_printf (&styled_msg[3], - _("Type \"%ps\" to search for commands related to "), + _("Type \"%ps\" to search for commands related to ."), styled_string (command_style.style (), "apropos ")); /* If there isn't enough space to display the longest URL in a boxed - style, use the simple styling of a singular visual break. The longest - URL is used because the other messages may be broken into multiple - lines, but URLs can't. */ - if (width - 3 <= docs_url.length ()) + style, then don't use the box, the terminal will break the output + where needed. The longest URL is used because the other messages may + be broken into multiple lines, but URLs can't. + + The ' + 1' after the URL accounts for the period that is placed after + the URL. + + The '+ 4' accounts for the box and inner white space. We add the 4 to + the string length rather than subtract from the width as the width + could be less than 4, and we want to avoid wrap around. */ + if (width < docs_url.length () + 1 + 4) { for (string_file &msg : styled_msg) gdb_printf (stream, "%s\n", msg.c_str ()); } else { + gdb_assert (width > 4); + std::string sep (width - 2, '-'); if (emojis_ok ()) -- 2.47.1