From patchwork Tue Oct 29 14:08:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 99773 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 923D13858428 for ; Tue, 29 Oct 2024 14:10:08 +0000 (GMT) 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.133.124]) by sourceware.org (Postfix) with ESMTP id 2AB4D3858C53 for ; Tue, 29 Oct 2024 14:08:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2AB4D3858C53 Authentication-Results: sourceware.org; dmarc=pass (p=none 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 2AB4D3858C53 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=1730210928; cv=none; b=bTBLfvolPWoJVRCIl3XSpk8h96bMEHRGHP339+RBIFVqOXEU2eUNRRytnjCY+BLFtka/QbV4Nnk18IOX9llJXt9aJhtKX4yHwxCRpiydZ4qtYUoLiGOxZY0BVScBQ7ZD5lTi5y8Gc1xnshM6+zJxk4IVIVkyObzq9Js+noyWmj8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730210928; c=relaxed/simple; bh=8nwL/DnJIUYk8K8S99F7rSG1fNXRvmOfXEgk/Kfeda4=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=jUjQ1/43v3Q6B5F51MjyjryNdyzWIRhm8Vl/kpgGLNRvbpREJ9v47xIjeIXLFf1vzo6tBdIcnJ6XKMLl8TkvEzjB3VW/QgbWajCCKvtvlQhAxUe0ybZwY7MvOrQl/QZG8t1d5lno20g03K6GMBpE4sGHMwgTNfJvjhaUvpzOolE= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1730210924; 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=sjKB2P3FjYCHg4RdQPCcYLqaMAKugpKuhqzi4n75Y/o=; b=RNH7JBZyUsu2O7OBxzfxskFFA8WVT8Z0xQoilXDho453O4a3EqDS5xud5ltZXcfOrWMB91 uHTL7Ryjogc1nSr2Eettdk11bHwTZu3kibzOmUZNlSijNbItonkVE6PKBYc5COrNr7FKM5 jBLEWekNCHfMKY2LH5Rl4Fe9teKycwY= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-376-zcVMZPz6MIytrkZnDkwJtQ-1; Tue, 29 Oct 2024 10:08:43 -0400 X-MC-Unique: zcVMZPz6MIytrkZnDkwJtQ-1 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-4315a0f25afso41971605e9.3 for ; Tue, 29 Oct 2024 07:08:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730210921; x=1730815721; 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=sjKB2P3FjYCHg4RdQPCcYLqaMAKugpKuhqzi4n75Y/o=; b=r5PbKYt+kH0d4fiVDRq3Y4UOp0cp9WyvxsQZGHaiPFqVg1BIS1RISwHnDNoa5SNRgv IIN4LSQk+r4O1YTWUNTwuySy9f3q7xP/NlpfKf/PqgG3O5btsFhudXZx0OHidTY4Oph+ y64w9U3G5a8G+i68VFLGM35vHEx/6VfJoopkqNtUvfRYSCneAjtAgfYf9B/VhujjPtgk VLH7EqGE6PlefyBqK1bPeCwQOgJUBw7uXDM6YEzDS+0Zz0OXiXMbep44GYnCi+TQ7XnK A84NkW0Sy6zvEMSwhFFjh7yWw5qqPIC+FQqBlQzsJwgtGtbLw7Va8YTpbmecs0TCIBbv lIqA== X-Gm-Message-State: AOJu0YyJE3Zg8qW8dbk7OBScTgW+MszWYUAKrWa4COPB279KMYoTcmC/ LdcK7LNJ4Qm3TZnTUda7aE1flArUtNyzGi7xfW1x6LSmvyqR2jfqI1wjPY5sURLkMAwKakmEWZ5 qr/Wt6zWvXub7Ck6+NJan2KkbPzSJMlPt1Xa2hw6OG4W7G1c0YY1PPowdEkrAjnrY5shZ0a0OzR y+gWcfNpezaahjh0heE9uIaE2SySlw6aQ1RAs+kDbGvcs= X-Received: by 2002:a05:600c:1390:b0:431:5d4f:73a3 with SMTP id 5b1f17b1804b1-4319acb226amr79286525e9.18.1730210921058; Tue, 29 Oct 2024 07:08:41 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHfee9NWmGJrMrxA+blnkMiZgmVcu6m+1RM9HzaWgeFSZ0s7CDOQAcjIlVFdqrhK/auQTkLrg== X-Received: by 2002:a05:600c:1390:b0:431:5d4f:73a3 with SMTP id 5b1f17b1804b1-4319acb226amr79286245e9.18.1730210920476; Tue, 29 Oct 2024 07:08:40 -0700 (PDT) Received: from localhost (197.209.200.146.dyn.plus.net. [146.200.209.197]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4318b55f484sm175661195e9.13.2024.10.29.07.08.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Oct 2024 07:08:39 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv3 5/5] gdb/freebsd: port core file context parsing to FreeBSD Date: Tue, 29 Oct 2024 14:08:29 +0000 Message-Id: <67f5dee4f3d4e740add402275e89722c7d602b70.1730205615.git.aburgess@redhat.com> 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, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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 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~patchwork=sourceware.org@sourceware.org This commit implements the gdbarch_core_parse_exec_context method for FreeBSD. This is much simpler than for Linux. On FreeBSD, at least the version (13.x) that I have installer, there are additional entries in the auxv vector that point directly to the argument and environment vectors, this makes it trivial to find this information. If these extra auxv entries are not available on earlier FreeBSD, then that's fine. The fallback behaviour will be for GDB to act as it always has up to this point, you'll just not get the extra functionality. Other differences compared to Linux are that FreeBSD has AT_FREEBSD_EXECPATH instead of AT_EXECFN, the AT_FREEBSD_EXECPATH is the full path to the executable. On Linux AT_EXECFN is the command the user typed, so this can be a relative path. This difference is handy as on FreeBSD we don't parse the mapped files from the core file (are they even available?). So having the EXECPATH means we can use that as the absolute path to the executable. However, if the user ran a symlink then AT_FREEBSD_EXECPATH will be the absolute path to the symlink, not to the underlying file. This is probably a good thing, but it does mean there is one case we test on Linux that fails on FreeBSD. On Linux if we create a symlink to an executable, then run the symlink and generate a corefile. Now delete the symlink and load the core file. On Linux GDB will still find (and open) the original executable. This is because we use the mapped file information to find the absolute path to the executable, and the mapped file information only stores the real file names, not symlink names. This is a total edge case, I only added the deleted symlink test originally because I could see that this would work on Linux. Though it is neat that Linux finds this, I don't feel too bad that this fails on FreeBSD. Other than this, everything seems to work on x86-64 FreeBSD (13.4) which is all I have setup right now. I don't see why other architectures wouldn't work too, but I haven't tested them. --- gdb/fbsd-tdep.c | 134 ++++++++++++++++++ .../gdb.base/corefile-exec-context.exp | 2 +- gdb/testsuite/gdb.base/corefile-find-exec.exp | 12 +- 3 files changed, 146 insertions(+), 2 deletions(-) diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c index e97ff52d5bf..804a72c4205 100644 --- a/gdb/fbsd-tdep.c +++ b/gdb/fbsd-tdep.c @@ -33,6 +33,7 @@ #include "elf-bfd.h" #include "fbsd-tdep.h" #include "gcore-elf.h" +#include "arch-utils.h" /* This enum is derived from FreeBSD's . */ @@ -2361,6 +2362,137 @@ fbsd_vdso_range (struct gdbarch *gdbarch, struct mem_range *range) return range->length != 0; } +/* Try to extract the inferior arguments, environment, and executable name + from CBFD. */ + +static core_file_exec_context +fbsd_corefile_parse_exec_context_1 (struct gdbarch *gdbarch, bfd *cbfd) +{ + gdb_assert (gdbarch != nullptr); + + /* If there's no core file loaded then we're done. */ + if (cbfd == nullptr) + return {}; + + int ptr_bytes = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT; + + /* Find the .auxv section in the core file. The BFD library creates this + for us from the AUXV note when the BFD is opened. If the section + can't be found then there's nothing more we can do. */ + struct bfd_section * section = bfd_get_section_by_name (cbfd, ".auxv"); + if (section == nullptr) + return {}; + + /* Grab the contents of the .auxv section. If we can't get the contents + then there's nothing more we can do. */ + bfd_size_type size = bfd_section_size (section); + if (bfd_section_size_insane (cbfd, section)) + return {}; + gdb::byte_vector contents (size); + if (!bfd_get_section_contents (cbfd, section, contents.data (), 0, size)) + return {}; + + /* Read AT_FREEBSD_ARGV, the address of the argument string vector. */ + CORE_ADDR argv_addr; + if (target_auxv_search (contents, current_inferior ()->top_target (), + gdbarch, AT_FREEBSD_ARGV, &argv_addr) != 1) + return {}; + + /* Read AT_FREEBSD_ARGV, the address of the environment string vector. */ + CORE_ADDR envv_addr; + if (target_auxv_search (contents, current_inferior ()->top_target (), + gdbarch, AT_FREEBSD_ENVV, &envv_addr) != 1) + return {}; + + /* Read the AT_EXECPATH string. It's OK if we can't get this + information. */ + gdb::unique_xmalloc_ptr execpath; + CORE_ADDR execpath_string_addr; + if (target_auxv_search (contents, current_inferior ()->top_target (), + gdbarch, AT_FREEBSD_EXECPATH, + &execpath_string_addr) == 1) + execpath = target_read_string (execpath_string_addr, INT_MAX); + + /* The byte order. */ + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + + /* On FreeBSD the command the user ran is found in argv[0]. When we + read the first argument we place it into EXECFN. */ + gdb::unique_xmalloc_ptr execfn; + + /* Read strings from AT_FREEBSD_ARGV until we find a NULL marker. The + first argument is placed into EXECFN as the command name. */ + std::vector> arguments; + CORE_ADDR str_addr; + while ((str_addr + = (CORE_ADDR) read_memory_unsigned_integer (argv_addr, ptr_bytes, + byte_order)) != 0) + { + gdb::unique_xmalloc_ptr str + = target_read_string (str_addr, INT_MAX); + if (str == nullptr) + return {}; + + if (execfn == nullptr) + execfn = std::move (str); + else + arguments.emplace_back (std::move (str)); + + argv_addr += ptr_bytes; + } + + /* Read strings from AT_FREEBSD_ENVV until we find a NULL marker. */ + std::vector> environment; + while ((str_addr + = (uint64_t) read_memory_unsigned_integer (envv_addr, ptr_bytes, + byte_order)) != 0) + { + gdb::unique_xmalloc_ptr str + = target_read_string (str_addr, INT_MAX); + if (str == nullptr) + return {}; + + environment.emplace_back (std::move (str)); + envv_addr += ptr_bytes; + } + + return core_file_exec_context (std::move (execfn), + std::move (execpath), + std::move (arguments), + std::move (environment)); +} + +/* See elf-corelow.h. */ + +static core_file_exec_context +fbsd_corefile_parse_exec_context (struct gdbarch *gdbarch, bfd *cbfd) +{ + /* Catch and discard memory errors. + + If the core file format is not as we expect then we can easily trigger + a memory error while parsing the core file. We don't want this to + prevent the user from opening the core file; the information provided + by this function is helpful, but not critical, debugging can continue + without it. Instead just give a warning and return an empty context + object. */ + try + { + return fbsd_corefile_parse_exec_context_1 (gdbarch, cbfd); + } + catch (const gdb_exception_error &ex) + { + if (ex.error == MEMORY_ERROR) + { + warning + (_("failed to parse execution context from corefile: %s"), + ex.message->c_str ()); + return {}; + } + else + throw; + } +} + /* Return the address range of the vDSO for the current inferior. */ static int @@ -2404,4 +2536,6 @@ fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* `catch syscall' */ set_xml_syscall_file_name (gdbarch, "syscalls/freebsd.xml"); set_gdbarch_get_syscall_number (gdbarch, fbsd_get_syscall_number); + set_gdbarch_core_parse_exec_context (gdbarch, + fbsd_corefile_parse_exec_context); } diff --git a/gdb/testsuite/gdb.base/corefile-exec-context.exp b/gdb/testsuite/gdb.base/corefile-exec-context.exp index ac97754fe71..73e13e60d75 100644 --- a/gdb/testsuite/gdb.base/corefile-exec-context.exp +++ b/gdb/testsuite/gdb.base/corefile-exec-context.exp @@ -18,7 +18,7 @@ # # Currently, only Linux supports reading full executable and arguments # from a core file. -require {istarget *-linux*} +require {is_any_target "*-*-linux*" "*-*-freebsd*"} standard_testfile diff --git a/gdb/testsuite/gdb.base/corefile-find-exec.exp b/gdb/testsuite/gdb.base/corefile-find-exec.exp index 40324c1f01c..07e660d85e8 100644 --- a/gdb/testsuite/gdb.base/corefile-find-exec.exp +++ b/gdb/testsuite/gdb.base/corefile-find-exec.exp @@ -18,7 +18,7 @@ # # Currently, only Linux supports reading full executable and arguments # from a core file. -require {istarget *-linux*} +require {is_any_target "*-*-linux*" "*-*-freebsd*"} standard_testfile @@ -115,6 +115,16 @@ with_test_prefix "absolute path" { remote_exec build "rm -f $symlink" + # FreeBSD is unable to figure out the actual underlying mapped + # file, so when the symlink is deleted, FeeeBSD is stuck. + # + # There is some argument that this shouldn't even be a + # failure, the user ran the symlink, and if the symlink is + # gone, should we really expect GDB to find the underlying + # file? That we can on Linux is really just a quirk of how + # the mapped file list works. + setup_xfail "*-*-freebsd*" + test_load $corefile_3 $binfile $symlink }