From patchwork Thu Jun 1 09:27:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 70440 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 47CCA385771D for ; Thu, 1 Jun 2023 09:29:02 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 47CCA385771D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1685611742; bh=8i0MQeYWdJkz2adWvsDAHblLrdWKqrmnbwWV2FHf2UM=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=GNPD8xDUCal8uXvIsi0bZRs3jGcR9OahqV7zZEz7w4j9xaiQ7ln81VZF2iYPtLoWM TQaB/8A7HWELoC73Bl7PNdbPKjzhPUsRQWjDAuTRIvZS+LjJoxyMiu3voU8Cgw0gma onY30LlK8USoJ80h0CMa7StJSSE6D9+nTvz1NHsI= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 04F643858C41 for ; Thu, 1 Jun 2023 09:28:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 04F643858C41 Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-425-Qc3XZzw7PqOeHWVqCMZYzQ-1; Thu, 01 Jun 2023 05:28:03 -0400 X-MC-Unique: Qc3XZzw7PqOeHWVqCMZYzQ-1 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-30793c16c78so832496f8f.3 for ; Thu, 01 Jun 2023 02:28:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685611682; x=1688203682; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8i0MQeYWdJkz2adWvsDAHblLrdWKqrmnbwWV2FHf2UM=; b=cvEcadUEF8OGbIkMVtOR4MAnUPpVm3byBU+U2fdRvWKpEcJZ22Trpkv9dZu9UWvo76 KcGHkvtNXO+NXBgLV0KDkUw8o5v+DDYBsbVacu6ZQqkdy0wyM7rfyPVGT7UF5TXlrpum e6WI+SA7XqKMwv4eHXQgYoiM43D59nXG3ybyJDu7Xi5E2CFcmhQEwKsy7rZgOpUyzJyn NJtdIfdP3Ox21guIdSkUXicDm4FQAr081NKA3E4gLSvVc2gVTjTvFtBlctGMggXYseF1 dyoVRCDPdxKxz87q/gP4y1m4xtKPPe8Dt3WVhln3TQPlUvl0Uj6/FS77MGgai3WApYtd zKnA== X-Gm-Message-State: AC+VfDy+Du280yerLZpgCXQYu8ohtx4SFemMMWmVYuMdYtsMjQ5b+JZ2 AVVByzG01q5XirHiHHeL5rnwaNiATs7kVsv3QLyj0T8CkaKK2lCcsCAC0kg3lYQKoKeI15buSud 0iX4jBnCB3ceG6Wn50J2epR2LfMARb8JnE4HDiRDLPyZlXHJmq7vqsWCCc0W+LgGiK1eYBKSeeM /Wi1DA8Q== X-Received: by 2002:adf:f507:0:b0:30a:e9a9:a4f8 with SMTP id q7-20020adff507000000b0030ae9a9a4f8mr1831589wro.38.1685611682102; Thu, 01 Jun 2023 02:28:02 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4/mJJY1Dbp8WtvXMWJrnByWU5AAbpfIniZfW1WmKX3txpLaMEF5PK+A+mdilwb7mkVIf/FxA== X-Received: by 2002:adf:f507:0:b0:30a:e9a9:a4f8 with SMTP id q7-20020adff507000000b0030ae9a9a4f8mr1831574wro.38.1685611681740; Thu, 01 Jun 2023 02:28:01 -0700 (PDT) Received: from localhost (11.72.115.87.dyn.plus.net. [87.115.72.11]) by smtp.gmail.com with ESMTPSA id h17-20020a5d4fd1000000b003095bd71159sm9770306wrw.7.2023.06.01.02.28.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 02:28:01 -0700 (PDT) To: gdb-patches@sourceware.org Cc: Simon Marchi , Andrew Burgess Subject: [PATCH 1/4] gdb: fix printf of wchar_t early in a gdb session Date: Thu, 1 Jun 2023 10:27:50 +0100 Message-Id: X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, 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 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-Patchwork-Original-From: Andrew Burgess via Gdb-patches From: Andrew Burgess Reply-To: Andrew Burgess Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Given this test program: #include const wchar_t wide_str[] = L"wide string"; int main (void) { return 0; } I observed this GDB behaviour: $ gdb -q /tmp/printf-wchar_t Reading symbols from /tmp/printf-wchar_t... (gdb) start Temporary breakpoint 1 at 0x40110a: file /tmp/printf-wchar_t.c, line 8. Starting program: /tmp/printf-wchar_t Temporary breakpoint 1, main () at /tmp/printf-wchar_t.c:8 25 return 0; (gdb) printf "%ls\n", wide_str (gdb) Notice that the printf results in a blank line rather than the expected 'wide string' output. I tracked the problem down to printf_wide_c_string (in printcmd.c), in this function we do this: struct type *wctype = lookup_typename (current_language, "wchar_t", NULL, 0); int wcwidth = wctype->length (); the problem here is that 'wchar_t' is a typedef. If we look at the comment on type::length() we see this: /* Note that if thistype is a TYPEDEF type, you have to call check_typedef. But check_typedef does set the TYPE_LENGTH of the TYPEDEF type, so you only have to call check_typedef once. Since value::allocate calls check_typedef, X->type ()->length () is safe. */ What this means is that after calling lookup_typename we should call check_typedef in order to ensure that the length of the typedef has been setup correctly. We are not doing this in printf_wide_c_string, and so wcwidth is incorrectly calculated as 0. This is what leads GDB to print an empty string. We can see in c_string_operation::evaluate (in c-lang.c) an example of calling check_typedef specifically to fix this exact issue. Initially I did fix this problem by adding a check_typedef call into printf_wide_c_string, but then I figured why not move the check_typedef call up into lookup_typename itself, that feels like it should be harmless when looking up a non-typedef type, but will avoid bugs like this when looking up a typedef. So that's what I did. I can then remove the extra check_typedef call from c-lang.c, I don't see any other places where we had extra check_typedef calls. This doesn't mean we definitely had bugs -- so long as we never checked the length, or, if we knew that check_typedef had already been called, then we would be fine. I don't see any test regressions after this change, and my new test case is now passing. Reviewed-By: Tom Tromey --- gdb/c-lang.c | 3 --- gdb/gdbtypes.c | 11 ++++++---- gdb/gdbtypes.h | 14 ++++++++++-- gdb/testsuite/gdb.base/printf-wchar_t.c | 26 +++++++++++++++++++++++ gdb/testsuite/gdb.base/printf-wchar_t.exp | 26 +++++++++++++++++++++++ 5 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 gdb/testsuite/gdb.base/printf-wchar_t.c create mode 100644 gdb/testsuite/gdb.base/printf-wchar_t.exp diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 484f81e455b..677e76ee71b 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -615,9 +615,6 @@ c_string_operation::evaluate (struct type *expect_type, internal_error (_("unhandled c_string_type")); } - /* Ensure TYPE_LENGTH is valid for TYPE. */ - check_typedef (type); - /* If the caller expects an array of some integral type, satisfy them. If something odder is expected, rely on the caller to cast. */ diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 10e585066f7..9eecf357152 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1648,9 +1648,7 @@ type_name_or_error (struct type *type) objfile ? objfile_name (objfile) : ""); } -/* Lookup a typedef or primitive type named NAME, visible in lexical - block BLOCK. If NOERR is nonzero, return zero if NAME is not - suitably defined. */ +/* See gdbtypes.h. */ struct type * lookup_typename (const struct language_defn *language, @@ -1662,7 +1660,12 @@ lookup_typename (const struct language_defn *language, sym = lookup_symbol_in_language (name, block, VAR_DOMAIN, language->la_language, NULL).symbol; if (sym != NULL && sym->aclass () == LOC_TYPEDEF) - return sym->type (); + { + struct type *type = sym->type (); + /* Ensure the length of TYPE is valid. */ + check_typedef (type); + return type; + } if (noerr) return NULL; diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 319a7731bca..f56de4544b5 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -2586,8 +2586,18 @@ extern void check_stub_method_group (struct type *, int); extern char *gdb_mangle_name (struct type *, int, int); -extern struct type *lookup_typename (const struct language_defn *, - const char *, const struct block *, int); +/* Lookup a typedef or primitive type named NAME, visible in lexical block + BLOCK. If NOERR is nonzero, return zero if NAME is not suitably + defined. + + If this function finds a suitable type then check_typedef is called on + the type, this ensures that if the type being returned is a typedef + then the length of the type will be correct. The original typedef will + still be returned, not the result of calling check_typedef. */ + +extern struct type *lookup_typename (const struct language_defn *language, + const char *name, + const struct block *block, int noerr); extern struct type *lookup_template_type (const char *, struct type *, const struct block *); diff --git a/gdb/testsuite/gdb.base/printf-wchar_t.c b/gdb/testsuite/gdb.base/printf-wchar_t.c new file mode 100644 index 00000000000..4d13fd3c961 --- /dev/null +++ b/gdb/testsuite/gdb.base/printf-wchar_t.c @@ -0,0 +1,26 @@ +/* This testcase is part of GDB, the GNU debugger. + + 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 . */ + +#include + +const wchar_t wide_str[] = L"wide string"; + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/printf-wchar_t.exp b/gdb/testsuite/gdb.base/printf-wchar_t.exp new file mode 100644 index 00000000000..85c6edf292c --- /dev/null +++ b/gdb/testsuite/gdb.base/printf-wchar_t.exp @@ -0,0 +1,26 @@ +# 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 . + +standard_testfile + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} { + return -1 +} + +if {![runto_main]} { + return -1 +} + +gdb_test {printf "%ls\n", wide_str} "^wide string"