From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id WQfROCG/WGrgdQwAWB0awg (envelope-from ) for ; Thu, 16 Jul 2026 07:23:13 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=qc+SztLO; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id E4A381E09E; Thu, 16 Jul 2026 07:23:13 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable autolearn_force=no version=4.0.1 Received: from vm01.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 269D01E099 for ; Thu, 16 Jul 2026 07:23:13 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EFA054BA2E2D for ; Thu, 16 Jul 2026 11:23:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EFA054BA2E2D Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=qc+SztLO Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by sourceware.org (Postfix) with ESMTPS id CC8A24BA5439 for ; Thu, 16 Jul 2026 11:22:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CC8A24BA5439 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org CC8A24BA5439 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::102a ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1784200959; cv=none; b=OyVPPQGmf1QRCWxkGf73sl8354fEWyrco2N1pHwEbJNmC109o0hgSBh8DKR3JT+Z53cYD2gxJzCvb2+/J65hM+IEz52Or44IrqHHDbW9PMq1BgdsTQqitaq8TsXW0kchrgNWgWRC5rKMhuWBPGkxvk0QNkCV5wSj+hbSPlYUc7s= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1784200959; c=relaxed/simple; bh=BOyCRVFlOFMn38GaHCz6VgygM4zKbSzakaXkl9p9Fbs=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=nJ5+3F7rd8c+EDhCg/zjvcb3dizVBEH9g88+q2wgCdpKfomPZ7/GgAVBzru+CrFS/QrF+VP4I9vqmaTWGv4Abmj71l8P4jv71hk7soLagyoI2dIdbYYSB9FJYjllddbqczM3i1FS9eAxED51iS+UslJM6aWRmHS0tn7mj2Q/AT4= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=qc+SztLO DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CC8A24BA5439 Received: by mail-pj1-x102a.google.com with SMTP id 98e67ed59e1d1-38dd55ad76cso285731a91.1 for ; Thu, 16 Jul 2026 04:22:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784200958; x=1784805758; 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:content-type; bh=g/kZW/CZbeEnKJ/H+PD7W+shgypE77zGyv1+AmMCwb4=; b=qc+SztLOIyUcafE7tQJXsYlOWUm69Seot5icGKbeVwdq+t15jY3O/G09I9/AK2mNKe 9iMsLnJ+MYPfAzecV+bHHpdpcyirCYJczx/1Jw43UnKP9q0ShwjX+06sW6XxF4IUFbH5 YIyeef1RUAbRNp/kVDvDUfnIr/iwITNJ38HqxGg/ix/PqdXAzc7SJdbiP7ekiANPWKgV K93UcDzedTjsAWnwr2nUkxtrh+H6V6HaGfPnjRLwftPewXYtJ/k1eSDZxPewSapI9cus e0ODD43cfkU/TlNgwQwjl/yRKLukWAFt2ck1JH/ldUhiJmly8zUGV5nYvaNcPcyB/fnt MnLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784200958; x=1784805758; 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:content-type; bh=g/kZW/CZbeEnKJ/H+PD7W+shgypE77zGyv1+AmMCwb4=; b=iLinEcNV/hw+n/2Y/UHzcN6zEXl+ORDttQ9qDSZS9KKIWW+PQTiz2udpGN0lnAvh+7 8naRQxHlmc1fk4S4d43ihu2M0ED3QbDsm+KBCsjtrPnstc2nw0lIz5QDzDjC3CatWZRN jQL38kefjiR/5DW1mKPDk8p4iNQnzqN3VQU6ebyMkFlsZqb98dTzDWoSazjUPxrt+6bT H+sbmd1DEYLAV9BAKg57bp6z+GlkBGr6VlWdxOY0fTP/gmM0N2eF8d0TJVYBxjDWkge3 b4/VIgpZLAfA+g+XE2sRu2gayFr06He+ZDs7rVY3BO5jbKftxUvxskAmaZbBBjLcT21M s8Ag== X-Gm-Message-State: AOJu0YzUvvC9IEXcdK55Y3hbJEk3v8sGOOiOgxD8r0f+B8+ElOVrgao1 FKnMDymWey9g/e/W1eIj/+RnIU3PiXj49ldw/fhwZoC7ZOcJPIt41loG X-Gm-Gg: AfdE7cmB1sRNE+z42sO2hn/5dDVq7mtXoiu0JjQUMT5A0mKqvOQjWrrl6TsMkeo9edE TQtsE0mGubBBoh3anyQkDPwYiw3qQikdGCo85v5JP7mV2BIvWiy+EjoiDmOPj28nVnDUR2Z06QC RO+BBE4pAtgx8pN8nhx71i8GfOPIx/QiSeKnzYl+xLV+pbuzc3HaiRIPuaUU1tjdanjSEQo5mY8 iOAzg1wArJGvTsRNlKwLUjOJEDF6SQ22FIxC6dpGRZXTt9hcXmP4HgwEyufwIH/NzDpJNH3T7fQ CQ+SCnRyXNQEbsog+QBpqjZBUN0hvk6PAZYh3NMCBKgowPxc8IT3BuwsbiASw/HUuxDVQNqQVtB Jn4H6MgIrTykmTnumTwsFMRUttjdzi/AF16jJKeczV8t8HZjtPKqbRLgl3ZyJ067fkpWFBHm7jg 5EwLVbf+ODaUeqRrIZqzpyoAV9ca56wa948216mNpaIQ== X-Received: by 2002:a17:90a:da86:b0:36b:4d63:4a93 with SMTP id 98e67ed59e1d1-38e3d21fc15mr2034980a91.13.1784200957643; Thu, 16 Jul 2026 04:22:37 -0700 (PDT) Received: from localhost.localdomain ([122.171.18.139]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-3140e6f0dcdsm9631807eec.31.2026.07.16.04.22.34 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 16 Jul 2026 04:22:37 -0700 (PDT) From: Aditya Vidyadhar Kamath To: ulrich.weigand@de.ibm.com, simon.marchi@polymtl.ca, tom@tromey.com Cc: gdb-patches@sourceware.org, Aditya.Kamath1@ibm.com, sangamesh.swamy@in.ibm.com, PRAJWAL.B.MEHENDARKAR@ibm.com Subject: [PATCH v2][RFC] Fix crash in AIX when current working directory is NULL Date: Thu, 16 Jul 2026 16:50:23 +0530 Message-ID: <20260716112022.81520-2-akamath996@gmail.com> X-Mailer: git-send-email 2.43.0 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 From: Aditya Kamath In AIX if we do not have read permission in a current directory we get, gdb ~/gdb_tests/simple_test gdb: warning: error finding working directory: A parameter must be a directory. GNU gdb (GDB) 18.0.50.20260619-git Copyright (C) 2026 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 "powerpc64-ibm-aix7.2.0.0". 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 word" to search for commands related to "word". | +------------------------------------------------------------------------------+ Reading symbols from //gdb_tests/simple_test... terminate called after throwing an instance of 'std::logic_error' what(): basic_string: construction from null is not valid Fatal signal: IOT/Abort trap ----- Backtrace ----- 0x100943f1b gdb_internal_backtrace_1 //home/binutils-gdb/gdb/bt-utils.c:122 0x100944027 _Z22gdb_internal_backtracev //home/binutils-gdb/gdb/bt-utils.c:173 0x10060faa7 handle_fatal_signal //home/binutils-gdb/gdb/event-top.c:1008 0x4fdf ??? --------------------- A fatal error internal to GDB has been detected, further debugging is not possible. GDB will now terminate. This is a bug, please report it. For instructions, see: . ============================= The reason for the same above is that in AIX, the variable current_directory in dwarf2/read.c can be NULL if getcwd () fails during GDB initialisation. When this happens the dwarf2_per_bfd construction initialisation list captured_cwd to NULL resulting in this segmentation fault shown above. There are two reasons this happened: 1: The current working directory got deleted in another terminal. 2: Insufficient permission to read the current directory or its parent/predecessor directory. This patch is a fix to the same. After this fix we get GDB loaded correctly. gdb ~/gdb_tests/simple_test gdb: warning: error finding working directory: A parameter must be a directory. GNU gdb (GDB) 18.0.50.20260619-git Copyright (C) 2026 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 "powerpc64-ibm-aix7.2.0.0". 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 word" to search for commands related to "word". | +------------------------------------------------------------------------------+ Reading symbols from //gdb_tests/simple_test... (gdb) q Also adding a test case for the same. The reason I could not do it in a simple exp file is AIX is protecting the current working directory when I try to delete. It says The requested resource is busy. So I had to write a C code which uses fork () and child will delete the current working directory. Then from parent we exec gdb with a binary having dwarf symbols to reproduce the crash. --- gdb/dwarf2/read.c | 7 ++- gdb/dwarf2/read.h | 7 ++- gdb/testsuite/gdb.base/getcwd-fail-helper.c | 67 +++++++++++++++++++++ gdb/testsuite/gdb.base/getcwd-fail.c | 5 ++ gdb/testsuite/gdb.base/getcwd-fail.exp | 57 ++++++++++++++++++ 5 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 gdb/testsuite/gdb.base/getcwd-fail-helper.c create mode 100644 gdb/testsuite/gdb.base/getcwd-fail.c create mode 100644 gdb/testsuite/gdb.base/getcwd-fail.exp diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 114c608fde3..7ef7e2a8c70 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -859,7 +859,9 @@ dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names, bool can_copy_) : obfd (obfd), can_copy (can_copy_), - captured_cwd (current_directory), + captured_cwd (current_directory != nullptr + ? std::optional (current_directory) + : std::nullopt), captured_debug_dir (debug_file_directory) { if (names == NULL) @@ -6735,7 +6737,8 @@ try_open_dwop_file (dwarf2_per_bfd *per_bfd, const char *file_name, int is_dwp, gdb::unique_xmalloc_ptr absolute_name; desc = openp (search_path, flags, file_name, O_RDONLY | O_BINARY, - &absolute_name, per_bfd->captured_cwd.c_str ()); + &absolute_name, per_bfd->captured_cwd.has_value () ? + per_bfd->captured_cwd->c_str () : nullptr); if (desc < 0) return NULL; diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index 15dd2abf3a1..a7c1861a64d 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -757,8 +757,11 @@ struct dwarf2_per_bfd abstract_to_concrete; /* Current directory, captured at the moment that object this was - created. */ - std::string captured_cwd; + created. If nullopt, the working directory was unavailable + which means getcwd failed either due to directory deletion or + permission issues. So paths should be treated as absolute. */ + std::optional captured_cwd; + /* Captured copy of debug_file_directory. */ std::string captured_debug_dir; }; diff --git a/gdb/testsuite/gdb.base/getcwd-fail-helper.c b/gdb/testsuite/gdb.base/getcwd-fail-helper.c new file mode 100644 index 00000000000..a5e8fe80cbf --- /dev/null +++ b/gdb/testsuite/gdb.base/getcwd-fail-helper.c @@ -0,0 +1,67 @@ +/* Helper to reproduce getcwd failure by deleting cwd via child process. */ +#include +#include +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + const char *temp_dir = argv[1]; + const char *gdb_path = argv[2]; + + /* Create and change to temp directory. */ + if (mkdir (temp_dir, 0755) != 0) + { + perror ("mkdir failed"); + return 1; + } + + if (chdir (temp_dir) != 0) + { + perror ("chdir failed"); + return 1; + } + + /* child deletes directory, parent execs GDB. */ + pid_t pid = fork (); + if (pid < 0) + { + perror ("fork failed"); + return 1; + } + + if (pid == 0) + { + /* cd to / and delete the temp directory. */ + if (chdir ("/") != 0) + exit (1); + + if (rmdir (temp_dir) != 0) + exit (1); + + exit (0); + } + + /* wait for child to delete directory. */ + int status; + waitpid (pid, &status, 0); + + if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) + { + fprintf (stderr, "Failed to delete directory\n"); + return 1; + } + + /* Exec GDB. */ + char **gdb_args = malloc ((argc - 1) * sizeof (char *)); + gdb_args[0] = (char *) gdb_path; + for (int i = 3; i < argc; i++) + gdb_args[i - 2] = argv[i]; + gdb_args[argc - 2] = NULL; + + execv (gdb_path, gdb_args); + perror ("execv failed"); + return 1; +} diff --git a/gdb/testsuite/gdb.base/getcwd-fail.c b/gdb/testsuite/gdb.base/getcwd-fail.c new file mode 100644 index 00000000000..398ec675a07 --- /dev/null +++ b/gdb/testsuite/gdb.base/getcwd-fail.c @@ -0,0 +1,5 @@ +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/getcwd-fail.exp b/gdb/testsuite/gdb.base/getcwd-fail.exp new file mode 100644 index 00000000000..d0041c22c13 --- /dev/null +++ b/gdb/testsuite/gdb.base/getcwd-fail.exp @@ -0,0 +1,57 @@ +# Test GDB when current working directory has been deleted. +# Reproduces crash: getcwd() returns NULL. + +standard_testfile .c + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug}]} { + return -1 +} + +# Compile helper program +set helper_src "${srcdir}/${subdir}/getcwd-fail-helper.c" +set helper_bin [standard_output_file "getcwd-fail-helper"] + +# Debug needs to be there so we can trigger getcwd the dwarf2/read.c code. +if {[gdb_compile $helper_src $helper_bin executable {debug}] != ""} { + untested "failed to compile helper" + return -1 +} + +set temp_dir [standard_output_file "temp_getcwd_test"] +set gdb_path [transform $GDB] + +# The test code creates temp dir, child deletes it, parent execs GDB +set test "gdb in deleted cwd" +set spawn_id [remote_spawn host "$helper_bin $temp_dir $gdb_path -nw -nx -q $binfile"] + +set crashed 0 + +remote_expect host 30 { + -re "terminate called.*logic_error.*basic_string.*construction from null" { + set crashed 1 + exp_continue + } + -re "Fatal signal.*IOT/Abort" { + set crashed 1 + exp_continue + } + -re "$gdb_prompt $" { + if {$crashed} { + fail "$test - crashed" + } else { + pass "$test" + } + } + eof { + if {$crashed} { + fail "$test - crashed with std::logic_error" + } else { + pass "$test" + } + } + timeout { + fail "$test - timeout" + } +} + +catch {file delete -force $temp_dir} -- 2.51.2