From patchwork Mon Oct 28 18:53:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 99724 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 30F9B3858406 for ; Mon, 28 Oct 2024 18:55:22 +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.129.124]) by sourceware.org (Postfix) with ESMTP id 0F8803858C60 for ; Mon, 28 Oct 2024 18:53:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0F8803858C60 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 0F8803858C60 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730141640; cv=none; b=Sd5HhHLahP/K7AavGg3ovKWG1SAB/d5kr7s71im6u7OjL1FJbtzsYZ0zxuoGXzDS6/lfvE6hCdMs9xU20CmUsurV0MVT5W5eQcNyLX8SyIz/cADYRVqgqB+QpVhBa67bCO1kcytJomROBNJ+NoKyN8TfsiXFD0wvuZXsRxQANGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730141640; c=relaxed/simple; bh=8nwL/DnJIUYk8K8S99F7rSG1fNXRvmOfXEgk/Kfeda4=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=hZmPKfd36Asu1q/ZNv4d2p/KgPTDQ53xr/QoIfA2e+8nVbkVQlWZ1OTPb453HdmVd5oq6Ci1+w9B61QVpfUHmn6z3Uy+n46kQgSVbM/xiM7QzRsEGJPOCFUdSS3pTapMp2I+FEzijIOIAKr4yRLlangoZIbSzSMx04r/nytfxkc= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1730141631; 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=Hsn0ob7/JGuzT5hX4vxETvkJ93sdYWHFPyN61/gNfaMgMtXh/N+MMHmWOuyMTmGJx1IxOS egLVFe3BQ9VY3LYAYFiY5iieHQaNMibXetpMZOn3p3+fXGDXo/3Xb1wUaBhTJBP7n7J6z9 XaiemiXv/z8kBIgYklNEs6VjStkucio= 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-625-bXl06MXVPT-IG4erIr4jHQ-1; Mon, 28 Oct 2024 14:53:50 -0400 X-MC-Unique: bXl06MXVPT-IG4erIr4jHQ-1 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-4316ac69e6dso35672665e9.0 for ; Mon, 28 Oct 2024 11:53:50 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730141629; x=1730746429; 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=tIWNigqIAR6pGP4g6+f3bijqj7tTFmVmhIElsw80TijBViTgEWtYr2ZkbjTorVY6rH hv6ewkXeRVoreaESayhU0A6m25alTk1vwjUycAHHGWlHa9AfTLgwu38dM7OmucnDWuAK BN37ieVD9PchzkNbNN5VaahXpb8TJ3ZExfosVJojV7Mv/GK4jXIu2IplRr3adDHD6xGH U55IL2EzGYfAvSQX/W7EXbm5MLKZpcBdVYbPzMc0dxN/0IC4WpbzkN9kfLHKKnHBDvYi BBkzxwev9+LaWMu4pA5VRmO10p3MLuUeNnrFQzoBlRtb6tVxO2/KAd3X5/XLs9k8IYJS Byhw== X-Gm-Message-State: AOJu0YykD9Bc0h0y324wkxITs4GWGsatJutVeH8iBA3KX5naepn5PDPc fymm5x5gjcQFfoTmatNhTxHDZp1LYFXOSlOfboH6qKQef0op/hv9ZaORYVfeFaXPlTAfBF0Aqsw 7qjOASLslSUEd9xAgeDOFOYT6hL3MeuTsSzokSYjOTfRBDJDdR6tXoCLshxEiQ/naDO+F3hdGEK gyFyIOs41XcDFOXsF8coXs0uoJFxw5loaHG7TNp33wQI0= X-Received: by 2002:a05:600c:46c8:b0:42c:b905:2bf9 with SMTP id 5b1f17b1804b1-4319acb17a9mr92970825e9.16.1730141628642; Mon, 28 Oct 2024 11:53:48 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEaTXBcuXerZj4DjxXOsUykV+s1HJwbHI/rtl0WNkFFkneBZy8hJ+EhiGrxWQfnEq5Ic4qH6Q== X-Received: by 2002:a05:600c:46c8:b0:42c:b905:2bf9 with SMTP id 5b1f17b1804b1-4319acb17a9mr92970615e9.16.1730141628068; Mon, 28 Oct 2024 11:53:48 -0700 (PDT) Received: from localhost (197.209.200.146.dyn.plus.net. [146.200.209.197]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4318b5430edsm149574085e9.2.2024.10.28.11.53.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Oct 2024 11:53:47 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv2 5/5] gdb/freebsd: port core file context parsing to FreeBSD Date: Mon, 28 Oct 2024 18:53:38 +0000 Message-Id: <3de7e75b9b8773f354c1e8e1a89305c6353770c1.1730141493.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_H2, 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 }