From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 6A25F3858C53 for ; Sat, 26 Oct 2024 11:11:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6A25F3858C53 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 6A25F3858C53 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=1729941104; cv=none; b=f28k2KRQFp+Qt8pDe3Zz0cdgfgwpZBVCCC6RQxsKkFytvnif156wxjb6yDMK3awnmOy1zUC+9m5dlt2D2s/qRoDHO3ZXwGPxiOYUOkad5WmPCLQuKhtedBq9M6tUn3uFtKDqIR4B3cheQj1F8hkm+btD+3z3oqwNyYJuO86BRAQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1729941104; c=relaxed/simple; bh=8nwL/DnJIUYk8K8S99F7rSG1fNXRvmOfXEgk/Kfeda4=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=uieEE1LXo/DSQj7dOZHmFIYyyRTWCPwIu9Q1XSlrErG3yrl18P2qYgEmWqouB4xWrkd5VhDwWXhKgY7zqCcMr+3XsMw8ulPWTnhCoUaqa1dQY4Sut4CcOR/XUDk15ft+nuTQlZOkJr4f+DK4WmuAaUrEsCiFVwCiMxoyN0TO1jU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1729941102; 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=didvSUUOiZ1t2XihVF7rNhGQmQ1vi2qopjnenuuUX6ryWYh6j/43AkUxl81d8C0TDcbs2R r4IZaygcF2LmLTgQqeAo3qQPkAG4PUfFdgel/0HwCz+0FBqUAskhUmzEkqemmzfmgZdG8I ydrIpggVQl3DW9RU4rRk31JIx4q8Xyw= Received: from mail-ej1-f69.google.com (mail-ej1-f69.google.com [209.85.218.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-561-TT-B8P7oNueiq5i_b3pwtA-1; Sat, 26 Oct 2024 07:11:40 -0400 X-MC-Unique: TT-B8P7oNueiq5i_b3pwtA-1 Received: by mail-ej1-f69.google.com with SMTP id a640c23a62f3a-a9adb271de7so145813666b.0 for ; Sat, 26 Oct 2024 04:11:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729941099; x=1730545899; 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=mtq/0kes1GUWvOjgNuKOiPWrJsQSj/fvp31n6WzLrh28gwAO8/P5pgnKznJoMXz2M2 qcqwYzGVZBYkJJX8qasI4AvxET5KQ8q3APXjD+ISJTA3JyNy24HQseq0ZyiS7wmgdu/C m2oxz/CQbUrVKWi/yCkS3VbCj496f1pnXg/yHAM0CVOazFN5v32SACssVdzdKxIvdAUI DC9oBwAw39d8Feip4j45lZZfhHMOmCR00LZ6a8i9vzXtYpirK0gWqh1BIX3WbQytUPfm eq4ZUkCuGCkP0lchVsicGxbW6k1mP9HtGtrx7IDbwatNdGpQjzG5wDvOLHK4A9ys7pzg Qi9A== X-Gm-Message-State: AOJu0YyUzkQUe1p9SjbWv7bFQ+oYkU/2G5xbtM0lTy0FPvgw5EMrRfCs eAGDF1hgAaOEbo8o+yYrQ6XtZMTJOuGTyBvbg1CXgIsLn/elibNzF3vrsq0pnC5BmF+2nJMPo2j ZgQP65Lfnt6CC/O8aYRQ9eO12G0qRTQCx1FiySpKgoenFADOz7Lo0ZDJMROxsK08uFXrVIBsc93 O2OHsvsS642ys35t1fYfALBsRM9/BFSL5d3tq4s8zR/Ec= X-Received: by 2002:a17:907:7f07:b0:a9a:17f5:79a8 with SMTP id a640c23a62f3a-a9de5d6fad3mr175842466b.13.1729941098882; Sat, 26 Oct 2024 04:11:38 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHHnlg0wtNHN+4kfrTYYw4vQ/xCgAzmdvhj4Mo2ji9tPAc17nzCUokYfFcSDk3acuHCo5RtLg== X-Received: by 2002:a17:907:7f07:b0:a9a:17f5:79a8 with SMTP id a640c23a62f3a-a9de5d6fad3mr175839466b.13.1729941098317; Sat, 26 Oct 2024 04:11:38 -0700 (PDT) Received: from localhost (92.40.184.80.threembb.co.uk. [92.40.184.80]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a9b3a0887besm164689766b.207.2024.10.26.04.11.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 26 Oct 2024 04:11:36 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCH 5/5] gdb/freebsd: port core file context parsing to FreeBSD Date: Sat, 26 Oct 2024 12:11:23 +0100 Message-Id: <42b05b015d58461c6f1b994eddf1cfc35ec9b3c1.1729940787.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 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-11.2 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,RCVD_IN_SBL_CSS,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 List-Id: 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 } -- 2.25.4