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 [216.205.24.124]) by sourceware.org (Postfix) with ESMTP id 2D09938515DC for ; Fri, 30 Apr 2021 07:21:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 2D09938515DC Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-447-rywMw9n5OL6DMUcc7fmRjQ-1; Fri, 30 Apr 2021 03:21:16 -0400 X-MC-Unique: rywMw9n5OL6DMUcc7fmRjQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0C7E01898296 for ; Fri, 30 Apr 2021 07:21:16 +0000 (UTC) Received: from oldenburg.str.redhat.com (ovpn-115-124.ams2.redhat.com [10.36.115.124]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 623FF100EB3D for ; Fri, 30 Apr 2021 07:21:15 +0000 (UTC) From: Florian Weimer To: libc-stable@sourceware.org Subject: [PATCH COMMITTED 2.33] nptl: Check for compatible GDB in nptl/tst-pthread-gdb-attach Date: Fri, 30 Apr 2021 09:21:27 +0200 Message-ID: <87h7jo9r0o.fsf@oldenburg.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain X-Spam-Status: No, score=-12.5 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_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-stable@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-stable mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 30 Apr 2021 07:21:20 -0000 Also do not clear the subprocess environment, in case running GDB needs certain environment variables. (cherry picked from commit f553dc066071a4465321fbc122bed8a75afd996b) --- nptl/tst-pthread-gdb-attach.c | 78 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/nptl/tst-pthread-gdb-attach.c b/nptl/tst-pthread-gdb-attach.c index 0603ad844d..901a120034 100644 --- a/nptl/tst-pthread-gdb-attach.c +++ b/nptl/tst-pthread-gdb-attach.c @@ -20,8 +20,12 @@ whether libthread_db can be loaded, and that access to thread-local variables works. */ +#include #include +#include +#include #include +#include #include #include #include @@ -35,6 +39,49 @@ the thread. */ __thread volatile int altered_by_debugger; +/* Common prefix between 32-bit and 64-bit ELF. */ +struct elf_prefix +{ + unsigned char e_ident[EI_NIDENT]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; +}; +_Static_assert (sizeof (struct elf_prefix) == EI_NIDENT + 8, + "padding in struct elf_prefix"); + +/* Reads the ELF header from PATH. Returns true if the header can be + read, false if the file is too short. */ +static bool +read_elf_header (const char *path, struct elf_prefix *elf) +{ + int fd = xopen (path, O_RDONLY, 0); + bool result = read (fd, elf, sizeof (*elf)) == sizeof (*elf); + xclose (fd); + return result; +} + +/* Searches for "gdb" alongside the path variable. See execvpe. */ +static char * +find_gdb (void) +{ + const char *path = getenv ("PATH"); + if (path == NULL) + return NULL; + while (true) + { + const char *colon = strchrnul (path, ':'); + char *candidate = xasprintf ("%.*s/gdb", (int) (colon - path), path); + if (access (candidate, X_OK) == 0) + return candidate; + free (candidate); + if (*colon == '\0') + break; + path = colon + 1; + } + return NULL; +} + /* Writes the GDB script to run the test to PATH. */ static void write_gdbscript (const char *path, int tested_pid) @@ -105,6 +152,33 @@ in_subprocess (void) static int do_test (void) { + char *gdb_path = find_gdb (); + if (gdb_path == NULL) + FAIL_UNSUPPORTED ("gdb command not found in PATH: %s", getenv ("PATH")); + + /* Check that libthread_db is compatible with the gdb architecture + because gdb loads it via dlopen. */ + { + char *threaddb_path = xasprintf ("%s/nptl_db/libthread_db.so", + support_objdir_root); + struct elf_prefix elf_threaddb; + TEST_VERIFY_EXIT (read_elf_header (threaddb_path, &elf_threaddb)); + struct elf_prefix elf_gdb; + /* If the ELF header cannot be read or "gdb" is not an ELF file, + assume this is a wrapper script that can run. */ + if (read_elf_header (gdb_path, &elf_gdb) + && memcmp (&elf_gdb, ELFMAG, SELFMAG) == 0) + { + if (elf_gdb.e_ident[EI_CLASS] != elf_threaddb.e_ident[EI_CLASS]) + FAIL_UNSUPPORTED ("GDB at %s has wrong class", gdb_path); + if (elf_gdb.e_ident[EI_DATA] != elf_threaddb.e_ident[EI_DATA]) + FAIL_UNSUPPORTED ("GDB at %s has wrong data", gdb_path); + if (elf_gdb.e_machine != elf_threaddb.e_machine) + FAIL_UNSUPPORTED ("GDB at %s has wrong machine", gdb_path); + } + free (threaddb_path); + } + pid_t tested_pid = xfork (); if (tested_pid == 0) in_subprocess (); @@ -117,9 +191,8 @@ do_test (void) pid_t gdb_pid = xfork (); if (gdb_pid == 0) { - clearenv (); xdup2 (STDOUT_FILENO, STDERR_FILENO); - execlp ("gdb", "gdb", "-nx", "-batch", "-x", gdbscript, NULL); + execl (gdb_path, "gdb", "-nx", "-batch", "-x", gdbscript, NULL); if (errno == ENOENT) _exit (EXIT_UNSUPPORTED); else @@ -137,6 +210,7 @@ do_test (void) free (tested_pid_string); free (gdbscript); + free (gdb_path); return 0; }